boost::filesystem added

git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@8328 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
Lars Gullik Bjønnes 2004-01-08 17:47:56 +00:00
parent 2f1d525ee1
commit 4768220752
17 changed files with 1968 additions and 4 deletions

View File

@ -1,11 +1,15 @@
2004-01-08 Lars Gullik Bjonnes <larsbj@gullik.net>
* configure.ac (AC_CONFIG_FILES): add boost::filesystem Makefiles.
2003-12-15 Ronald Florence <ron@18james.com>
* README.MacOSX: updated for 1.4.0cvs
2003-11-18 Angus Leeming <leeming@lyx.org>
* autogen.sh: accept autoconf 2.58 as a supported version.
2003-10-24 André Pönitz <poenitz@gmx.net>
* lyxfunc.C:
@ -19,7 +23,7 @@
* INSTALL: remove a comment about --with-included-string
* configure.ac: remove the configure are
--with-included-string
--with-included-string
2003-09-21 Lars Gullik Bjønnes <larsbj@gullik.net>

View File

@ -1,3 +1,7 @@
2004-01-08 Lars Gullik Bjonnes <larsbj@gullik.net>
* add boost::filesystem.
2003-10-23 Lars Gullik Bjønnes <larsbj@gullik.net>
* libs/regex/src/cpp_regex_traits.cpp (seekpos): use correct

View File

@ -0,0 +1,38 @@
// boost/filesystem/convenience.hpp ----------------------------------------//
// (C) Copyright Beman Dawes, 2002
// (C) Copyright Vladimir Prus, 2002
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
// See http://www.boost.org/libs/filesystem for documentation.
//----------------------------------------------------------------------------//
#ifndef BOOST_FILESYSTEM_CONVENIENCE_HPP
#define BOOST_FILESYSTEM_CONVENIENCE_HPP
#include <boost/filesystem/path.hpp>
#include <boost/filesystem/operations.hpp>
namespace boost
{
namespace filesystem
{
// create_directories (contributed by Vladimir Prus) -----------------------//
/** Creates directory 'ph' and all necessary parent directories.
@post exists(directory_ph) && is_directory(directory_ph) && is_empty(directory_ph)
*/
void create_directories(const path& ph);
} // namespace filesystem
} // namespace boost
#endif // BOOST_FILESYSTEM_CONVENIENCE_HPP

View File

@ -0,0 +1,105 @@
// boost/filesystem/exception.hpp ------------------------------------------//
// < ----------------------------------------------------------------------- >
// < Copyright © 2002 Beman Dawes >
// < Copyright © 2001 Dietmar Kühl, All Rights Reserved >
// < >
// < Permission to use, copy, modify, distribute and sell this >
// < software for any purpose is hereby granted without fee, provided >
// < that the above copyright notice appears in all copies and that >
// < both that copyright notice and this permission notice appear in >
// < supporting documentation. The authors make no representations about >
// < the suitability of this software for any purpose. It is provided >
// < "as is" without express or implied warranty. >
// < ----------------------------------------------------------------------- >
// See http://www.boost.org/libs/filesystem for documentation.
//----------------------------------------------------------------------------//
#ifndef BOOST_FILESYSTEM_EXCEPTION_HPP
#define BOOST_FILESYSTEM_EXCEPTION_HPP
#include <boost/filesystem/path.hpp>
#include <string>
#include <stdexcept>
//----------------------------------------------------------------------------//
namespace boost
{
namespace filesystem
{
namespace detail
{
int system_error_code(); // artifact of POSIX and WINDOWS error reporting
}
enum error_code
{
no_error = 0,
system_error, // system generated error; if possible, is translated
// to one of the more specific errors below.
other_error, // library generated error
security_error, // includes access rights, permissions failures
read_only_error,
io_error,
path_error,
not_found_error,
not_directory_error,
busy_error, // implies trying again might succeed
already_exists_error,
not_empty_error,
is_directory_error,
out_of_space_error,
out_of_memory_error,
out_of_resource_error
};
class filesystem_error : public std::runtime_error
{
public:
filesystem_error(
const std::string & who,
const std::string & message ); // assumed to be error_code::other_error
filesystem_error(
const std::string & who,
const path & path1,
const std::string & message ); // assumed to be error_code::other_error
filesystem_error(
const std::string & who,
const path & path1,
int sys_err_code );
filesystem_error(
const std::string & who,
const path & path1,
const path & path2,
int sys_err_code );
~filesystem_error() throw();
int native_error() const { return m_sys_err; }
// Note: a value of 0 implies a library (rather than system) error
error_code error() const { return m_err; }
const std::string & who() const; // name of who throwing exception
const path & path1() const; // argument 1 to who; may be empty()
const path & path2() const; // argument 2 to who; may be empty()
private:
int m_sys_err;
error_code m_err;
std::string m_who;
path m_path1;
path m_path2;
};
} // namespace filesystem
} // namespace boost
#endif // BOOST_FILESYSTEM_EXCEPTION_HPP

View File

@ -0,0 +1,124 @@
// boost/filesystem/fstream.hpp --------------------------------------------//
// (C) Copyright Beman Dawes 2002. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
// See http://www.boost.org/libs/filesystem for documentation.
//----------------------------------------------------------------------------//
#ifndef BOOST_FILESYSTEM_FSTREAM_HPP
#define BOOST_FILESYSTEM_FSTREAM_HPP
#include <boost/filesystem/path.hpp>
#include <iosfwd>
#include <fstream>
namespace boost
{
namespace filesystem
{
template < class charT, class traits = std::char_traits<charT> >
class basic_filebuf : public std::basic_filebuf<charT,traits>
{
public:
virtual ~basic_filebuf() {}
#if !defined(BOOST_MSVC) || BOOST_MSVC > 1200 // VC++ 6.0 can't handle this
std::basic_filebuf<charT,traits> * open( const path & file_ph,
std::ios_base::openmode mode )
{
return std::basic_filebuf<charT,traits>::open(
file_ph.native_file_string().c_str(), mode );
}
#endif
};
typedef basic_filebuf<char> filebuf;
# ifndef BOOST_NO_STD_WSTRING
typedef basic_filebuf<wchar_t> wfilebuf;
# endif
template < class charT, class traits = std::char_traits<charT> >
class basic_ifstream : public std::basic_ifstream<charT,traits>
{
public:
basic_ifstream() {}
explicit basic_ifstream( const path & file_ph,
std::ios_base::openmode mode = std::ios_base::in )
: std::basic_ifstream<charT,traits>(
file_ph.native_file_string().c_str(), mode ) {}
virtual ~basic_ifstream() {}
#if !defined(BOOST_MSVC) || BOOST_MSVC > 1200 // VC++ 6.0 can't handle this
void open( const path & file_ph,
std::ios_base::openmode mode = std::ios_base::in )
{
std::basic_ifstream<charT,traits>::open(
file_ph.native_file_string().c_str(), mode );
}
#endif
};
typedef basic_ifstream<char> ifstream;
# ifndef BOOST_NO_STD_WSTRING
typedef basic_ifstream<wchar_t> wifstream;
# endif
template < class charT, class traits = std::char_traits<charT> >
class basic_ofstream : public std::basic_ofstream<charT,traits>
{
public:
basic_ofstream() {}
explicit basic_ofstream( const path & file_ph,
std::ios_base::openmode mode = std::ios_base::out )
: std::basic_ofstream<charT,traits>(
file_ph.native_file_string().c_str(), mode ) {}
virtual ~basic_ofstream() {}
#if !defined(BOOST_MSVC) || BOOST_MSVC > 1200 // VC++ 6.0 can't handle this
void open( const path & file_ph,
std::ios_base::openmode mode = std::ios_base::out )
{
std::basic_ofstream<charT,traits>::open(
file_ph.native_file_string().c_str(), mode );
}
#endif
};
typedef basic_ofstream<char> ofstream;
# ifndef BOOST_NO_STD_WSTRING
typedef basic_ofstream<wchar_t> wofstream;
# endif
template < class charT, class traits = std::char_traits<charT> >
class basic_fstream : public std::basic_fstream<charT,traits>
{
public:
basic_fstream() {}
explicit basic_fstream( const path & file_ph,
std::ios_base::openmode mode = std::ios_base::in|std::ios_base::out )
: std::basic_fstream<charT,traits>(
file_ph.native_file_string().c_str(), mode ) {}
virtual ~basic_fstream() {}
#if !defined(BOOST_MSVC) || BOOST_MSVC > 1200 // VC++ 6.0 can't handle this
void open( const path & file_ph,
std::ios_base::openmode mode = std::ios_base::in|std::ios_base::out )
{
std::basic_fstream<charT,traits>::open(
file_ph.native_file_string().c_str(), mode );
}
#endif
};
typedef basic_fstream<char> fstream;
# ifndef BOOST_NO_STD_WSTRING
typedef basic_fstream<wchar_t> wfstream;
# endif
} // namespace filesystem
} // namespace boost
#endif // BOOST_FILESYSTEM_FSTREAM_HPP

View File

@ -0,0 +1,121 @@
// boost/filesystem/directory.hpp ------------------------------------------//
// < ----------------------------------------------------------------------- >
// < Copyright © 2002 Beman Dawes. >
// < Copyright © 2002 Jan Langer. >
// < Copyright © 2001 Dietmar Kühl, All Rights Reserved >
// < >
// < Permission to use, copy, modify, distribute and sell this >
// < software for any purpose is hereby granted without fee, provided >
// < that the above copyright notice appears in all copies and that >
// < both that copyright notice and this permission notice appear in >
// < supporting documentation. The authors make no representations about >
// < the suitability of this software for any purpose. It is provided >
// < "as is" without express or implied warranty. >
// < ----------------------------------------------------------------------- >
// See http://www.boost.org/libs/filesystem for documentation.
//----------------------------------------------------------------------------//
#ifndef BOOST_FILESYSTEM_DIRECTORY_HPP
#define BOOST_FILESYSTEM_DIRECTORY_HPP
#include <boost/config.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/iterator.hpp>
#include <string>
//----------------------------------------------------------------------------//
namespace boost
{
namespace filesystem
{
// query functions ---------------------------------------------------------//
bool exists( const path & ph );
bool is_directory( const path & ph );
// VC++ 7.0 and earlier has a serious namespace bug that causes a clash
// between boost::filesystem::is_empty and the unrelated type trait
// boost::is_empty. The workaround for those who must use broken versions
// of VC++ is to use the function _is_empty. All others should use the
// correct is_empty name.
bool _is_empty( const path & ph ); // deprecated
# if !defined( BOOST_MSVC ) || BOOST_MSVC > 1300
inline bool is_empty( const path & ph ) { return _is_empty( ph ); }
# endif
// operations --------------------------------------------------------------//
void create_directory( const path & directory_ph );
bool remove( const path & ph );
unsigned long remove_all( const path & ph );
void rename( const path & from_path,
const path & to_path );
void copy_file( const path & from_file_ph,
const path & to_file_ph );
path current_path();
const path & initial_path();
path system_complete( const path & ph );
path complete( const path & ph, const path & base = initial_path() );
// directory_iterator ------------------------------------------------------//
class directory_iterator
: public boost::iterator< std::input_iterator_tag,
path, std::ptrdiff_t, const path *, const path & >
{
private:
typedef directory_iterator self;
public:
directory_iterator(); // creates the "end" iterator
explicit directory_iterator( const path & p );
reference operator*() const { return m_deref(); }
pointer operator->() const { return &m_deref(); }
self & operator++() { m_inc(); return *this; }
friend bool operator==( const self & x, const self & y )
{ return x.m_imp == y.m_imp; }
friend bool operator!=( const self & x, const self & y )
{ return !(x.m_imp == y.m_imp); }
struct path_proxy // allows *i++ to work, as required by std
{
path pv;
explicit path_proxy( const path & p ) : pv(p) {}
path operator*() const { return pv; }
};
path_proxy operator++(int)
{
path_proxy pp( m_deref() );
++*this;
return pp;
}
private:
class dir_itr_imp;
// shared_ptr provides shallow-copy semantics required for InputIterators
typedef boost::shared_ptr< dir_itr_imp > m_imp_ptr;
m_imp_ptr m_imp;
reference m_deref() const;
void m_inc();
};
} // namespace filesystem
} // namespace boost
#endif // BOOST_FILESYSTEM_DIRECTORY_HPP

View File

@ -0,0 +1,213 @@
// boost/filesystem/path.hpp -----------------------------------------------//
// (C) Copyright Beman Dawes 2002. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
// See http://www.boost.org/libs/filesystem for documentation.
//----------------------------------------------------------------------------//
#ifndef BOOST_FILESYSTEM_PATH_HPP
#define BOOST_FILESYSTEM_PATH_HPP
#include <boost/iterator_adaptors.hpp>
#include <string>
#include <cassert>
//----------------------------------------------------------------------------//
namespace boost
{
namespace filesystem
{
class path;
namespace detail
{
struct path_itr_imp
{
std::string name; // cache current element.
const path * path_ptr; // path being iterated over.
std::string::size_type pos; // position of name in
// path_ptr->string(). The
// end() iterator is indicated by
// pos == path_ptr->string().size()
const std::string & operator*() const { return name; }
void operator++();
void operator--();
bool operator==( const path_itr_imp & rhs ) const
{ return path_ptr == rhs.path_ptr && pos == rhs.pos; }
};
} // detail
enum path_format { native }; // ugly enough to discourage use
// except when actually needed
// path -------------------------------------------------------------------//
class path
{
public:
// compiler generates copy constructor, copy assignment, and destructor
path(){}
path( const std::string & src );
path( const char * src );
path( const std::string & src, path_format );
path( const char * src, path_format );
// append operations:
path & operator /=( const path & rhs );
path operator /( const path & rhs ) const
{ return path( *this ) /= rhs; }
// conversion functions:
const std::string & string() const { return m_path; }
std::string native_file_string() const;
std::string native_directory_string() const;
// decomposition functions:
path root_path() const;
std::string root_name() const;
std::string root_directory() const;
path relative_path() const;
std::string leaf() const;
path branch_path() const;
// query functions:
bool empty() const { return m_path.empty(); } // name consistent with std containers
bool is_complete() const;
bool has_root_path() const;
bool has_root_name() const;
bool has_root_directory() const;
bool has_relative_path() const;
bool has_leaf() const { return !m_path.empty(); }
bool has_branch_path() const;
// iteration over the names in the path:
typedef boost::iterator_adaptor<
detail::path_itr_imp,
boost::default_iterator_policies,
std::string,
const std::string &,
const std::string *,
std::bidirectional_iterator_tag,
std::ptrdiff_t
> iterator;
iterator begin() const;
iterator end() const
{
iterator itr;
itr.base().path_ptr = this;
itr.base().pos = m_path.size();
return itr;
}
private:
// Note: This is an implementation for POSIX and Windows, where there
// are only minor differences between generic and system-specific
// constructor input formats. Private members might be quite different
// in other implementations, particularly where there were wide
// differences between generic and system-specific argument formats,
// or between native_file_string() and native_directory_string() formats.
std::string m_path;
friend class directory_iterator;
friend struct boost::filesystem::detail::path_itr_imp;
enum source_context { generic, platform, nocheck };
void m_path_append( const std::string & src,
source_context context = generic );
public: // should be private, but friend functions don't work for me
void m_replace_leaf( const char * new_leaf );
};
// path non-member functions ---------------------------------------------//
inline path operator / ( const char * lhs, const path & rhs )
{ return path( lhs ) /= rhs; }
inline path operator / ( const std::string & lhs, const path & rhs )
{ return path( lhs ) /= rhs; }
// error checking --------------------------------------------------------//
// TODO: write a program that probes valid file and directory names. Ask
// Boost people to report results from many operating systems. Use results
// to adjust generic_name().
// generic_name() is extremely permissive; its intent is not to ensure
// general portablity, but rather to detect names so trouble-prone that
// they likely represent coding errors or gross misconceptions.
//
// Any characters are allowed except:
//
// Those characters < ' ', including '\0'. These are the so-called
// control characters, in both ASCII (and its decendents) and EBCDIC.
// Hard to imagine how these could be useful in a generic path name.
//
// < > : " / \ | * ? These have special meaning to enough operating
// systems that use in a generic name would be a serious problem.
//
// The names "." and ".." are not allowed.
// An empty name (null string) is not allowed.
// Names beginning or ending with spaces are not allowed.
//
bool generic_name( const std::string & name );
// posix_name() is based on POSIX (IEEE Std 1003.1-2001)
// "Portable Filename Character Set" rules.
// http://www.opengroup.org/onlinepubs/007904975/basedefs/xbd_chap03.html
//
// That character set only allows 0-9, a-z, A-Z, '.', '_', and '-'.
// Note that such names are also portable to other popular operating
// systems, such as Windows.
//
bool posix_name( const std::string & name );
const path & check_posix_leaf( const path & ph );
// Throws: if !posix_name( ph.leaf() )
// Returns: ph
// Note: Although useful in its own right, check_posix_leaf() also serves
// as an example. A user might provide similar functions; behavior might
// be to assert or warn rather than throw. A user provided function
// could also check the entire path instead of just the leaf; a leaf
// check is often, but not always, the required behavior.
// Rationale: For the "const path &" rather than "void" return is to
// allow (and encourage portability checking) uses like:
// create_directory( check_posix_leaf( "foo" ) );
// While there is some chance of misuse (by passing through a reference
// to a temporary), the benefits outweigh the costs.
// For Boost, we often tighten name restrictions for maximum portability:
//
// * The portable POSIX character restrictions, plus
// * Maximum name length 31 characters (for Classic Mac OS).
// * Lowercase only (so code written on case-insensitive platforms like
// Windows works properly when used on case-sensitive systems like
// POSIX.
// * Directory names do not contain '.', as this is not a valid character
// for directory names on some systems.
//
// TODO: provide some check_boost_xxx functions once error handling
// approach ratified.
bool boost_file_name( const std::string & name );
bool boost_directory_name( const std::string & name );
} // namespace filesystem
} // namespace boost
#endif // BOOST_FILESYSTEM_PATH_HPP

View File

@ -1,3 +1,3 @@
include $(top_srcdir)/config/common.am
SUBDIRS = regex signals
SUBDIRS = filesystem regex signals

View File

@ -0,0 +1,2 @@
Makefile
Makefile.in

View File

@ -0,0 +1,4 @@
include $(top_srcdir)/config/common.am
SUBDIRS = src

View File

@ -0,0 +1,6 @@
Makefile
Makefile.in
libboostfilesystem.la
*.lo
.libs
.deps

View File

@ -0,0 +1,13 @@
include $(top_srcdir)/config/common.am
noinst_LTLIBRARIES = libboostfilesystem.la
INCLUDES = $(BOOST_INCLUDES)
libboostfilesystem_la_SOURCES = \
convenience.cpp \
exception.cpp \
Makefile.am \
operations_posix_windows.cpp \
path_posix_windows.cpp

View File

@ -0,0 +1,32 @@
// libs/filesystem/src/convenience.cpp -------------------------------------//
// (C) Copyright Beman Dawes, 2002
// (C) Copyright Vladimir Prus, 2002
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
// See http://www.boost.org/libs/filesystem for documentation.
#include <boost/filesystem/convenience.hpp>
namespace boost
{
namespace filesystem
{
// create_directories (contributed by Vladimir Prus) -----------------------//
void create_directories(const path& ph)
{
if (ph.empty() || exists(ph)) return;
// First create branch, by calling ourself recursively
create_directories(ph.branch_path());
// Now that parent's path exists, create the directory
create_directory(ph);
}
} // namespace filesystem
} // namespace boost

View File

@ -0,0 +1,246 @@
// Exception implementation file -------------------------------------------//
// < ----------------------------------------------------------------------- >
// < Copyright © 2002 Beman Dawes >
// < Copyright © 2001 Dietmar Kühl, All Rights Reserved >
// < >
// < Permission to use, copy, modify, distribute and sell this >
// < software for any purpose is hereby granted without fee, provided >
// < that the above copyright notice appears in all copies and that >
// < both that copyright notice and this permission notice appear in >
// < supporting documentation. The authors make no representations about >
// < the suitability of this software for any purpose. It is provided >
// < "as is" without express or implied warranty. >
// < ----------------------------------------------------------------------- >
// See http://www.boost.org/libs/filesystem for documentation.
//----------------------------------------------------------------------------//
#include <boost/config.hpp>
#include <boost/filesystem/exception.hpp>
namespace fs = boost::filesystem;
#include <cstring> // SGI MIPSpro compilers need this
#include <string>
# ifdef BOOST_NO_STDC_NAMESPACE
namespace std { using ::strerror; }
# endif
// BOOST_POSIX or BOOST_WINDOWS specify which API to use.
# if !defined( BOOST_WINDOWS ) && !defined( BOOST_POSIX )
# if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) || defined(__CYGWIN__)
# define BOOST_WINDOWS
# else
# define BOOST_POSIX
# endif
# endif
# if defined( BOOST_WINDOWS )
# include "windows.h"
# else
# include <errno.h> // for POSIX error codes
# endif
//----------------------------------------------------------------------------//
namespace
{
std::string system_message( int sys_err_code )
{
std::string str;
# ifdef BOOST_WINDOWS
LPVOID lpMsgBuf;
::FormatMessageA(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
sys_err_code,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPSTR) &lpMsgBuf,
0,
NULL
);
str += static_cast<LPCSTR>(lpMsgBuf);
::LocalFree( lpMsgBuf ); // free the buffer
while ( str.size()
&& (str[str.size()-1] == '\n' || str[str.size()-1] == '\r') )
str.erase( str.size()-1 );
# else
str += std::strerror( errno );
# endif
return str;
}
struct ec_xlate { int sys_ec; fs::error_code ec; };
const ec_xlate ec_table[] =
{
# ifdef BOOST_WINDOWS
{ ERROR_ACCESS_DENIED, fs::security_error },
{ ERROR_INVALID_ACCESS, fs::security_error },
{ ERROR_SHARING_VIOLATION, fs::security_error },
{ ERROR_LOCK_VIOLATION, fs::security_error },
{ ERROR_LOCKED, fs::security_error },
{ ERROR_NOACCESS, fs::security_error },
{ ERROR_WRITE_PROTECT, fs::read_only_error },
{ ERROR_NOT_READY, fs::io_error },
{ ERROR_SEEK, fs::io_error },
{ ERROR_READ_FAULT, fs::io_error },
{ ERROR_WRITE_FAULT, fs::io_error },
{ ERROR_CANTOPEN, fs::io_error },
{ ERROR_CANTREAD, fs::io_error },
{ ERROR_CANTWRITE, fs::io_error },
{ ERROR_DIRECTORY, fs::path_error },
{ ERROR_INVALID_NAME, fs::path_error },
{ ERROR_FILE_NOT_FOUND, fs::not_found_error },
{ ERROR_PATH_NOT_FOUND, fs::not_found_error },
{ ERROR_DEV_NOT_EXIST, fs::not_found_error },
{ ERROR_DEVICE_IN_USE, fs::busy_error },
{ ERROR_OPEN_FILES, fs::busy_error },
{ ERROR_BUSY_DRIVE, fs::busy_error },
{ ERROR_BUSY, fs::busy_error },
{ ERROR_FILE_EXISTS, fs::already_exists_error },
{ ERROR_ALREADY_EXISTS, fs::already_exists_error },
{ ERROR_DIR_NOT_EMPTY, fs::not_empty_error },
{ ERROR_HANDLE_DISK_FULL, fs::out_of_space_error },
{ ERROR_DISK_FULL, fs::out_of_space_error },
{ ERROR_OUTOFMEMORY, fs::out_of_memory_error },
{ ERROR_NOT_ENOUGH_MEMORY, fs::out_of_memory_error },
{ ERROR_TOO_MANY_OPEN_FILES, fs::out_of_resource_error }
# else
{ EACCES, fs::security_error },
{ EROFS, fs::read_only_error },
{ EIO, fs::io_error },
{ ENAMETOOLONG, fs::path_error },
{ ENOENT, fs::not_found_error },
{ ENOTDIR, fs::not_directory_error },
{ EAGAIN, fs::busy_error },
{ EBUSY, fs::busy_error },
{ ETXTBSY, fs::busy_error },
{ EEXIST, fs::already_exists_error },
{ ENOTEMPTY, fs::not_empty_error },
{ EISDIR, fs::is_directory_error },
{ ENOSPC, fs::out_of_space_error },
{ ENOMEM, fs::out_of_memory_error },
{ EMFILE, fs::out_of_resource_error }
# endif
};
fs::error_code lookup_error( int sys_err_code )
{
for ( const ec_xlate * cur = &ec_table[0];
cur != ec_table
+ sizeof(ec_table)/sizeof(ec_xlate); ++cur )
{
if ( sys_err_code == cur->sys_ec ) return cur->ec;
}
return fs::system_error; // general system error code
}
// These helper functions work for POSIX and Windows. For systems where
// path->native_file_string() != path->native_directory_string(), more
// care would be required to get the right form for the function involved.
std::string other_error_prep(
const std::string & who,
const std::string & message )
{
return who + ": " + message;
}
std::string other_error_prep(
const std::string & who,
const fs::path & path1,
const std::string & message )
{
return who + ": \"" + path1.native_file_string() + "\": " + message;
}
std::string system_error_prep(
const std::string & who,
const fs::path & path1,
int sys_err_code )
{
return who + ": \"" + path1.native_file_string() + "\": "
+ system_message( sys_err_code );
}
std::string system_error_prep(
const std::string & who,
const fs::path & path1,
const fs::path & path2,
int sys_err_code )
{
return who + ": \"" + path1.native_file_string()
+ "\", \"" + path2.native_file_string() + "\": "
+ system_message( sys_err_code );
}
} // unnamed namespace
namespace boost
{
namespace filesystem
{
// filesystem_error implementation -----------------------------------------//
filesystem_error::filesystem_error(
const std::string & who,
const std::string & message )
: std::runtime_error(
other_error_prep( who, message ).c_str() ),
m_sys_err(0), m_err(other_error), m_who(who)
{}
filesystem_error::filesystem_error(
const std::string & who,
const path & path1,
const std::string & message )
: std::runtime_error(
other_error_prep( who, path1, message ).c_str() ),
m_sys_err(0), m_err(other_error), m_who(who), m_path1(path1)
{}
filesystem_error::filesystem_error(
const std::string & who,
const path & path1,
int sys_err_code )
: std::runtime_error(
system_error_prep( who, path1, sys_err_code ).c_str() ),
m_sys_err(sys_err_code), m_err(lookup_error(sys_err_code)),
m_who(who), m_path1(path1)
{}
filesystem_error::filesystem_error(
const std::string & who,
const path & path1,
const path & path2,
int sys_err_code )
: std::runtime_error(
system_error_prep( who, path1, path2, sys_err_code ).c_str() ),
m_sys_err(sys_err_code), m_err(lookup_error(sys_err_code)),
m_who(who), m_path1(path1), m_path2(path2)
{}
filesystem_error::~filesystem_error() throw()
{
}
namespace detail
{
int system_error_code() // artifact of POSIX and WINDOWS error reporting
{
# ifdef BOOST_WINDOWS
return ::GetLastError();
# else
return errno; // GCC 3.1 won't accept ::errno
# endif
}
} // namespace detail
} // namespace filesystem
} // namespace boost

View File

@ -0,0 +1,484 @@
// directory_posix_windows.cpp ---------------------------------------------//
// < ----------------------------------------------------------------------- >
// < Copyright © 2002 Beman Dawes. >
// < Copyright © 2001 Dietmar Kühl, All Rights Reserved >
// < >
// < Permission to use, copy, modify, distribute and sell this >
// < software for any purpose is hereby granted without fee, provided >
// < that the above copyright notice appears in all copies and that >
// < both that copyright notice and this permission notice appear in >
// < supporting documentation. The authors make no representations about >
// < the suitability of this software for any purpose. It is provided >
// < "as is" without expressed or implied warranty. >
// < ----------------------------------------------------------------------- >
// See http://www.boost.org/libs/filesystem for documentation.
//----------------------------------------------------------------------------//
// The point of this implementation is to prove the interface. There is no
// claim the implementation is efficient, follows good coding practice, etc.
//----------------------------------------------------------------------------//
#include <boost/config.hpp>
#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/exception.hpp>
#include <boost/scoped_array.hpp>
#include <boost/throw_exception.hpp>
//#include <iostream>
namespace fs = boost::filesystem;
// BOOST_POSIX or BOOST_WINDOWS specify which API to use.
# if !defined( BOOST_WINDOWS ) && !defined( BOOST_POSIX )
# if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) || defined(__CYGWIN__)
# define BOOST_WINDOWS
# else
# define BOOST_POSIX
# endif
# endif
# if defined(BOOST_WINDOWS)
# include "windows.h"
// For Windows, the xxxA form of various function names is used to avoid
// inadvertently getting wide forms of the functions. (The undecorated
// forms are actually macros, so can misfire if the user has various
// other macros defined. There was a bug report of this happening.)
# else
# include "sys/stat.h"
# include "dirent.h"
# include "unistd.h"
# include "fcntl.h"
# endif
#include <string>
#include <cstdio>
#include <cerrno>
#include <cassert>
// helpers -----------------------------------------------------------------//
namespace
{
#ifdef BOOST_POSIX
# define BOOST_HANDLE DIR *
# define BOOST_INVALID_HANDLE_VALUE 0
# define BOOST_SYSTEM_DIRECTORY_TYPE struct dirent *
inline const char * find_first_file( const char * dir,
BOOST_HANDLE & handle, BOOST_SYSTEM_DIRECTORY_TYPE & )
// Returns: 0 if error, otherwise name
{
const char * dummy_first_name = ".";
return ( (handle = ::opendir( dir ))
== BOOST_INVALID_HANDLE_VALUE ) ? 0 : dummy_first_name;
}
inline void find_close( BOOST_HANDLE handle )
{
assert( handle != BOOST_INVALID_HANDLE_VALUE );
::closedir( handle );
}
inline const char * find_next_file(
BOOST_HANDLE handle, const fs::path & ph, BOOST_SYSTEM_DIRECTORY_TYPE & )
// Returns: if EOF 0, otherwise name
// Throws: if system reports error
{
// TODO: use readdir_r() if available, so code is multi-thread safe.
// Fly-in-ointment: not all platforms support readdir_r().
struct dirent * dp;
errno = 0;
if ( (dp = ::readdir( handle )) == 0 )
{
if ( errno != 0 )
{
boost::throw_exception(
fs::filesystem_error(
"boost::filesystem::directory_iterator::operator++",
ph, errno ) );
}
else { return 0; } // end reached
}
return dp->d_name;
}
#else // BOOST_WINDOWS
# define BOOST_HANDLE HANDLE
# define BOOST_INVALID_HANDLE_VALUE INVALID_HANDLE_VALUE
# define BOOST_SYSTEM_DIRECTORY_TYPE WIN32_FIND_DATAA
inline const char * find_first_file( const char * dir,
BOOST_HANDLE & handle, BOOST_SYSTEM_DIRECTORY_TYPE & data )
// Returns: 0 if error, otherwise name
{
// std::cout << "find_first_file " << dir << std::endl;
std::string dirpath( std::string(dir) + "/*" );
return ( (handle = ::FindFirstFileA( dirpath.c_str(), &data ))
== BOOST_INVALID_HANDLE_VALUE ) ? 0 : data.cFileName;
}
inline void find_close( BOOST_HANDLE handle )
{
// std::cout << "find_close" << std::endl;
assert( handle != BOOST_INVALID_HANDLE_VALUE );
::FindClose( handle );
}
inline const char * find_next_file(
BOOST_HANDLE handle, const fs::path & ph,
BOOST_SYSTEM_DIRECTORY_TYPE & data )
// Returns: 0 if EOF, otherwise name
// Throws: if system reports error
{
if ( ::FindNextFileA( handle, &data ) == 0 )
{
if ( ::GetLastError() != ERROR_NO_MORE_FILES )
{
boost::throw_exception( fs::filesystem_error(
"boost::filesystem::directory_iterator::operator++",
ph.branch_path(), fs::detail::system_error_code() ) );
}
else { return 0; } // end reached
}
return data.cFileName;
}
#endif
fs::directory_iterator end_itr;
bool is_empty_directory( const fs::path & dir_path )
{
return fs::directory_iterator(dir_path) == end_itr;
}
unsigned long remove_all_aux( const fs::path & ph )
{
unsigned long count = 1;
if ( fs::is_directory( ph ) )
{
for ( fs::directory_iterator itr( ph );
itr != end_itr; ++itr )
{
count += remove_all_aux( *itr );
}
}
fs::remove( ph );
return count;
}
} // unnamed namespace
namespace boost
{
namespace filesystem
{
// dir_itr_imp -------------------------------------------------------------//
class directory_iterator::dir_itr_imp
{
public:
path entry_path;
BOOST_HANDLE handle;
~dir_itr_imp()
{
if ( handle != BOOST_INVALID_HANDLE_VALUE ) find_close( handle );
}
};
// directory_iterator implementation ---------------------------------------//
// default ctor creates the "end" iterator (by letting base default to 0)
directory_iterator::directory_iterator() {}
directory_iterator::directory_iterator( const path & dir_path )
{
m_imp.reset( new dir_itr_imp );
BOOST_SYSTEM_DIRECTORY_TYPE scratch;
const char * name = 0; // initialization quiets compiler warnings
if ( dir_path.empty() )
m_imp->handle = BOOST_INVALID_HANDLE_VALUE;
else
name = find_first_file( dir_path.native_directory_string().c_str(),
m_imp->handle, scratch ); // sets handle
if ( m_imp->handle != BOOST_INVALID_HANDLE_VALUE )
{
m_imp->entry_path = dir_path;
m_imp->entry_path.m_path_append( name, path::nocheck );
while ( m_imp.get()
&& ( m_imp->entry_path.leaf() == "."
|| m_imp->entry_path.leaf() == ".." ) )
{ operator++(); }
}
else
{
boost::throw_exception( filesystem_error(
"boost::filesystem::directory_iterator constructor",
dir_path, fs::detail::system_error_code() ) );
}
}
path const & directory_iterator::m_deref() const
{
assert( m_imp.get() ); // fails if dereference end iterator
return m_imp->entry_path;
}
void directory_iterator::m_inc()
{
assert( m_imp.get() ); // fails on increment end iterator
assert( m_imp->handle != BOOST_INVALID_HANDLE_VALUE ); // reality check
BOOST_SYSTEM_DIRECTORY_TYPE scratch;
const char * name;
if ( (name = find_next_file( m_imp->handle,
m_imp->entry_path, scratch )) != 0 )
{
m_imp->entry_path.m_replace_leaf( name );
}
else
{
m_imp.reset(); // make base() the end iterator
}
}
// free functions ----------------------------------------------------------//
bool exists( const path & ph )
{
# ifdef BOOST_POSIX
struct stat path_stat;
return ::stat( ph.string().c_str(), &path_stat ) == 0;
# else
return ::GetFileAttributesA( ph.string().c_str() ) != 0xFFFFFFFF;
# endif
}
bool is_directory( const path & ph )
{
# ifdef BOOST_POSIX
struct stat path_stat;
if ( ::stat( ph.native_directory_string().c_str(), &path_stat ) != 0 )
boost::throw_exception( filesystem_error(
"boost::filesystem::is_directory",
ph, fs::detail::system_error_code() ) );
return S_ISDIR( path_stat.st_mode );
# else
DWORD attributes = ::GetFileAttributesA( ph.native_directory_string().c_str() );
if ( attributes == 0xFFFFFFFF )
boost::throw_exception( filesystem_error(
"boost::filesystem::is_directory",
ph, fs::detail::system_error_code() ) );
return (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
# endif
}
bool _is_empty( const path & ph )
{
# ifdef BOOST_POSIX
struct stat path_stat;
if ( ::stat( ph.string().c_str(), &path_stat ) != 0 )
boost::throw_exception( filesystem_error(
"boost::filesystem::is_empty",
ph, fs::detail::system_error_code() ) );
return S_ISDIR( path_stat.st_mode )
? is_empty_directory( ph )
: path_stat.st_size == 0;
# else
WIN32_FILE_ATTRIBUTE_DATA fad;
if ( !::GetFileAttributesExA( ph.string().c_str(),
::GetFileExInfoStandard, &fad ) )
boost::throw_exception( filesystem_error(
"boost::filesystem::is_empty",
ph, fs::detail::system_error_code() ) );
return ( fad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
? is_empty_directory( ph )
:( !fad.nFileSizeHigh && !fad.nFileSizeLow );
# endif
}
void create_directory( const path & dir_path )
{
# ifdef BOOST_POSIX
if ( ::mkdir( dir_path.native_directory_string().c_str(),
S_IRWXU|S_IRWXG|S_IRWXO ) != 0 )
# else
if ( !::CreateDirectoryA( dir_path.native_directory_string().c_str(), 0 ) )
# endif
boost::throw_exception( filesystem_error(
"boost::filesystem::create_directory",
dir_path, fs::detail::system_error_code() ) );
}
bool remove( const path & ph )
{
if ( exists( ph ) )
{
# ifdef BOOST_POSIX
if ( ::remove( ph.string().c_str() ) != 0 )
{
# else
if ( is_directory( ph ) )
{
if ( !::RemoveDirectoryA( ph.string().c_str() ) )
boost::throw_exception( filesystem_error(
"boost::filesystem::remove",
ph, fs::detail::system_error_code() ) );
}
else
{
if ( !::DeleteFileA( ph.string().c_str() ) )
# endif
boost::throw_exception( filesystem_error(
"boost::filesystem::remove",
ph, fs::detail::system_error_code() ) );
}
return true;
}
return false;
}
unsigned long remove_all( const path & ph )
{
return exists( ph ) ? remove_all_aux( ph ) : 0;
}
void rename( const path & old_path,
const path & new_path )
{
# ifdef BOOST_POSIX
if ( exists( new_path ) // POSIX is too permissive so must check
|| ::rename( old_path.string().c_str(), new_path.string().c_str() ) != 0 )
# else
if ( !::MoveFileA( old_path.string().c_str(), new_path.string().c_str() ) )
# endif
boost::throw_exception( filesystem_error(
"boost::filesystem::rename",
old_path, new_path, fs::detail::system_error_code() ) );
}
void copy_file( const path & from_file_ph,
const path & to_file_ph )
{
# ifdef BOOST_POSIX
// TODO: Ask POSIX experts if this is the best way to copy a file
const std::size_t buf_sz = 32768;
boost::scoped_array<char> buf( new char [buf_sz] );
int infile, outfile=0; // init quiets compiler warning
if ( (infile = ::open( from_file_ph.string().c_str(),
O_RDONLY )) < 0
|| (outfile = ::open( to_file_ph.string().c_str(),
O_WRONLY | O_CREAT | O_EXCL,
S_IRWXU|S_IRWXG|S_IRWXO )) < 0 )
{
if ( infile != 0 ) ::close( infile );
boost::throw_exception( filesystem_error(
"boost::filesystem::copy_file",
from_file_ph, to_file_ph, fs::detail::system_error_code() ) );
}
ssize_t sz;
while ( (sz = ::read( infile, buf.get(), buf_sz )) > 0
&& (sz = ::write( outfile, buf.get(), sz )) > 0 ) {}
::close( infile );
::close( outfile );
if ( sz != 0 )
# else
if ( !::CopyFileA( from_file_ph.string().c_str(),
to_file_ph.string().c_str(), /*fail_if_exists=*/true ) )
# endif
boost::throw_exception( filesystem_error(
"boost::filesystem::copy_file",
from_file_ph, to_file_ph, fs::detail::system_error_code() ) );
}
path current_path()
{
# ifdef BOOST_POSIX
long path_max = ::pathconf( ".", _PC_PATH_MAX );
if ( path_max < 1 )
boost::throw_exception(
filesystem_error( "boost::filesystem::current_path",
"_PC_PATH_MAX < 1" ) );
boost::scoped_array<char>
buf( new char[static_cast<std::size_t>(path_max)] );
if ( ::getcwd( buf.get(), static_cast<std::size_t>(path_max) ) == 0 )
# else
DWORD sz;
if ( (sz = ::GetCurrentDirectoryA( 0, static_cast<char*>(0) )) == 0 )
boost::throw_exception(
filesystem_error( "boost::filesystem::current_path",
"size is 0" ) );
boost::scoped_array<char> buf( new char[sz] );
if ( ::GetCurrentDirectoryA( sz, buf.get() ) == 0 )
# endif
boost::throw_exception(
filesystem_error( "boost::filesystem::current_path", path(),
fs::detail::system_error_code() ) );
return path( buf.get(), native );
}
const path & initial_path()
{
static path init_path;
if ( init_path.empty() ) init_path = current_path();
return init_path;
}
path system_complete( const path & ph )
{
# ifdef BOOST_WINDOWS
if ( ph.empty() ) return ph;
char buf[MAX_PATH];
char * pfn;
std::size_t len = ::GetFullPathNameA( ph.string().c_str(),
sizeof(buf) , buf, &pfn );
if ( !len )
{ boost::throw_exception(
filesystem_error( "boost::filesystem::system_complete",
ph, "size is 0" ) ); }
buf[len] = '\0';
return path( buf, native );
# else
return (ph.empty() || ph.is_complete())
? ph : current_path() / ph;
# endif
}
path complete( const path & ph, const path & base )
{
assert( base.is_complete()
&& (ph.is_complete() || !ph.has_root_name()) ); // precondition
# ifdef BOOST_WINDOWS
if (ph.empty() || ph.is_complete()) return ph;
if ( !ph.has_root_name() )
return ph.has_root_directory()
? path( base.root_name(), native ) / ph
: base / ph;
return base / ph;
# else
return (ph.empty() || ph.is_complete()) ? ph : base / ph;
# endif
}
} // namespace filesystem
} // namespace boost

View File

@ -0,0 +1,566 @@
// path implementation -----------------------------------------------------//
// (C) Copyright Beman Dawes 2002. Permission to copy,
// use, modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided "as is"
// without express or implied warranty, and with no claim as to its
// suitability for any purpose.
// See http://www.boost.org/libs/filesystem for documentation.
//****************************************************************************//
// WARNING: This code was hacked time and time again as different library
// designs were tried. Thus portions may be residue from the earlier
// experiments, and be totally stupid or wrong in light of the final library
// specifications. The code needs to be reviewed line-by-line to elmininate
// such problems.
//****************************************************************************//
// BOOST_POSIX or BOOST_WINDOWS specify which API to use.
# if !defined( BOOST_WINDOWS ) && !defined( BOOST_POSIX )
# if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) || defined(__CYGWIN__)
# define BOOST_WINDOWS
# else
# define BOOST_POSIX
# endif
# endif
#include <boost/filesystem/path.hpp>
#include <boost/filesystem/exception.hpp>
namespace fs = boost::filesystem;
#include <boost/config.hpp>
#ifdef BOOST_NO_STDC_NAMESPACE
namespace std { using ::strlen; }
#endif
#include <boost/throw_exception.hpp>
#include <cstring> // SGI MIPSpro compilers need this
#include <vector>
#include <cassert>
// helpers -----------------------------------------------------------------//
namespace
{
// POSIX & Windows cases: "", "/", "/foo", "foo", "foo/bar"
// Windows only cases: "c:", "c:/", "c:foo", "c:/foo",
// "prn:", "//share", "//share/", "//share/foo"
std::string::size_type leaf_pos( const std::string & str,
std::string::size_type end_pos ) // end_pos is past-the-end position
// return 0 if str itself is leaf (or empty)
{
if ( end_pos && str[end_pos-1] == '/' ) return end_pos-1;
std::string::size_type pos( str.find_last_of( '/', end_pos-1 ) );
# ifdef BOOST_WINDOWS
if ( pos == std::string::npos ) pos = str.find_last_of( ':', end_pos-2 );
# endif
return ( pos == std::string::npos // path itself must be a leaf (or empty)
# ifdef BOOST_WINDOWS
|| (pos == 1 && str[0] == '/') // or share
# endif
) ? 0 // so leaf is entire string
: pos + 1; // or starts after delimiter
}
void first_name( const std::string & src, std::string & target )
{
target = ""; // VC++ 6.0 doesn't have string::clear()
std::string::const_iterator itr( src.begin() );
# ifdef BOOST_WINDOWS
// deal with //share
if ( src.size() >= 2 && src[0] == '/' && src[1] == '/' )
{ target = "//"; itr += 2; }
# endif
while ( itr != src.end()
# ifdef BOOST_WINDOWS
&& *itr != ':'
# endif
&& *itr != '/' ) { target += *itr++; }
if ( itr == src.end() ) return;
# ifdef BOOST_WINDOWS
if ( *itr == ':' )
{
target += *itr++;
return;
}
# endif
// *itr is '/'
if ( itr == src.begin() ) { target += '/'; }
return;
}
const char invalid_chars[] =
"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F"
"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F"
"<>:\"/\\|*?";
// note that the terminating '\0' is part of the string - thus the size below
// is sizeof(invalid_chars) rather than sizeof(invalid_chars)-1. I
const std::string invalid_generic( invalid_chars, sizeof(invalid_chars) );
const std::string valid_posix(
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789._-" );
const std::string valid_boost_file(
"abcdefghijklmnopqrstuvwxyz0123456789._-" );
const std::string valid_boost_directory(
"abcdefghijklmnopqrstuvwxyz0123456789_-" );
} // unnamed namespace
//----------------------------------------------------------------------------//
namespace boost
{
namespace filesystem
{
// error checking functions --------------------------------------------//
bool generic_name( const std::string & name )
{
return name.size() != 0
&& name.find_first_of( invalid_generic ) == std::string::npos
&& name != "."
&& name != ".."
&& *name.begin() != ' '
&& *(name.end()-1) != ' ';
}
bool posix_name( const std::string & name )
{
return name.find_first_not_of( valid_posix ) == std::string::npos
&& name != ".";
}
const path & check_posix_leaf( const path & ph )
{
if ( !posix_name( ph.leaf() ) )
boost::throw_exception( filesystem_error(
"boost::filesystem::check_posix_leaf",
ph, "invalid posix name: \""
+ ph.leaf() + "\"" ) );
return ph;
}
bool boost_file_name( const std::string & name )
{
return name.size() <= 31
&& name.find_first_not_of( valid_boost_file ) == std::string::npos
&& name != ".";
}
bool boost_directory_name( const std::string & name )
{
return name.size() <= 31
&& name.find_first_not_of( valid_boost_directory ) == std::string::npos;
}
// path implementation -----------------------------------------------------//
path::path( const std::string & src )
{
m_path_append( src );
}
path::path( const char * src )
{
m_path_append( src );
}
path::path( const std::string & src, path_format )
{
m_path_append( src, platform );
}
path::path( const char * src, path_format )
{
m_path_append( src, platform );
}
path & path::operator /=( const path & rhs )
{
m_path_append( rhs.m_path, nocheck );
return *this;
}
void path::m_path_append( const std::string & src, source_context context )
{
// convert backslash to forward slash if context is "platform"
// check names if context is "generic"
// allow system-specific-root if context is not "generic"
assert( src.size() == std::strlen( src.c_str() ) ); // no embedded 0
if ( src.size() == 0 ) return;
std::string::const_iterator itr( src.begin() );
// [root-filesystem]
# ifdef BOOST_WINDOWS
if ( context != generic && src.size() >= 2 )
{
// drive or device
if ( src[1] == ':' || src[src.size()-1] == ':' )
{
for ( ; *itr != ':'; ++itr ) m_path += *itr;
m_path += ':';
++itr;
}
// share
else if ( (*itr == '/' || (*itr == '\\' && context == platform))
&& (*(itr+1) == '/' || (*(itr+1) == '\\' && context == platform)) )
{
m_path += "//";
for ( itr += 2;
itr != src.end() && *itr != '/' && *itr != '\\';
++itr ) m_path += *itr;
}
}
# endif
// root directory [ "/" ]
if ( itr != src.end() && (*itr == '/'
# ifdef BOOST_WINDOWS
|| (*itr == '\\' && context == platform)
# endif
) )
{
++itr;
if ( m_path.size() == 0
# ifdef BOOST_WINDOWS
|| m_path[m_path.size()-1] == ':' // drive or device
|| ( // share
m_path.size() > 2
&& m_path[0] == '/'
&& m_path[1] == '/'
&& m_path.find( '/', 2 ) == std::string::npos
)
# endif
) m_path += '/';
}
// element { "/" element } [ "/" ]
while ( itr != src.end() )
{
// append '/' if needed
if ( !empty()
&& *(m_path.end()-1) != ':' && *(m_path.end()-1) != '/' )
m_path += '/';
if ( *itr == '.'&& (itr+1) != src.end() && *(itr+1) == '.' ) // ".."
{
if ( m_path.size() >= 2 // there is a named parent directory present
&& *(m_path.end()-1) == '/'
# ifdef BOOST_WINDOWS
&& *(m_path.end()-2) != ':'
# endif
&& *(m_path.end()-2) != '.' )
{
// reference to parent so erase child
std::string::iterator child( m_path.end()-2 );
while ( child != m_path.begin() && *child != '/'
# ifdef BOOST_WINDOWS
&& *child != ':'
# endif
) --child;
// only erase '/' if it is a separator rather than part of the root
if ( (*child == '/'
&& (child == m_path.begin()
# ifdef BOOST_WINDOWS
|| *(child-1) == ':'))
|| *child == ':'
# else
))
# endif
) ++child;
m_path.erase( child, m_path.end() );
}
else { m_path += ".."; }
++itr;
++itr;
} // ".."
else // element is name
{
std::string name;
do
{ name += *itr; }
while ( ++itr != src.end() && *itr != '/'
# ifdef BOOST_WINDOWS
&& (*itr != '\\' || context != platform)
# endif
);
if ( context == generic && !generic_name( name ) )
{
boost::throw_exception( filesystem_error(
"boost::filesystem::path",
"invalid name \"" + name + "\" in path: \"" + src + "\"" ) );
}
m_path += name;
}
if ( itr != src.end() )
{
if ( *itr == '/'
# ifdef BOOST_WINDOWS
|| (*itr == '\\' && context == platform)
# endif
) ++itr;
else
boost::throw_exception( filesystem_error(
"boost::filesystem::path",
"invalid path syntax: \"" + src + "\"" ) );
}
} // while more elements
}
// path conversion functions ------------------------------------------------//
std::string path::native_file_string() const
{
# ifdef BOOST_WINDOWS
std::string s( m_path );
for ( std::string::iterator itr( s.begin() );
itr != s.end(); ++itr )
if ( *itr == '/' ) *itr = '\\';
return s;
# else
return m_path;
# endif
}
std::string path::native_directory_string() const
{ return native_file_string(); }
// path decomposition functions ---------------------------------------------//
path::iterator path::begin() const
{
iterator itr;
itr.base().path_ptr = this;
first_name( m_path, itr.base().name );
itr.base().pos = 0;
return itr;
}
void path::m_replace_leaf( const char * new_leaf )
{
m_path.erase( leaf_pos( m_path, m_path.size() ) );
m_path += new_leaf;
}
std::string path::leaf() const
{
return m_path.substr( leaf_pos( m_path, m_path.size() ) );
}
namespace detail
{
inline bool is_absolute_root( const std::string & s,
std::string::size_type len )
{
return
len && s[len-1] == '/'
&&
(
len == 1 // "/"
# ifdef BOOST_WINDOWS
|| ( len > 1
&& ( s[len-2] == ':' // drive or device
|| ( s[0] == '/' // share
&& s[1] == '/'
&& s.find( '/', 2 ) == len-1
)
)
)
# endif
);
}
}
path path::branch_path() const
{
std::string::size_type end_pos( leaf_pos( m_path, m_path.size() ) );
// skip a '/' unless it is a root directory
if ( end_pos && m_path[end_pos-1] == '/'
&& !detail::is_absolute_root( m_path, end_pos ) ) --end_pos;
return path( m_path.substr( 0, end_pos ), native );
}
path path::relative_path() const
{
std::string::size_type pos( 0 );
if ( m_path.size() && m_path[0] == '/' )
{ pos = 1;
# ifdef BOOST_WINDOWS
if ( m_path.size()>1 && m_path[1] == '/' ) // share
{
if ( (pos = m_path.find( '/', 2 )) != std::string::npos ) ++pos;
else return path();
}
}
else if ( (pos = m_path.find( ':' )) == std::string::npos ) pos = 0;
else // has ':'
{
if ( ++pos < m_path.size() && m_path[pos] == '/' ) ++pos;
# endif
}
return path( m_path.substr( pos ) );
}
std::string path::root_name() const
{
# ifdef BOOST_WINDOWS
std::string::size_type pos( m_path.find( ':' ) );
if ( pos != std::string::npos ) return m_path.substr( 0, pos+1 );
if ( m_path.size() > 2 && m_path[0] == '/' && m_path[1] == '/' )
{
pos = m_path.find( '/', 2 );
return m_path.substr( 0, pos );
}
# endif
return std::string();
}
std::string path::root_directory() const
{
return std::string(
( m_path.size() && m_path[0] == '/' ) // covers both "/" and "//share"
# ifdef BOOST_WINDOWS
|| ( m_path.size() > 2
&& m_path[1] == ':'
&& m_path[2] == '/' ) // "c:/"
# endif
? "/" : "" );
}
path path::root_path() const
{
return path(
# ifdef BOOST_WINDOWS
root_name(), native ) /= root_directory();
# else
root_directory() );
# endif
}
// path query functions -----------------------------------------------------//
bool path::is_complete() const
{
# ifdef BOOST_WINDOWS
return m_path.size() > 2
&& ( (m_path[1] == ':' && m_path[2] == '/') // "c:/"
|| (m_path[0] == '/' && m_path[1] == '/') // "//share"
|| m_path[m_path.size()-1] == ':' );
# else
return m_path.size() && m_path[0] == '/';
# endif
}
bool path::has_root_path() const
{
return ( m_path.size()
&& m_path[0] == '/' ) // covers both "/" and "//share"
# ifdef BOOST_WINDOWS
|| ( m_path.size() > 1 && m_path[1] == ':' ) // "c:" and "c:/"
|| ( m_path.size() > 3
&& m_path[m_path.size()-1] == ':' ) // "device:"
# endif
;
}
bool path::has_root_name() const
{
# ifdef BOOST_WINDOWS
return m_path.size() > 1
&& ( m_path[1] == ':' // "c:"
|| m_path[m_path.size()-1] == ':' // "prn:"
|| (m_path[0] == '/' && m_path[1] == '/') // "//share"
);
# else
return false;
# endif
}
bool path::has_root_directory() const
{
return ( m_path.size()
&& m_path[0] == '/' ) // covers both "/" and "//share"
# ifdef BOOST_WINDOWS
|| ( m_path.size() > 2
&& m_path[1] == ':' && m_path[2] == '/' ) // "c:/"
# endif
;
}
bool path::has_relative_path() const { return !relative_path().empty(); }
bool path::has_branch_path() const { return !branch_path().empty(); }
// path_itr_imp implementation ----------------------------------------------//
namespace detail
{
void path_itr_imp::operator++()
{
assert( pos < path_ptr->m_path.size() ); // detect increment past end
pos += name.size();
if ( pos == path_ptr->m_path.size() )
{
name = ""; // not strictly required, but might aid debugging
return;
}
if ( path_ptr->m_path[pos] == '/' )
{
# ifdef BOOST_WINDOWS
if ( name[name.size()-1] == ':' // drive or device
|| (name[0] == '/' && name[1] == '/') ) // share
{
name = "/";
return;
}
# endif
++pos;
}
std::string::size_type end_pos( path_ptr->m_path.find( '/', pos ) );
if ( end_pos == std::string::npos ) end_pos = path_ptr->m_path.size();
name = path_ptr->m_path.substr( pos, end_pos - pos );
}
void path_itr_imp::operator--()
{
assert( pos ); // detect decrement of begin
std::string::size_type end_pos( pos );
// skip a '/' unless it is a root directory
if ( path_ptr->m_path[end_pos-1] == '/'
&& !detail::is_absolute_root( path_ptr->m_path, end_pos ) ) --end_pos;
pos = leaf_pos( path_ptr->m_path, end_pos );
name = path_ptr->m_path.substr( pos, end_pos - pos );
}
} // namespace detail
} // namespace filesystem
} // namespace boost

View File

@ -389,6 +389,8 @@ AC_CONFIG_SUBDIRS(lib lib/reLyX)
AC_CONFIG_FILES([Makefile \
boost/Makefile \
boost/libs/Makefile \
boost/libs/filesystem/Makefile \
boost/libs/filesystem/src/Makefile \
boost/libs/regex/Makefile \
boost/libs/regex/src/Makefile \
boost/libs/signals/Makefile \