You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and dots ('.'), can be up to 35 characters long. Letters must be lowercase.
		
		
		
		
		
			
		
			
				
					
					
						
							1571 lines
						
					
					
						
							55 KiB
						
					
					
				
			
		
		
	
	
							1571 lines
						
					
					
						
							55 KiB
						
					
					
				| //  boost/filesystem/path.hpp  -----------------------------------------------// | |
|  | |
| //  Copyright Beman Dawes 2002-2005 | |
| //  Copyright Vladimir Prus 2002 | |
|  | |
| //  Distributed under the Boost Software License, Version 1.0. (See accompanying | |
| //  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
|  | |
| //  See library home page at http://www.boost.org/libs/filesystem | |
|  | |
| //  basic_path's stem(), extension(), and replace_extension() are based on | |
| //  basename(), extension(), and change_extension() from the original | |
| //  filesystem/convenience.hpp header by Vladimir Prus. | |
|  | |
| //----------------------------------------------------------------------------//  | |
|  | |
| #ifndef BOOST_FILESYSTEM2_PATH_HPP | |
| #define BOOST_FILESYSTEM2_PATH_HPP | |
|  | |
| #include <boost/filesystem/v2/config.hpp> | |
| #include <boost/system/system_error.hpp> | |
| #include <boost/iterator/iterator_facade.hpp> | |
| #include <boost/shared_ptr.hpp> | |
| #include <boost/type_traits/is_same.hpp> | |
| #include <boost/static_assert.hpp> | |
| #include <boost/assert.hpp> | |
|  | |
| #include <string> | |
| #include <algorithm> // for lexicographical_compare | |
| #include <iosfwd>    // needed by basic_path inserter and extractor | |
| #include <stdexcept> | |
|  | |
| # ifndef BOOST_FILESYSTEM2_NARROW_ONLY | |
| #   include <locale> | |
| # endif | |
|  | |
| #include <boost/config/abi_prefix.hpp> // must be the last #include | |
|  | |
| namespace boost | |
| { | |
|   namespace BOOST_FILESYSTEM2_NAMESPACE | |
|   { | |
|     template<class String, class Traits> class basic_path; | |
| 
 | |
|     struct path_traits; | |
|     typedef basic_path< std::string, path_traits > path; | |
| 
 | |
|     struct path_traits | |
|     { | |
|       typedef std::string internal_string_type; | |
|       typedef std::string external_string_type; | |
|       static external_string_type to_external( const path &, | |
|         const internal_string_type & src ) { return src; } | |
|       static internal_string_type to_internal( | |
|         const external_string_type & src ) { return src; } | |
|     }; | |
| 
 | |
| # ifndef BOOST_FILESYSTEM2_NARROW_ONLY | |
|  | |
|     struct BOOST_FILESYSTEM_DECL wpath_traits; | |
|      | |
|     typedef basic_path< std::wstring, wpath_traits > wpath; | |
| 
 | |
|     struct BOOST_FILESYSTEM_DECL wpath_traits | |
|     { | |
|       typedef std::wstring internal_string_type; | |
| # ifdef BOOST_WINDOWS_API | |
|       typedef std::wstring external_string_type; | |
|       static external_string_type to_external( const wpath &, | |
|         const internal_string_type & src ) { return src; } | |
|       static internal_string_type to_internal( | |
|         const external_string_type & src ) { return src; } | |
| # else | |
|       typedef std::string external_string_type; | |
|       static external_string_type to_external( const wpath & ph, | |
|         const internal_string_type & src ); | |
|       static internal_string_type to_internal( | |
|         const external_string_type & src ); | |
| # endif | |
|       static void imbue( const std::locale & loc ); | |
|       static bool imbue( const std::locale & loc, const std::nothrow_t & ); | |
|     }; | |
| 
 | |
| # endif // ifndef BOOST_FILESYSTEM2_NARROW_ONLY | |
|  | |
|     //  path traits  ---------------------------------------------------------// | |
|  | |
|     template<class Path> struct is_basic_path | |
|       { BOOST_STATIC_CONSTANT( bool, value = false ); }; | |
|     template<> struct is_basic_path<path> | |
|       { BOOST_STATIC_CONSTANT( bool, value = true ); }; | |
| # ifndef BOOST_FILESYSTEM2_NARROW_ONLY | |
|     template<> struct is_basic_path<wpath> | |
|       { BOOST_STATIC_CONSTANT( bool, value = true ); }; | |
| # endif | |
|  | |
|     // These only have to be specialized if Path::string_type::value_type | |
|     // is not convertible from char, although specializations may eliminate | |
|     // compiler warnings. See ticket 2543. | |
|     template<class Path> struct slash | |
|       { BOOST_STATIC_CONSTANT( char, value = '/' ); }; | |
| 
 | |
|     template<class Path> struct dot | |
|       { BOOST_STATIC_CONSTANT( char, value = '.' ); }; | |
| 
 | |
|     template<class Path> struct colon | |
|       { BOOST_STATIC_CONSTANT( char, value = ':' ); }; | |
| 
 | |
| # ifndef BOOST_FILESYSTEM2_NARROW_ONLY | |
|     template<> struct slash<wpath> | |
|       { BOOST_STATIC_CONSTANT( wchar_t, value = L'/' ); }; | |
|     template<> struct dot<wpath> | |
|       { BOOST_STATIC_CONSTANT( wchar_t, value = L'.' ); }; | |
|     template<> struct colon<wpath> | |
|       { BOOST_STATIC_CONSTANT( wchar_t, value = L':' ); }; | |
| # endif | |
|  | |
| # ifdef BOOST_WINDOWS_PATH | |
|     template<class Path> struct path_alt_separator | |
|       { BOOST_STATIC_CONSTANT( char, value = '\\' ); }; | |
| #   ifndef BOOST_FILESYSTEM2_NARROW_ONLY | |
|     template<> struct path_alt_separator<wpath> | |
|       { BOOST_STATIC_CONSTANT( wchar_t, value = L'\\' ); }; | |
| #   endif | |
| # endif | |
|  | |
|     //  workaround for VC++ 7.0 and earlier issues with nested classes | |
|     namespace detail | |
|     { | |
|       template<class Path> | |
|       class iterator_helper | |
|       { | |
|       public: | |
|         typedef typename Path::iterator iterator; | |
|         static void do_increment( iterator & ph ); | |
|         static void do_decrement( iterator & ph ); | |
|       }; | |
|     } | |
| 
 | |
|     //  basic_path  ----------------------------------------------------------// | |
|    | |
|     template<class String, class Traits> | |
|     class basic_path | |
|     { | |
|     // invariant: m_path valid according to the portable generic path grammar | |
|  | |
|       // validate template arguments | |
| // TODO: get these working | |
| //      BOOST_STATIC_ASSERT( ::boost::is_same<String,typename Traits::internal_string_type>::value ); | |
| //      BOOST_STATIC_ASSERT( ::boost::is_same<typename Traits::external_string_type,std::string>::value || ::boost::is_same<typename Traits::external_string_type,std::wstring>::value ); | |
|  | |
|     public: | |
|       // compiler generates copy constructor and copy assignment | |
|  | |
|       typedef basic_path<String, Traits> path_type; | |
|       typedef String string_type; | |
|       typedef typename String::value_type value_type; | |
|       typedef Traits traits_type; | |
|       typedef typename Traits::external_string_type external_string_type;  | |
| 
 | |
|       // constructors/destructor | |
|       basic_path() {} | |
|       basic_path( const string_type & s ) { operator/=( s ); } | |
|       basic_path( const value_type * s )  { operator/=( s ); } | |
| #     ifndef BOOST_NO_MEMBER_TEMPLATES | |
|         template <class InputIterator> | |
|           basic_path( InputIterator first, InputIterator last ) | |
|             { append( first, last ); } | |
| #     endif | |
|      ~basic_path() {} | |
| 
 | |
|       // assignments | |
|       basic_path & operator=( const string_type & s ) | |
|       { | |
| #     if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, >= 310) | |
|         m_path.clear(); | |
| #     else | |
|         m_path.erase( m_path.begin(), m_path.end() ); | |
| #     endif | |
|         operator/=( s );  | |
|         return *this; | |
|       } | |
|       basic_path & operator=( const value_type * s ) | |
|       {  | |
| #     if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, >= 310) | |
|         m_path.clear(); | |
| #     else | |
|         m_path.erase( m_path.begin(), m_path.end() ); | |
| #     endif | |
|         operator/=( s );  | |
|         return *this; | |
|       } | |
| #     ifndef BOOST_NO_MEMBER_TEMPLATES | |
|         template <class InputIterator> | |
|           basic_path & assign( InputIterator first, InputIterator last ) | |
|             { m_path.clear(); append( first, last ); return *this; } | |
| #     endif | |
|  | |
|       // modifiers | |
|       basic_path & operator/=( const basic_path & rhs )  { return operator /=( rhs.string().c_str() ); } | |
|       basic_path & operator/=( const string_type & rhs ) { return operator /=( rhs.c_str() ); } | |
|       basic_path & operator/=( const value_type * s ); | |
| #     ifndef BOOST_NO_MEMBER_TEMPLATES | |
|         template <class InputIterator> | |
|           basic_path & append( InputIterator first, InputIterator last ); | |
| #     endif | |
|        | |
|       void clear() | |
|       {  | |
| #     if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, >= 310) | |
|         m_path.clear(); | |
| #     else | |
|         m_path.erase( m_path.begin(), m_path.end() ); | |
| #     endif | |
|       } | |
| 
 | |
|       void swap( basic_path & rhs ) | |
|       { | |
|         m_path.swap( rhs.m_path ); | |
| #       ifdef BOOST_CYGWIN_PATH | |
|           std::swap( m_cygwin_root, rhs.m_cygwin_root ); | |
| #       endif | |
|       } | |
| 
 | |
|       basic_path & remove_filename(); | |
|       basic_path & replace_extension( const string_type & new_extension = string_type() ); | |
| 
 | |
| # ifndef BOOST_FILESYSTEM_NO_DEPRECATED | |
|       basic_path & remove_leaf() { return remove_filename(); } | |
| # endif | |
|  | |
|       // observers | |
|       const string_type & string() const         { return m_path; } | |
|       const string_type file_string() const; | |
|       const string_type directory_string() const { return file_string(); } | |
| 
 | |
|       const external_string_type external_file_string() const { return Traits::to_external( *this, file_string() ); } | |
|       const external_string_type external_directory_string() const { return Traits::to_external( *this, directory_string() ); } | |
| 
 | |
|       basic_path   root_path() const; | |
|       string_type  root_name() const; | |
|       string_type  root_directory() const; | |
|       basic_path   relative_path() const; | |
|       basic_path   parent_path() const; | |
|       string_type  filename() const; | |
|       string_type  stem() const; | |
|       string_type  extension() const; | |
| 
 | |
| # ifndef BOOST_FILESYSTEM_NO_DEPRECATED | |
|       string_type  leaf() const            { return filename(); } | |
|       basic_path   branch_path() const     { return parent_path(); } | |
|       bool         has_leaf() const        { return !m_path.empty(); } | |
|       bool         has_branch_path() const { return !parent_path().empty(); } | |
| # endif | |
|  | |
|       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   { return !relative_path().empty(); } | |
|       bool has_filename() const        { return !m_path.empty(); } | |
|       bool has_parent_path() const     { return !parent_path().empty(); } | |
| 
 | |
|       // iterators | |
|       class iterator : public boost::iterator_facade< | |
|         iterator, | |
|         string_type const, | |
|         boost::bidirectional_traversal_tag > | |
|       { | |
|       private: | |
|         friend class boost::iterator_core_access; | |
|         friend class boost::BOOST_FILESYSTEM2_NAMESPACE::basic_path<String, Traits>; | |
| 
 | |
|         const string_type & dereference() const | |
|           { return m_name; } | |
|         bool equal( const iterator & rhs ) const | |
|           { return m_path_ptr == rhs.m_path_ptr && m_pos == rhs.m_pos; } | |
| 
 | |
|         friend class boost::BOOST_FILESYSTEM2_NAMESPACE::detail::iterator_helper<path_type>; | |
| 
 | |
|         void increment() | |
|         {  | |
|           boost::BOOST_FILESYSTEM2_NAMESPACE::detail::iterator_helper<path_type>::do_increment( | |
|             *this ); | |
|         } | |
|         void decrement() | |
|         {  | |
|           boost::BOOST_FILESYSTEM2_NAMESPACE::detail::iterator_helper<path_type>::do_decrement( | |
|             *this ); | |
|         } | |
| 
 | |
|         string_type             m_name;     // current element | |
|         const basic_path *      m_path_ptr; // path being iterated over | |
|         typename string_type::size_type  m_pos;  // position of name in | |
|                                             // path_ptr->string(). The | |
|                                             // end() iterator is indicated by  | |
|                                             // pos == path_ptr->m_path.size() | |
|       }; // iterator | |
|  | |
|       typedef iterator const_iterator; | |
| 
 | |
|       iterator begin() const; | |
|       iterator end() const; | |
| 
 | |
|     private: | |
|       // Note: This is an implementation for POSIX and Windows, where there | |
|       // are only minor differences between generic and native path grammars. | |
|       // Private members might be quite different in other implementations, | |
|       // particularly where there were wide differences between portable and | |
|       // native path formats, or between file_string() and | |
|       // directory_string() formats, or simply that the implementation | |
|       // was willing expend additional memory to achieve greater speed for | |
|       // some operations at the expense of other operations. | |
|  | |
|       string_type  m_path; // invariant: portable path grammar | |
|                            // on Windows, backslashes converted to slashes | |
|  | |
| #   ifdef BOOST_CYGWIN_PATH | |
|       bool m_cygwin_root; // if present, m_path[0] was slash. note: initialization | |
|                           // done by append | |
| #   endif   | |
|  | |
|       void m_append_separator_if_needed(); | |
|       void m_append( value_type value ); // converts Windows alt_separator | |
|  | |
|       // Was qualified; como433beta8 reports: | |
|       //    warning #427-D: qualified name is not allowed in member declaration  | |
|       friend class iterator; | |
|       friend class boost::BOOST_FILESYSTEM2_NAMESPACE::detail::iterator_helper<path_type>; | |
| 
 | |
|       // Deprecated features ease transition for existing code. Don't use these | |
|       // in new code. | |
| # ifndef BOOST_FILESYSTEM_NO_DEPRECATED | |
|     public: | |
|       typedef bool (*name_check)( const std::string & name ); | |
|       basic_path( const string_type & str, name_check ) { operator/=( str ); } | |
|       basic_path( const typename string_type::value_type * s, name_check ) | |
|         { operator/=( s );} | |
|       string_type native_file_string() const { return file_string(); } | |
|       string_type native_directory_string() const { return directory_string(); } | |
|       static bool default_name_check_writable() { return false; }  | |
|       static void default_name_check( name_check ) {} | |
|       static name_check default_name_check() { return 0; } | |
|       basic_path & canonize(); | |
|       basic_path & normalize(); | |
| # endif | |
|     }; | |
| 
 | |
|   //  basic_path non-member functions  ---------------------------------------// | |
|  | |
|     template< class String, class Traits > | |
|     inline void swap( basic_path<String, Traits> & lhs, | |
|                basic_path<String, Traits> & rhs ) { lhs.swap( rhs ); } | |
| 
 | |
|     template< class String, class Traits > | |
|     bool operator<( const basic_path<String, Traits> & lhs, const basic_path<String, Traits> & rhs ) | |
|     { | |
|       return std::lexicographical_compare( | |
|         lhs.begin(), lhs.end(), rhs.begin(), rhs.end() ); | |
|     } | |
| 
 | |
|     template< class String, class Traits > | |
|     bool operator<( const typename basic_path<String, Traits>::string_type::value_type * lhs, | |
|                     const basic_path<String, Traits> & rhs ) | |
|     { | |
|       basic_path<String, Traits> tmp( lhs ); | |
|       return std::lexicographical_compare( | |
|         tmp.begin(), tmp.end(), rhs.begin(), rhs.end() ); | |
|     } | |
| 
 | |
|     template< class String, class Traits > | |
|     bool operator<( const typename basic_path<String, Traits>::string_type & lhs, | |
|                     const basic_path<String, Traits> & rhs ) | |
|     { | |
|       basic_path<String, Traits> tmp( lhs ); | |
|       return std::lexicographical_compare( | |
|         tmp.begin(), tmp.end(), rhs.begin(), rhs.end() ); | |
|     } | |
| 
 | |
|     template< class String, class Traits > | |
|     bool operator<( const basic_path<String, Traits> & lhs, | |
|                     const typename basic_path<String, Traits>::string_type::value_type * rhs ) | |
|     { | |
|       basic_path<String, Traits> tmp( rhs ); | |
|       return std::lexicographical_compare( | |
|         lhs.begin(), lhs.end(), tmp.begin(), tmp.end() ); | |
|     } | |
| 
 | |
|     template< class String, class Traits > | |
|     bool operator<( const basic_path<String, Traits> & lhs, | |
|                     const typename basic_path<String, Traits>::string_type & rhs ) | |
|     { | |
|       basic_path<String, Traits> tmp( rhs ); | |
|       return std::lexicographical_compare( | |
|         lhs.begin(), lhs.end(), tmp.begin(), tmp.end() ); | |
|     } | |
| 
 | |
|     //  operator == uses hand-written compare rather than !(lhs < rhs) && !(rhs < lhs) | |
|     //  because the result is the same yet the direct compare is much more efficient | |
|     //  than lexicographical_compare, which would also be called twice. | |
|  | |
|     template< class String, class Traits > | |
|     inline bool operator==( const basic_path<String, Traits> & lhs, | |
|                     const typename basic_path<String, Traits>::string_type::value_type * rhs ) | |
|     { | |
|       typedef typename | |
|         boost::BOOST_FILESYSTEM2_NAMESPACE::basic_path<String, Traits> path_type; | |
|       const typename path_type::string_type::value_type * l (lhs.string().c_str()); | |
|       while ( (*l == *rhs | |
| #      ifdef BOOST_WINDOWS_PATH | |
|         || (*l == path_alt_separator<path_type>::value && *rhs == slash<path_type>::value)  | |
|             || (*l == slash<path_type>::value && *rhs == path_alt_separator<path_type>::value) | |
| #      endif | |
|         ) && *l ) { ++l; ++rhs; } | |
|       return *l == *rhs | |
| #      ifdef BOOST_WINDOWS_PATH | |
|         || (*l == path_alt_separator<path_type>::value && *rhs == slash<path_type>::value)  | |
|           || (*l == slash<path_type>::value && *rhs == path_alt_separator<path_type>::value) | |
| #      endif | |
|         ;   | |
|     } | |
| 
 | |
|     template< class String, class Traits > | |
|     inline bool operator==( const basic_path<String, Traits> & lhs, | |
|                             const basic_path<String, Traits> & rhs ) | |
|     {  | |
|       return lhs == rhs.string().c_str(); | |
|     } | |
| 
 | |
|     template< class String, class Traits > | |
|     inline bool operator==( const typename basic_path<String, Traits>::string_type::value_type * lhs, | |
|                     const basic_path<String, Traits> & rhs ) | |
|     { | |
|       return rhs == lhs; | |
|     } | |
| 
 | |
|     template< class String, class Traits > | |
|     inline bool operator==( const typename basic_path<String, Traits>::string_type & lhs, | |
|                     const basic_path<String, Traits> & rhs ) | |
|     { | |
|       return rhs == lhs.c_str(); | |
|     } | |
| 
 | |
|     template< class String, class Traits > | |
|     inline bool operator==( const basic_path<String, Traits> & lhs, | |
|                     const typename basic_path<String, Traits>::string_type & rhs ) | |
|     { | |
|       return lhs == rhs.c_str(); | |
|     } | |
| 
 | |
|     template< class String, class Traits > | |
|     inline bool operator!=( const basic_path<String, Traits> & lhs, | |
|       const basic_path<String, Traits> & rhs ) | |
|         { return !(lhs == rhs); } | |
|      | |
|     template< class String, class Traits > | |
|     inline bool operator!=( const typename basic_path<String, | |
|       Traits>::string_type::value_type * lhs, | |
|         const basic_path<String, Traits> & rhs ) | |
|         { return !(lhs == rhs); } | |
| 
 | |
|     template< class String, class Traits > | |
|     inline bool operator!=( const typename basic_path<String, Traits>::string_type & lhs, | |
|       const basic_path<String, Traits> & rhs ) | |
|         { return !(lhs == rhs); } | |
| 
 | |
|     template< class String, class Traits > | |
|     inline bool operator!=( const basic_path<String, Traits> & lhs, | |
|       const typename basic_path<String, Traits>::string_type::value_type * rhs ) | |
|         { return !(lhs == rhs); } | |
| 
 | |
|     template< class String, class Traits > | |
|     inline bool operator!=( const basic_path<String, Traits> & lhs, | |
|       const typename basic_path<String, Traits>::string_type & rhs ) | |
|         { return !(lhs == rhs); } | |
| 
 | |
|     template< class String, class Traits > | |
|     inline bool operator>( const basic_path<String, Traits> & lhs, const basic_path<String, Traits> & rhs ) { return rhs < lhs; } | |
|      | |
|     template< class String, class Traits > | |
|     inline bool operator>( const typename basic_path<String, Traits>::string_type::value_type * lhs, | |
|                     const basic_path<String, Traits> & rhs ) { return rhs < basic_path<String, Traits>(lhs); } | |
| 
 | |
|     template< class String, class Traits > | |
|     inline bool operator>( const typename basic_path<String, Traits>::string_type & lhs, | |
|                     const basic_path<String, Traits> & rhs ) { return rhs < basic_path<String, Traits>(lhs); } | |
| 
 | |
|     template< class String, class Traits > | |
|     inline bool operator>( const basic_path<String, Traits> & lhs, | |
|                     const typename basic_path<String, Traits>::string_type::value_type * rhs ) | |
|                     { return basic_path<String, Traits>(rhs) < lhs; } | |
| 
 | |
|     template< class String, class Traits > | |
|     inline bool operator>( const basic_path<String, Traits> & lhs, | |
|                     const typename basic_path<String, Traits>::string_type & rhs ) | |
|                     { return basic_path<String, Traits>(rhs) < lhs; } | |
| 
 | |
|     template< class String, class Traits > | |
|     inline bool operator<=( const basic_path<String, Traits> & lhs, const basic_path<String, Traits> & rhs ) { return !(rhs < lhs); } | |
|      | |
|     template< class String, class Traits > | |
|     inline bool operator<=( const typename basic_path<String, Traits>::string_type::value_type * lhs, | |
|                     const basic_path<String, Traits> & rhs ) { return !(rhs < basic_path<String, Traits>(lhs)); } | |
| 
 | |
|     template< class String, class Traits > | |
|     inline bool operator<=( const typename basic_path<String, Traits>::string_type & lhs, | |
|                     const basic_path<String, Traits> & rhs ) { return !(rhs < basic_path<String, Traits>(lhs)); } | |
| 
 | |
|     template< class String, class Traits > | |
|     inline bool operator<=( const basic_path<String, Traits> & lhs, | |
|                     const typename basic_path<String, Traits>::string_type::value_type * rhs ) | |
|                     { return !(basic_path<String, Traits>(rhs) < lhs); } | |
| 
 | |
|     template< class String, class Traits > | |
|     inline bool operator<=( const basic_path<String, Traits> & lhs, | |
|                     const typename basic_path<String, Traits>::string_type & rhs ) | |
|                     { return !(basic_path<String, Traits>(rhs) < lhs); } | |
| 
 | |
|     template< class String, class Traits > | |
|     inline bool operator>=( const basic_path<String, Traits> & lhs, const basic_path<String, Traits> & rhs ) { return !(lhs < rhs); } | |
|      | |
|     template< class String, class Traits > | |
|     inline bool operator>=( const typename basic_path<String, Traits>::string_type::value_type * lhs, | |
|                     const basic_path<String, Traits> & rhs ) { return !(lhs < basic_path<String, Traits>(rhs)); } | |
| 
 | |
|     template< class String, class Traits > | |
|     inline bool operator>=( const typename basic_path<String, Traits>::string_type & lhs, | |
|                     const basic_path<String, Traits> & rhs ) { return !(lhs < basic_path<String, Traits>(rhs)); } | |
| 
 | |
|     template< class String, class Traits > | |
|     inline bool operator>=( const basic_path<String, Traits> & lhs, | |
|                     const typename basic_path<String, Traits>::string_type::value_type * rhs ) | |
|                     { return !(basic_path<String, Traits>(lhs) < rhs); } | |
| 
 | |
|     template< class String, class Traits > | |
|     inline bool operator>=( const basic_path<String, Traits> & lhs, | |
|                     const typename basic_path<String, Traits>::string_type & rhs ) | |
|                     { return !(basic_path<String, Traits>(lhs) < rhs); } | |
| 
 | |
|     // operator / | |
|  | |
|     template< class String, class Traits > | |
|     inline basic_path<String, Traits> operator/(  | |
|       const basic_path<String, Traits> & lhs, | |
|       const basic_path<String, Traits> & rhs ) | |
|       { return basic_path<String, Traits>( lhs ) /= rhs; } | |
| 
 | |
|     template< class String, class Traits > | |
|     inline basic_path<String, Traits> operator/(  | |
|       const basic_path<String, Traits> & lhs, | |
|       const typename String::value_type * rhs ) | |
|       { return basic_path<String, Traits>( lhs ) /= | |
|           basic_path<String, Traits>( rhs ); } | |
| 
 | |
|     template< class String, class Traits > | |
|     inline basic_path<String, Traits> operator/(  | |
|       const basic_path<String, Traits> & lhs, const String & rhs ) | |
|       { return basic_path<String, Traits>( lhs ) /= | |
|           basic_path<String, Traits>( rhs ); } | |
| 
 | |
|     template< class String, class Traits > | |
|     inline basic_path<String, Traits> operator/(  | |
|       const typename String::value_type * lhs, | |
|       const basic_path<String, Traits> & rhs ) | |
|       { return basic_path<String, Traits>( lhs ) /= rhs; } | |
| 
 | |
|     template< class String, class Traits > | |
|     inline basic_path<String, Traits> operator/( | |
|       const String & lhs, const basic_path<String, Traits> & rhs ) | |
|       { return basic_path<String, Traits>( lhs ) /= rhs; } | |
|     | |
|     //  inserters and extractors  --------------------------------------------// | |
|  | |
| // bypass VC++ 7.0 and earlier, and broken Borland compilers | |
| # if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) && !BOOST_WORKAROUND(__BORLANDC__, < 0x610) | |
|     template< class Path > | |
|     std::basic_ostream< typename Path::string_type::value_type, | |
|       typename Path::string_type::traits_type > & | |
|       operator<< | |
|       ( std::basic_ostream< typename Path::string_type::value_type, | |
|       typename Path::string_type::traits_type >& os, const Path & ph ) | |
|     { | |
|       os << ph.string(); | |
|       return os; | |
|     } | |
| 
 | |
|     template< class Path > | |
|     std::basic_istream< typename Path::string_type::value_type, | |
|       typename Path::string_type::traits_type > & | |
|       operator>> | |
|       ( std::basic_istream< typename Path::string_type::value_type, | |
|       typename Path::string_type::traits_type >& is, Path & ph ) | |
|     { | |
|       typename Path::string_type str; | |
|       std::getline(is, str);  // See ticket 3863 | |
|       ph = str; | |
|       return is; | |
|     } | |
| # elif BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) | |
|     template< class String, class Traits > | |
|     std::basic_ostream< BOOST_DEDUCED_TYPENAME String::value_type, | |
|       BOOST_DEDUCED_TYPENAME String::traits_type > & | |
|       operator<< | |
|       ( std::basic_ostream< BOOST_DEDUCED_TYPENAME String::value_type, | |
|           BOOST_DEDUCED_TYPENAME String::traits_type >& os,  | |
|         const basic_path< String, Traits > & ph ) | |
|     { | |
|       os << ph.string(); | |
|       return os; | |
|     } | |
| 
 | |
|     template< class String, class Traits > | |
|     std::basic_istream< BOOST_DEDUCED_TYPENAME String::value_type,  | |
|       BOOST_DEDUCED_TYPENAME String::traits_type > & | |
|       operator>> | |
|       ( std::basic_istream< BOOST_DEDUCED_TYPENAME String::value_type, | |
|           BOOST_DEDUCED_TYPENAME String::traits_type> & is, | |
|         basic_path< String, Traits > & ph ) | |
|     { | |
|       String str; | |
|       std::getline(is, str);  // See ticket 3863 | |
|       ph = str; | |
|       return is; | |
|     } | |
| # endif | |
|  | |
|     //  basic_filesystem_error helpers  --------------------------------------// | |
|  | |
|     //  Originally choice of implementation was done via specialization of | |
|     //  basic_filesystem_error::what(). Several compilers (GCC, aCC, etc.) | |
|     //  couldn't handle that, so the choice is now accomplished by overloading. | |
|  | |
|     namespace detail | |
|     { | |
|       // BOOST_FILESYSTEM_DECL version works for VC++ but not GCC. Go figure! | |
|       inline | |
|       const char * what( const char * sys_err_what, | |
|         const path & path1_arg, const path & path2_arg, std::string & target ) | |
|       { | |
|         try | |
|         { | |
|           if ( target.empty() ) | |
|           { | |
|             target = sys_err_what; | |
|             if ( !path1_arg.empty() ) | |
|             { | |
|               target += ": \""; | |
|               target += path1_arg.file_string(); | |
|               target += "\""; | |
|             } | |
|             if ( !path2_arg.empty() ) | |
|             { | |
|               target += ", \""; | |
|               target += path2_arg.file_string(); | |
|               target += "\""; | |
|             } | |
|           } | |
|           return target.c_str(); | |
|         } | |
|         catch (...) | |
|         { | |
|           return sys_err_what; | |
|         } | |
|       } | |
| 
 | |
|       template<class Path> | |
|       const char * what( const char * sys_err_what, | |
|         const Path & /*path1_arg*/, const Path & /*path2_arg*/, std::string & /*target*/ ) | |
|       { | |
|         return sys_err_what; | |
|       } | |
|     } | |
| 
 | |
|     //  basic_filesystem_error  ----------------------------------------------// | |
|  | |
|     template<class Path> | |
|     class basic_filesystem_error : public system::system_error | |
|     { | |
|     // see http://www.boost.org/more/error_handling.html for design rationale | |
|     public: | |
|       // compiler generates copy constructor and copy assignment | |
|  | |
|       typedef Path path_type; | |
| 
 | |
|       basic_filesystem_error( const std::string & what_arg, | |
|         system::error_code ec ); | |
| 
 | |
|       basic_filesystem_error( const std::string & what_arg, | |
|         const path_type & path1_arg, system::error_code ec ); | |
| 
 | |
|       basic_filesystem_error( const std::string & what_arg, const path_type & path1_arg, | |
|         const path_type & path2_arg, system::error_code ec ); | |
| 
 | |
|       ~basic_filesystem_error() throw() {} | |
| 
 | |
|       const path_type & path1() const | |
|       { | |
|         static const path_type empty_path; | |
|         return m_imp_ptr.get() ? m_imp_ptr->m_path1 : empty_path ; | |
|       } | |
|       const path_type & path2() const | |
|       { | |
|         static const path_type empty_path; | |
|         return m_imp_ptr.get() ? m_imp_ptr->m_path2 : empty_path ; | |
|       } | |
| 
 | |
|       const char * what() const throw() | |
|       {  | |
|         if ( !m_imp_ptr.get() ) | |
|           return system::system_error::what(); | |
|         return detail::what( system::system_error::what(), m_imp_ptr->m_path1, | |
|           m_imp_ptr->m_path2, m_imp_ptr->m_what );   | |
|       } | |
| 
 | |
|     private: | |
|       struct m_imp | |
|       { | |
|         path_type                 m_path1; // may be empty() | |
|         path_type                 m_path2; // may be empty() | |
|         std::string               m_what;  // not built until needed | |
|       }; | |
|       boost::shared_ptr<m_imp> m_imp_ptr; | |
|     }; | |
| 
 | |
|     typedef basic_filesystem_error<path> filesystem_error; | |
| 
 | |
| # ifndef BOOST_FILESYSTEM2_NARROW_ONLY | |
|     typedef basic_filesystem_error<wpath> wfilesystem_error; | |
| # endif | |
|  | |
|   //  path::name_checks  -----------------------------------------------------// | |
|  | |
|     BOOST_FILESYSTEM_DECL bool portable_posix_name( const std::string & name ); | |
|     BOOST_FILESYSTEM_DECL bool windows_name( const std::string & name ); | |
|     BOOST_FILESYSTEM_DECL bool portable_name( const std::string & name ); | |
|     BOOST_FILESYSTEM_DECL bool portable_directory_name( const std::string & name ); | |
|     BOOST_FILESYSTEM_DECL bool portable_file_name( const std::string & name ); | |
|     BOOST_FILESYSTEM_DECL bool native( const std::string & name ); | |
|     inline bool no_check( const std::string & ) | |
|       { return true; } | |
| 
 | |
| // implementation  -----------------------------------------------------------// | |
|  | |
|     namespace detail | |
|     { | |
| 
 | |
|       //  is_separator helper ------------------------------------------------// | |
|  | |
|       template<class Path> | |
|       inline  bool is_separator( typename Path::string_type::value_type c ) | |
|       { | |
|         return c == slash<Path>::value | |
| #     ifdef BOOST_WINDOWS_PATH | |
|           || c == path_alt_separator<Path>::value | |
| #     endif | |
|           ; | |
|       } | |
| 
 | |
|       // filename_pos helper  ----------------------------------------------------// | |
|  | |
|       template<class String, class Traits> | |
|       typename String::size_type filename_pos( | |
|         const String & str, // precondition: portable generic path grammar | |
|         typename String::size_type end_pos ) // end_pos is past-the-end position | |
|       // return 0 if str itself is filename (or empty) | |
|       { | |
|         typedef typename | |
|           boost::BOOST_FILESYSTEM2_NAMESPACE::basic_path<String, Traits> path_type; | |
| 
 | |
|         // case: "//" | |
|         if ( end_pos == 2  | |
|           && str[0] == slash<path_type>::value | |
|           && str[1] == slash<path_type>::value ) return 0; | |
| 
 | |
|         // case: ends in "/" | |
|         if ( end_pos && str[end_pos-1] == slash<path_type>::value ) | |
|           return end_pos-1; | |
|          | |
|         // set pos to start of last element | |
|         typename String::size_type pos( | |
|           str.find_last_of( slash<path_type>::value, end_pos-1 ) ); | |
| #       ifdef BOOST_WINDOWS_PATH | |
|         if ( pos == String::npos ) | |
|           pos = str.find_last_of( path_alt_separator<path_type>::value, end_pos-1 ); | |
|         if ( pos == String::npos ) | |
|           pos = str.find_last_of( colon<path_type>::value, end_pos-2 ); | |
| #       endif | |
|  | |
|         return ( pos == String::npos // path itself must be a filename (or empty) | |
|           || (pos == 1 && str[0] == slash<path_type>::value) ) // or net | |
|             ? 0 // so filename is entire string | |
|             : pos + 1; // or starts after delimiter | |
|       } | |
| 
 | |
|       // first_element helper  -----------------------------------------------// | |
|       //   sets pos and len of first element, excluding extra separators | |
|       //   if src.empty(), sets pos,len, to 0,0. | |
|  | |
|       template<class String, class Traits> | |
|         void first_element( | |
|           const String & src, // precondition: portable generic path grammar | |
|           typename String::size_type & element_pos, | |
|           typename String::size_type & element_size, | |
| #       if !BOOST_WORKAROUND( BOOST_MSVC, <= 1310 ) // VC++ 7.1 | |
|           typename String::size_type size = String::npos | |
| #       else | |
|           typename String::size_type size = -1 | |
| #       endif | |
|           ) | |
|       { | |
|         if ( size == String::npos ) size = src.size(); | |
|         element_pos = 0; | |
|         element_size = 0; | |
|         if ( src.empty() ) return; | |
| 
 | |
|         typedef typename boost::BOOST_FILESYSTEM2_NAMESPACE::basic_path<String, Traits> path_type; | |
| 
 | |
|         typename String::size_type cur(0); | |
|          | |
|         // deal with // [network] | |
|         if ( size >= 2 && src[0] == slash<path_type>::value | |
|           && src[1] == slash<path_type>::value | |
|           && (size == 2 | |
|             || src[2] != slash<path_type>::value) ) | |
|         {  | |
|           cur += 2; | |
|           element_size += 2; | |
|         } | |
| 
 | |
|         // leading (not non-network) separator | |
|         else if ( src[0] == slash<path_type>::value ) | |
|         { | |
|           ++element_size; | |
|           // bypass extra leading separators | |
|           while ( cur+1 < size | |
|             && src[cur+1] == slash<path_type>::value ) | |
|           { | |
|             ++cur; | |
|             ++element_pos; | |
|           } | |
|           return; | |
|         } | |
| 
 | |
|         // at this point, we have either a plain name, a network name, | |
|         // or (on Windows only) a device name | |
|  | |
|         // find the end | |
|         while ( cur < size | |
| #         ifdef BOOST_WINDOWS_PATH | |
|           && src[cur] != colon<path_type>::value | |
| #         endif | |
|           && src[cur] != slash<path_type>::value ) | |
|         { | |
|           ++cur; | |
|           ++element_size; | |
|         } | |
| 
 | |
| #       ifdef BOOST_WINDOWS_PATH | |
|         if ( cur == size ) return; | |
|         // include device delimiter | |
|         if ( src[cur] == colon<path_type>::value ) | |
|           { ++element_size; } | |
| #       endif | |
|  | |
|         return; | |
|       } | |
| 
 | |
|       // root_directory_start helper  ----------------------------------------// | |
|  | |
|       template<class String, class Traits> | |
|       typename String::size_type root_directory_start( | |
|         const String & s, // precondition: portable generic path grammar | |
|         typename String::size_type size ) | |
|       // return npos if no root_directory found | |
|       { | |
|         typedef typename boost::BOOST_FILESYSTEM2_NAMESPACE::basic_path<String, Traits> path_type; | |
| 
 | |
| #     ifdef BOOST_WINDOWS_PATH | |
|         // case "c:/" | |
|         if ( size > 2 | |
|           && s[1] == colon<path_type>::value | |
|           && s[2] == slash<path_type>::value ) return 2; | |
| #     endif | |
|  | |
|         // case "//" | |
|         if ( size == 2 | |
|           && s[0] == slash<path_type>::value | |
|           && s[1] == slash<path_type>::value ) return String::npos; | |
| 
 | |
|         // case "//net {/}" | |
|         if ( size > 3 | |
|           && s[0] == slash<path_type>::value | |
|           && s[1] == slash<path_type>::value | |
|           && s[2] != slash<path_type>::value ) | |
|         { | |
|           typename String::size_type pos( | |
|             s.find( slash<path_type>::value, 2 ) ); | |
|           return pos < size ? pos : String::npos; | |
|         } | |
|          | |
|         // case "/" | |
|         if ( size > 0 && s[0] == slash<path_type>::value ) return 0; | |
| 
 | |
|         return String::npos; | |
|       } | |
| 
 | |
|       // is_non_root_slash helper  -------------------------------------------// | |
|  | |
|       template<class String, class Traits> | |
|       bool is_non_root_slash( const String & str, | |
|         typename String::size_type pos ) // pos is position of the slash | |
|       { | |
|         typedef typename | |
|           boost::BOOST_FILESYSTEM2_NAMESPACE::basic_path<String, Traits> | |
|             path_type; | |
| 
 | |
|         BOOST_ASSERT( !str.empty() && str[pos] == slash<path_type>::value | |
|           && "precondition violation" ); | |
| 
 | |
|         // subsequent logic expects pos to be for leftmost slash of a set | |
|         while ( pos > 0 && str[pos-1] == slash<path_type>::value ) | |
|           --pos; | |
| 
 | |
|         return  pos != 0 | |
|           && (pos <= 2 || str[1] != slash<path_type>::value | |
|             || str.find( slash<path_type>::value, 2 ) != pos) | |
| #       ifdef BOOST_WINDOWS_PATH | |
|           && (pos !=2 || str[1] != colon<path_type>::value) | |
| #       endif | |
|             ; | |
|       } | |
|     } // namespace detail | |
|  | |
|     // decomposition functions  ----------------------------------------------// | |
|  | |
|     template<class String, class Traits> | |
|     String basic_path<String, Traits>::filename() const | |
|     { | |
|       typename String::size_type end_pos( | |
|         detail::filename_pos<String, Traits>( m_path, m_path.size() ) ); | |
|       return (m_path.size() | |
|                 && end_pos | |
|                 && m_path[end_pos] == slash<path_type>::value | |
|                 && detail::is_non_root_slash< String, Traits >(m_path, end_pos)) | |
|         ? String( 1, dot<path_type>::value ) | |
|         : m_path.substr( end_pos ); | |
|     } | |
| 
 | |
|     template<class String, class Traits> | |
|     String basic_path<String, Traits>::stem() const | |
|     { | |
|       string_type name = filename(); | |
|       typename string_type::size_type n = name.rfind(dot<path_type>::value); | |
|       return name.substr(0, n); | |
|     } | |
| 
 | |
|     template<class String, class Traits> | |
|     String basic_path<String, Traits>::extension() const | |
|     { | |
|       string_type name = filename(); | |
|       typename string_type::size_type n = name.rfind(dot<path_type>::value); | |
|       if (n != string_type::npos) | |
|         return name.substr(n); | |
|       else | |
|         return string_type(); | |
|     } | |
| 
 | |
|     template<class String, class Traits> | |
|     basic_path<String, Traits> basic_path<String, Traits>::parent_path() const | |
|     { | |
|       typename String::size_type end_pos( | |
|         detail::filename_pos<String, Traits>( m_path, m_path.size() ) ); | |
| 
 | |
|       bool filename_was_separator( m_path.size() | |
|         && m_path[end_pos] == slash<path_type>::value ); | |
| 
 | |
|       // skip separators unless root directory | |
|       typename string_type::size_type root_dir_pos( detail::root_directory_start | |
|         <string_type, traits_type>( m_path, end_pos ) ); | |
|       for ( ;  | |
|         end_pos > 0 | |
|         && (end_pos-1) != root_dir_pos | |
|         && m_path[end_pos-1] == slash<path_type>::value | |
|         ; | |
|         --end_pos ) {} | |
| 
 | |
|      return (end_pos == 1 && root_dir_pos == 0 && filename_was_separator) | |
|        ? path_type() | |
|        : path_type( m_path.substr( 0, end_pos ) ); | |
|     } | |
| 
 | |
|     template<class String, class Traits> | |
|     basic_path<String, Traits> basic_path<String, Traits>::relative_path() const | |
|     { | |
|       iterator itr( begin() ); | |
|       for ( ; itr.m_pos != m_path.size() | |
|           && (itr.m_name[0] == slash<path_type>::value | |
| #     ifdef BOOST_WINDOWS_PATH | |
|           || itr.m_name[itr.m_name.size()-1] | |
|             == colon<path_type>::value | |
| #     endif | |
|              ); ++itr ) {} | |
| 
 | |
|       return basic_path<String, Traits>( m_path.substr( itr.m_pos ) ); | |
|     } | |
| 
 | |
|     template<class String, class Traits> | |
|     String basic_path<String, Traits>::root_name() const | |
|     { | |
|       iterator itr( begin() ); | |
| 
 | |
|       return ( itr.m_pos != m_path.size() | |
|         && ( | |
|             ( itr.m_name.size() > 1 | |
|               && itr.m_name[0] == slash<path_type>::value | |
|               && itr.m_name[1] == slash<path_type>::value | |
|             ) | |
| #     ifdef BOOST_WINDOWS_PATH | |
|           || itr.m_name[itr.m_name.size()-1] | |
|             == colon<path_type>::value | |
| #     endif | |
|            ) ) | |
|         ? *itr | |
|         : String(); | |
|     } | |
| 
 | |
|     template<class String, class Traits> | |
|     String basic_path<String, Traits>::root_directory() const | |
|     { | |
|       typename string_type::size_type start( | |
|         detail::root_directory_start<String, Traits>( m_path, m_path.size() ) ); | |
| 
 | |
|       return start == string_type::npos | |
|         ? string_type() | |
|         : m_path.substr( start, 1 ); | |
|     } | |
| 
 | |
|     template<class String, class Traits> | |
|     basic_path<String, Traits> basic_path<String, Traits>::root_path() const | |
|     { | |
|       // even on POSIX, root_name() is non-empty() on network paths | |
|       return basic_path<String, Traits>( root_name() ) /= root_directory(); | |
|     } | |
| 
 | |
|     // path query functions  -------------------------------------------------// | |
|  | |
|     template<class String, class Traits> | |
|     inline bool basic_path<String, Traits>::is_complete() const | |
|     { | |
| #   ifdef BOOST_WINDOWS_PATH | |
|       return has_root_name() && has_root_directory(); | |
| #   else | |
|       return has_root_directory(); | |
| #   endif | |
|     } | |
| 
 | |
|     template<class String, class Traits> | |
|     inline bool basic_path<String, Traits>::has_root_path() const | |
|     { | |
|       return !root_path().empty(); | |
|     } | |
| 
 | |
|     template<class String, class Traits> | |
|     inline bool basic_path<String, Traits>::has_root_name() const | |
|     { | |
|       return !root_name().empty(); | |
|     } | |
| 
 | |
|     template<class String, class Traits> | |
|     inline bool basic_path<String, Traits>::has_root_directory() const | |
|     { | |
|       return !root_directory().empty(); | |
|     } | |
| 
 | |
|     // append  ---------------------------------------------------------------// | |
|  | |
|     template<class String, class Traits> | |
|     void basic_path<String, Traits>::m_append_separator_if_needed() | |
|     // requires: !empty() | |
|     { | |
|       if ( | |
| #       ifdef BOOST_WINDOWS_PATH | |
|         *(m_path.end()-1) != colon<path_type>::value &&  | |
| #       endif | |
|         *(m_path.end()-1) != slash<path_type>::value ) | |
|       { | |
|         m_path += slash<path_type>::value; | |
|       } | |
|     } | |
|        | |
|     template<class String, class Traits> | |
|     void basic_path<String, Traits>::m_append( value_type value ) | |
|     { | |
| #   ifdef BOOST_CYGWIN_PATH | |
|       if ( m_path.empty() ) m_cygwin_root = (value == slash<path_type>::value); | |
| #   endif | |
|  | |
| #   ifdef BOOST_WINDOWS_PATH | |
|       // for BOOST_WINDOWS_PATH, convert alt_separator ('\') to separator ('/') | |
|       m_path += ( value == path_alt_separator<path_type>::value | |
|         ? slash<path_type>::value | |
|         : value ); | |
| #   else | |
|       m_path += value; | |
| #   endif | |
|     } | |
|      | |
|     // except that it wouldn't work for BOOST_NO_MEMBER_TEMPLATES compilers, | |
|     // the append() member template could replace this code. | |
|     template<class String, class Traits> | |
|     basic_path<String, Traits> & basic_path<String, Traits>::operator /= | |
|       ( const value_type * next_p ) | |
|     { | |
|       // ignore escape sequence on POSIX or Windows | |
|       if ( *next_p == slash<path_type>::value | |
|         && *(next_p+1) == slash<path_type>::value | |
|         && *(next_p+2) == colon<path_type>::value ) next_p += 3; | |
|        | |
|       // append slash<path_type>::value if needed | |
|       if ( !empty() && *next_p != 0 | |
|         && !detail::is_separator<path_type>( *next_p ) ) | |
|       { m_append_separator_if_needed(); } | |
| 
 | |
|       for ( ; *next_p != 0; ++next_p ) m_append( *next_p ); | |
|       return *this; | |
|     } | |
| 
 | |
| # ifndef BOOST_NO_MEMBER_TEMPLATES | |
|     template<class String, class Traits> template <class InputIterator> | |
|       basic_path<String, Traits> & basic_path<String, Traits>::append( | |
|         InputIterator first, InputIterator last ) | |
|     { | |
|       // append slash<path_type>::value if needed | |
|       if ( !empty() && first != last | |
|         && !detail::is_separator<path_type>( *first ) ) | |
|       { m_append_separator_if_needed(); } | |
| 
 | |
|       // song-and-dance to avoid violating InputIterator requirements | |
|       // (which prohibit lookahead) in detecting a possible escape sequence | |
|       // (escape sequences are simply ignored on POSIX and Windows) | |
|       bool was_escape_sequence(true); | |
|       std::size_t append_count(0); | |
|       typename String::size_type initial_pos( m_path.size() ); | |
| 
 | |
|       for ( ; first != last && *first; ++first ) | |
|       { | |
|         if ( append_count == 0 && *first != slash<path_type>::value ) | |
|           was_escape_sequence = false; | |
|         if ( append_count == 1 && *first != slash<path_type>::value ) | |
|           was_escape_sequence = false; | |
|         if ( append_count == 2 && *first != colon<path_type>::value ) | |
|           was_escape_sequence = false; | |
|         m_append( *first ); | |
|         ++append_count; | |
|       } | |
| 
 | |
|       // erase escape sequence if any | |
|       if ( was_escape_sequence && append_count >= 3 ) | |
|         m_path.erase( initial_pos, 3 ); | |
| 
 | |
|       return *this; | |
|     } | |
| # endif | |
|  | |
| # ifndef BOOST_FILESYSTEM_NO_DEPRECATED | |
|  | |
|     // canonize  ------------------------------------------------------------// | |
|  | |
|     template<class String, class Traits> | |
|     basic_path<String, Traits> & basic_path<String, Traits>::canonize() | |
|     { | |
|       static const typename string_type::value_type dot_str[] | |
|         = { dot<path_type>::value, 0 }; | |
| 
 | |
|       if ( m_path.empty() ) return *this; | |
|          | |
|       path_type temp; | |
| 
 | |
|       for ( iterator itr( begin() ); itr != end(); ++itr ) | |
|       { | |
|         temp /= *itr; | |
|       }; | |
| 
 | |
|       if ( temp.empty() ) temp /= dot_str; | |
|       m_path = temp.m_path; | |
|       return *this; | |
|     } | |
| 
 | |
|     // normalize  ------------------------------------------------------------// | |
|  | |
|     template<class String, class Traits> | |
|     basic_path<String, Traits> & basic_path<String, Traits>::normalize() | |
|     { | |
|       static const typename string_type::value_type dot_str[] | |
|         = { dot<path_type>::value, 0 }; | |
| 
 | |
|       if ( m_path.empty() ) return *this; | |
|          | |
|       path_type temp; | |
|       iterator start( begin() ); | |
|       iterator last( end() ); | |
|       iterator stop( last-- ); | |
|       for ( iterator itr( start ); itr != stop; ++itr ) | |
|       { | |
|         // ignore "." except at start and last | |
|         if ( itr->size() == 1 | |
|           && (*itr)[0] == dot<path_type>::value | |
|           && itr != start | |
|           && itr != last ) continue; | |
| 
 | |
|         // ignore a name and following ".." | |
|         if ( !temp.empty() | |
|           && itr->size() == 2 | |
|           && (*itr)[0] == dot<path_type>::value | |
|           && (*itr)[1] == dot<path_type>::value ) // dot dot | |
|         { | |
|           string_type lf( temp.filename() );   | |
|           if ( lf.size() > 0   | |
|             && (lf.size() != 1 | |
|               || (lf[0] != dot<path_type>::value | |
|                 && lf[0] != slash<path_type>::value)) | |
|             && (lf.size() != 2  | |
|               || (lf[0] != dot<path_type>::value | |
|                 && lf[1] != dot<path_type>::value | |
| #             ifdef BOOST_WINDOWS_PATH | |
|                 && lf[1] != colon<path_type>::value | |
| #             endif | |
|                  ) | |
|                ) | |
|             ) | |
|           { | |
|             temp.remove_filename(); | |
|             // if not root directory, must also remove "/" if any | |
|             if ( temp.m_path.size() > 0 | |
|               && temp.m_path[temp.m_path.size()-1] | |
|                 == slash<path_type>::value ) | |
|             { | |
|               typename string_type::size_type rds( | |
|                 detail::root_directory_start<String,Traits>( temp.m_path, | |
|                   temp.m_path.size() ) ); | |
|               if ( rds == string_type::npos | |
|                 || rds != temp.m_path.size()-1 )  | |
|                 { temp.m_path.erase( temp.m_path.size()-1 ); } | |
|             } | |
| 
 | |
|             iterator next( itr ); | |
|             if ( temp.empty() && ++next != stop | |
|               && next == last && *last == dot_str ) temp /= dot_str; | |
|             continue; | |
|           } | |
|         } | |
| 
 | |
|         temp /= *itr; | |
|       }; | |
| 
 | |
|       if ( temp.empty() ) temp /= dot_str; | |
|       m_path = temp.m_path; | |
|       return *this; | |
|     } | |
| 
 | |
| # endif | |
|  | |
|     // modifiers  ------------------------------------------------------------// | |
|  | |
|     template<class String, class Traits> | |
|     basic_path<String, Traits> & basic_path<String, Traits>::remove_filename() | |
|     { | |
|       m_path.erase( | |
|         detail::filename_pos<String, Traits>( m_path, m_path.size() ) ); | |
|       return *this; | |
|     } | |
| 
 | |
|     template<class String, class Traits> | |
|     basic_path<String, Traits> & | |
|     basic_path<String, Traits>::replace_extension( const string_type & new_ext ) | |
|     { | |
|       // erase existing extension if any | |
|       string_type old_ext = extension(); | |
|       if ( !old_ext.empty() ) | |
|         m_path.erase( m_path.size() - old_ext.size() ); | |
| 
 | |
|       if ( !new_ext.empty() && new_ext[0] != dot<path_type>::value ) | |
|         m_path += dot<path_type>::value; | |
| 
 | |
|       m_path += new_ext; | |
| 
 | |
|       return *this; | |
|     } | |
| 
 | |
| 
 | |
|     // path conversion functions  --------------------------------------------// | |
|  | |
|     template<class String, class Traits> | |
|     const String | |
|     basic_path<String, Traits>::file_string() const | |
|     { | |
| #   ifdef BOOST_WINDOWS_PATH | |
|       // for Windows, use the alternate separator, and bypass extra  | |
|       // root separators | |
|  | |
|       typename string_type::size_type root_dir_start( | |
|         detail::root_directory_start<String, Traits>( m_path, m_path.size() ) ); | |
|       bool in_root( root_dir_start != string_type::npos ); | |
|       String s; | |
|       for ( typename string_type::size_type pos( 0 ); | |
|         pos != m_path.size(); ++pos ) | |
|       { | |
|         // special case // [net] | |
|         if ( pos == 0 && m_path.size() > 1 | |
|           && m_path[0] == slash<path_type>::value | |
|           && m_path[1] == slash<path_type>::value | |
|           && ( m_path.size() == 2  | |
|             || !detail::is_separator<path_type>( m_path[2] ) | |
|              ) ) | |
|         { | |
|           ++pos; | |
|           s += path_alt_separator<path_type>::value; | |
|           s += path_alt_separator<path_type>::value; | |
|           continue; | |
|         }    | |
| 
 | |
|         // bypass extra root separators | |
|         if ( in_root ) | |
|         {  | |
|           if ( s.size() > 0 | |
|             && s[s.size()-1] == path_alt_separator<path_type>::value | |
|             && m_path[pos] == slash<path_type>::value | |
|             ) continue; | |
|         } | |
| 
 | |
|         if ( m_path[pos] == slash<path_type>::value ) | |
|           s += path_alt_separator<path_type>::value; | |
|         else | |
|           s += m_path[pos]; | |
| 
 | |
|         if ( pos > root_dir_start | |
|           && m_path[pos] == slash<path_type>::value ) | |
|           { in_root = false; } | |
|       } | |
| #   ifdef BOOST_CYGWIN_PATH | |
|       if ( m_cygwin_root ) s[0] = slash<path_type>::value; | |
| #   endif | |
|       return s; | |
| #   else | |
|       return m_path; | |
| #   endif | |
|     } | |
| 
 | |
|     // iterator functions  ---------------------------------------------------// | |
|  | |
|     template<class String, class Traits> | |
|     typename basic_path<String, Traits>::iterator basic_path<String, Traits>::begin() const | |
|     { | |
|       iterator itr; | |
|       itr.m_path_ptr = this; | |
|       typename string_type::size_type element_size; | |
|       detail::first_element<String, Traits>( m_path, itr.m_pos, element_size ); | |
|       itr.m_name = m_path.substr( itr.m_pos, element_size ); | |
|       return itr; | |
|     } | |
| 
 | |
|     template<class String, class Traits> | |
|     typename basic_path<String, Traits>::iterator basic_path<String, Traits>::end() const | |
|       { | |
|         iterator itr; | |
|         itr.m_path_ptr = this; | |
|         itr.m_pos = m_path.size(); | |
|         return itr; | |
|       } | |
| 
 | |
|     namespace detail | |
|     { | |
|       //  do_increment  ------------------------------------------------------// | |
|  | |
|       template<class Path> | |
|       void iterator_helper<Path>::do_increment( iterator & itr ) | |
|       { | |
|         typedef typename Path::string_type string_type; | |
|         typedef typename Path::traits_type traits_type; | |
| 
 | |
|         BOOST_ASSERT( itr.m_pos < itr.m_path_ptr->m_path.size() && "basic_path::iterator increment past end()" ); | |
| 
 | |
|         bool was_net( itr.m_name.size() > 2 | |
|           && itr.m_name[0] == slash<Path>::value | |
|           && itr.m_name[1] == slash<Path>::value | |
|           && itr.m_name[2] != slash<Path>::value ); | |
| 
 | |
|         // increment to position past current element | |
|         itr.m_pos += itr.m_name.size(); | |
| 
 | |
|         // if end reached, create end iterator | |
|         if ( itr.m_pos == itr.m_path_ptr->m_path.size() ) | |
|         { | |
|           itr.m_name.erase( itr.m_name.begin(), itr.m_name.end() ); // VC++ 6.0 lib didn't supply clear()  | |
|           return; | |
|         } | |
| 
 | |
|         // process separator (Windows drive spec is only case not a separator) | |
|         if ( itr.m_path_ptr->m_path[itr.m_pos] == slash<Path>::value ) | |
|         { | |
|           // detect root directory | |
|           if ( was_net | |
|   #       ifdef BOOST_WINDOWS_PATH | |
|             // case "c:/" | |
|             || itr.m_name[itr.m_name.size()-1] == colon<Path>::value | |
|   #       endif | |
|              ) | |
|           { | |
|             itr.m_name = slash<Path>::value; | |
|             return; | |
|           } | |
| 
 | |
|           // bypass separators | |
|           while ( itr.m_pos != itr.m_path_ptr->m_path.size() | |
|             && itr.m_path_ptr->m_path[itr.m_pos] == slash<Path>::value ) | |
|             { ++itr.m_pos; } | |
| 
 | |
|           // detect trailing separator, and treat it as ".", per POSIX spec | |
|           if ( itr.m_pos == itr.m_path_ptr->m_path.size() | |
|             && detail::is_non_root_slash< string_type, traits_type >( | |
|                 itr.m_path_ptr->m_path, itr.m_pos-1 ) )  | |
|           { | |
|             --itr.m_pos; | |
|             itr.m_name = dot<Path>::value; | |
|             return; | |
|           } | |
|         } | |
| 
 | |
|         // get next element | |
|         typename string_type::size_type end_pos( | |
|           itr.m_path_ptr->m_path.find( slash<Path>::value, itr.m_pos ) ); | |
|         itr.m_name = itr.m_path_ptr->m_path.substr( itr.m_pos, end_pos - itr.m_pos ); | |
|       }  | |
| 
 | |
|       //  do_decrement  ------------------------------------------------------// | |
|  | |
|       template<class Path> | |
|       void iterator_helper<Path>::do_decrement( iterator & itr ) | |
|       {                                                                                 | |
|         BOOST_ASSERT( itr.m_pos && "basic_path::iterator decrement past begin()"  ); | |
| 
 | |
|         typedef typename Path::string_type string_type; | |
|         typedef typename Path::traits_type traits_type; | |
| 
 | |
|         typename string_type::size_type end_pos( itr.m_pos ); | |
| 
 | |
|         typename string_type::size_type root_dir_pos( | |
|           detail::root_directory_start<string_type, traits_type>( | |
|             itr.m_path_ptr->m_path, end_pos ) ); | |
| 
 | |
|         // if at end and there was a trailing non-root '/', return "." | |
|         if ( itr.m_pos == itr.m_path_ptr->m_path.size() | |
|           && itr.m_path_ptr->m_path.size() > 1 | |
|           && itr.m_path_ptr->m_path[itr.m_pos-1] == slash<Path>::value | |
|           && detail::is_non_root_slash< string_type, traits_type >( | |
|                itr.m_path_ptr->m_path, itr.m_pos-1 )  | |
|            ) | |
|         { | |
|           --itr.m_pos; | |
|             itr.m_name = dot<Path>::value; | |
|             return; | |
|         } | |
| 
 | |
|         // skip separators unless root directory | |
|         for (  | |
|           ;  | |
|           end_pos > 0 | |
|           && (end_pos-1) != root_dir_pos | |
|           && itr.m_path_ptr->m_path[end_pos-1] == slash<Path>::value | |
|           ; | |
|           --end_pos ) {} | |
| 
 | |
|         itr.m_pos = detail::filename_pos<string_type, traits_type> | |
|             ( itr.m_path_ptr->m_path, end_pos ); | |
|         itr.m_name = itr.m_path_ptr->m_path.substr( itr.m_pos, end_pos - itr.m_pos ); | |
|       } | |
|     } // namespace detail | |
|  | |
|     //  basic_filesystem_error implementation --------------------------------// | |
|  | |
|     template<class Path> | |
|     basic_filesystem_error<Path>::basic_filesystem_error( | |
|       const std::string & what_arg, system::error_code ec ) | |
|       : system::system_error(ec, what_arg) | |
|     { | |
|       try | |
|       { | |
|         m_imp_ptr.reset( new m_imp ); | |
|       } | |
|       catch (...) { m_imp_ptr.reset(); } | |
|     } | |
| 
 | |
|     template<class Path> | |
|     basic_filesystem_error<Path>::basic_filesystem_error( | |
|       const std::string & what_arg, const path_type & path1_arg, | |
|       system::error_code ec ) | |
|       : system::system_error(ec, what_arg) | |
|     { | |
|       try | |
|       { | |
|         m_imp_ptr.reset( new m_imp ); | |
|         m_imp_ptr->m_path1 = path1_arg; | |
|       } | |
|       catch (...) { m_imp_ptr.reset(); } | |
|     } | |
| 
 | |
|     template<class Path> | |
|     basic_filesystem_error<Path>::basic_filesystem_error( | |
|       const std::string & what_arg, const path_type & path1_arg, | |
|       const path_type & path2_arg, system::error_code ec ) | |
|       : system::system_error(ec, what_arg) | |
|     { | |
|       try | |
|       { | |
|         m_imp_ptr.reset( new m_imp ); | |
|         m_imp_ptr->m_path1 = path1_arg; | |
|         m_imp_ptr->m_path2 = path2_arg; | |
|       } | |
|       catch (...) { m_imp_ptr.reset(); } | |
|     } | |
| 
 | |
|   } // namespace BOOST_FILESYSTEM2_NAMESPACE | |
| } // namespace boost | |
|  | |
| //----------------------------------------------------------------------------// | |
|  | |
| namespace boost | |
| { | |
|   namespace filesystem | |
|   { | |
|     using filesystem2::basic_path; | |
|     using filesystem2::path_traits; | |
| 
 | |
|     using filesystem2::slash; | |
|     using filesystem2::dot; | |
|     using filesystem2::colon; | |
| 
 | |
|     using filesystem2::path; | |
| # ifndef BOOST_FILESYSTEM2_NARROW_ONLY | |
|     using filesystem2::wpath_traits; | |
|     using filesystem2::wpath; | |
|     using filesystem2::wfilesystem_error; | |
| # endif | |
|     using filesystem2::basic_filesystem_error; | |
|     using filesystem2::filesystem_error; | |
|     using filesystem2::portable_posix_name; | |
|     using filesystem2::windows_name; | |
|     using filesystem2::portable_name; | |
|     using filesystem2::portable_directory_name; | |
|     using filesystem2::portable_file_name; | |
|     using filesystem2::native; | |
|     using filesystem2::no_check; | |
|     using filesystem2::swap; | |
|     using filesystem2::operator<; | |
|     using filesystem2::operator==; | |
|     using filesystem2::operator!=; | |
|     using filesystem2::operator>; | |
|     using filesystem2::operator<=; | |
|     using filesystem2::operator>=; | |
|     using filesystem2::operator/; | |
|     using filesystem2::operator<<; | |
|     using filesystem2::operator>>; | |
|   } | |
| } | |
| 
 | |
| //----------------------------------------------------------------------------// | |
|  | |
| #include <boost/config/abi_suffix.hpp> // pops abi_prefix.hpp pragmas | |
|  | |
| #endif // BOOST_FILESYSTEM2_PATH_HPP
 | |
| 
 |