ossrv_pub/boost_apis/boost/filesystem/path.hpp
changeset 0 e4d67989cc36
equal deleted inserted replaced
-1:000000000000 0:e4d67989cc36
       
     1 //  boost/filesystem/path.hpp  -----------------------------------------------//
       
     2 
       
     3 //  Copyright Beman Dawes 2002-2005
       
     4 //  Use, modification, and distribution is subject to the Boost Software
       
     5 //  License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
       
     6 //  http://www.boost.org/LICENSE_1_0.txt)
       
     7 
       
     8 //  See library home page at http://www.boost.org/libs/filesystem
       
     9 
       
    10 //----------------------------------------------------------------------------// 
       
    11 
       
    12 #ifndef BOOST_FILESYSTEM_PATH_HPP
       
    13 #define BOOST_FILESYSTEM_PATH_HPP
       
    14 
       
    15 #include <boost/filesystem/config.hpp>
       
    16 #include <boost/iterator/iterator_facade.hpp>
       
    17 #include <boost/throw_exception.hpp>
       
    18 #include <boost/shared_ptr.hpp>
       
    19 #include <boost/type_traits/is_same.hpp>
       
    20 #include <boost/static_assert.hpp>
       
    21 
       
    22 #include <string>
       
    23 #include <algorithm> // for lexicographical_compare
       
    24 #include <iosfwd>    // needed by basic_path inserter and extractor
       
    25 #include <stdexcept>
       
    26 #include <cassert>
       
    27 
       
    28 # ifndef BOOST_FILESYSTEM_NARROW_ONLY
       
    29 #   include <locale>
       
    30 # endif
       
    31 
       
    32 #include <boost/config/abi_prefix.hpp> // must be the last #include
       
    33 
       
    34 //----------------------------------------------------------------------------//
       
    35 
       
    36 namespace boost
       
    37 {
       
    38   namespace BOOST_FILESYSTEM_NAMESPACE
       
    39   {
       
    40     template<class String, class Traits> class basic_path;
       
    41 
       
    42     struct path_traits;
       
    43     typedef basic_path< std::string, path_traits > path;
       
    44 
       
    45     struct path_traits
       
    46     {
       
    47       typedef std::string internal_string_type;
       
    48       typedef std::string external_string_type;
       
    49       static external_string_type to_external( const path &,
       
    50         const internal_string_type & src ) { return src; }
       
    51       static internal_string_type to_internal(
       
    52         const external_string_type & src ) { return src; }
       
    53     };
       
    54 
       
    55 # ifndef BOOST_FILESYSTEM_NARROW_ONLY
       
    56 
       
    57     struct wpath_traits;
       
    58     
       
    59     typedef basic_path< std::wstring, wpath_traits > wpath;
       
    60 
       
    61     struct wpath_traits
       
    62     {
       
    63       typedef std::wstring internal_string_type;
       
    64 # ifdef BOOST_WINDOWS_API
       
    65       typedef std::wstring external_string_type;
       
    66       static external_string_type to_external( const wpath &,
       
    67         const internal_string_type & src ) { return src; }
       
    68       static internal_string_type to_internal(
       
    69         const external_string_type & src ) { return src; }
       
    70 # else
       
    71       typedef std::string external_string_type;
       
    72       static external_string_type to_external( const wpath & ph,
       
    73         const internal_string_type & src );
       
    74       static internal_string_type to_internal(
       
    75         const external_string_type & src );
       
    76 # endif
       
    77       static void imbue( const std::locale & loc );
       
    78       static bool imbue( const std::locale & loc, const std::nothrow_t & );
       
    79     };
       
    80 
       
    81 # endif // ifndef BOOST_FILESYSTEM_NARROW_ONLY
       
    82 
       
    83 //  error reporting support  -------------------------------------------------//
       
    84 
       
    85     typedef int errno_type;  // determined by C standard
       
    86     
       
    87 # ifdef BOOST_WINDOWS_API
       
    88     typedef unsigned system_error_type;
       
    89 
       
    90     BOOST_FILESYSTEM_DECL
       
    91     errno_type lookup_errno( system_error_type sys_err_code );
       
    92 # else
       
    93     typedef int system_error_type;
       
    94 
       
    95     inline errno_type lookup_errno( system_error_type sys_err_code )
       
    96       { return sys_err_code; }
       
    97 # endif
       
    98 
       
    99     // deprecated support for legacy function name
       
   100     inline errno_type lookup_error_code( system_error_type sys_err_code )
       
   101       { return lookup_errno( sys_err_code ); }
       
   102 
       
   103     BOOST_FILESYSTEM_DECL
       
   104     void system_message( system_error_type sys_err_code, std::string & target );
       
   105     // Effects: appends error message to target
       
   106 
       
   107 # if defined(BOOST_WINDOWS_API) && !defined(BOOST_FILESYSTEM_NARROW_ONLY)
       
   108     BOOST_FILESYSTEM_DECL void
       
   109     system_message( system_error_type sys_err_code, std::wstring & target );
       
   110 # endif
       
   111 
       
   112     //  filesystem_error  ----------------------------------------------------//
       
   113 
       
   114     class filesystem_error : public std::runtime_error
       
   115     // see http://www.boost.org/more/error_handling.html for design rationale
       
   116     {
       
   117     public:
       
   118       filesystem_error()
       
   119         : std::runtime_error("filesystem error"), m_sys_err(0) {}
       
   120       explicit filesystem_error(
       
   121         const std::string & what_arg, system_error_type sys_ec = 0 )
       
   122         : std::runtime_error(what_arg), m_sys_err(sys_ec) {}
       
   123 
       
   124       system_error_type  system_error() const { return m_sys_err; }
       
   125       // Note: system_error() == 0 implies a library (rather than system) error
       
   126 
       
   127     private:
       
   128       system_error_type m_sys_err;
       
   129     };
       
   130 
       
   131     //  basic_filesystem_error  ----------------------------------------------//
       
   132 
       
   133     template<class Path>
       
   134     class basic_filesystem_error : public filesystem_error
       
   135     {
       
   136     // see http://www.boost.org/more/error_handling.html for design rationale
       
   137     public:
       
   138       // compiler generates copy constructor and copy assignment
       
   139 
       
   140       typedef Path path_type;
       
   141 
       
   142       basic_filesystem_error( const std::string & what,
       
   143         system_error_type sys_err_code );
       
   144 
       
   145       basic_filesystem_error( const std::string & what,
       
   146         const path_type & path1, system_error_type sys_err_code );
       
   147 
       
   148       basic_filesystem_error( const std::string & what, const path_type & path1,
       
   149         const path_type & path2, system_error_type sys_err_code );
       
   150 
       
   151       ~basic_filesystem_error() throw() {}
       
   152 
       
   153       const path_type & path1() const
       
   154       {
       
   155         static const path_type empty_path;
       
   156         return m_imp_ptr.get() ? m_imp_ptr->m_path1 : empty_path ;
       
   157       }
       
   158       const path_type & path2() const
       
   159       {
       
   160         static const path_type empty_path;
       
   161         return m_imp_ptr.get() ? m_imp_ptr->m_path2 : empty_path ;
       
   162       }
       
   163 
       
   164     private:
       
   165       struct m_imp
       
   166       {
       
   167         path_type       m_path1; // may be empty()
       
   168         path_type       m_path2; // may be empty()
       
   169       };
       
   170       boost::shared_ptr<m_imp> m_imp_ptr;
       
   171     };
       
   172 
       
   173     typedef basic_filesystem_error<path> filesystem_path_error;
       
   174 
       
   175 # ifndef BOOST_FILESYSTEM_NARROW_ONLY
       
   176     typedef basic_filesystem_error<wpath> filesystem_wpath_error;
       
   177 # endif
       
   178 
       
   179     //  path traits  ---------------------------------------------------------//
       
   180 
       
   181     template<class Path> struct is_basic_path
       
   182       { BOOST_STATIC_CONSTANT( bool, value = false ); };
       
   183     template<> struct is_basic_path<path>
       
   184       { BOOST_STATIC_CONSTANT( bool, value = true ); };
       
   185 # ifndef BOOST_FILESYSTEM_NARROW_ONLY
       
   186     template<> struct is_basic_path<wpath>
       
   187       { BOOST_STATIC_CONSTANT( bool, value = true ); };
       
   188 # endif
       
   189 
       
   190     // these only have to be specialized if Path::string_type::value_type
       
   191     // is not convertible from char
       
   192     template<class Path> struct slash
       
   193       { BOOST_STATIC_CONSTANT( char, value = '/' ); };
       
   194 
       
   195     template<class Path> struct dot
       
   196       { BOOST_STATIC_CONSTANT( char, value = '.' ); };
       
   197 
       
   198     template<class Path> struct colon
       
   199       { BOOST_STATIC_CONSTANT( char, value = ':' ); };
       
   200 
       
   201 # ifdef BOOST_WINDOWS_PATH
       
   202     template<class Path> struct path_alt_separator
       
   203       { BOOST_STATIC_CONSTANT( char, value = '\\' ); };
       
   204 # endif
       
   205 
       
   206     //  workaround for VC++ 7.0 and earlier issues with nested classes
       
   207     namespace detail
       
   208     {
       
   209       template<class Path>
       
   210       class iterator_helper
       
   211       {
       
   212       public:
       
   213         typedef typename Path::iterator iterator;
       
   214         static void do_increment( iterator & ph );
       
   215         static void do_decrement( iterator & ph );
       
   216       };
       
   217     }
       
   218 
       
   219     //  basic_path  ----------------------------------------------------------//
       
   220   
       
   221     template<class String, class Traits>
       
   222     class basic_path
       
   223     {
       
   224     // invariant: m_path valid according to the portable generic path grammar
       
   225 
       
   226       // validate template arguments
       
   227 // TODO: get these working
       
   228 //      BOOST_STATIC_ASSERT( ::boost::is_same<String,typename Traits::internal_string_type>::value );
       
   229 //      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 );
       
   230 
       
   231     public:
       
   232       // compiler generates copy constructor and copy assignment
       
   233 
       
   234       typedef basic_path<String, Traits> path_type;
       
   235       typedef String string_type;
       
   236       typedef typename String::value_type value_type;
       
   237       typedef Traits traits_type;
       
   238       typedef typename Traits::external_string_type external_string_type; 
       
   239 
       
   240       // constructors/destructor
       
   241       basic_path() {}
       
   242       basic_path( const string_type & s ) { operator/=( s ); }
       
   243       basic_path( const value_type * s )  { operator/=( s ); }
       
   244 #     ifndef BOOST_NO_MEMBER_TEMPLATES
       
   245         template <class InputIterator>
       
   246           basic_path( InputIterator first, InputIterator last )
       
   247             { append( first, last ); }
       
   248 #     endif
       
   249      ~basic_path() {}
       
   250 
       
   251       // assignments
       
   252       basic_path & operator=( const string_type & s )
       
   253       {
       
   254 #     if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, >= 310)
       
   255         m_path.clear();
       
   256 #     else
       
   257         m_path.erase( m_path.begin(), m_path.end() );
       
   258 #     endif
       
   259         operator/=( s ); 
       
   260         return *this;
       
   261       }
       
   262       basic_path & operator=( const value_type * s )
       
   263       { 
       
   264 #     if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, >= 310)
       
   265         m_path.clear();
       
   266 #     else
       
   267         m_path.erase( m_path.begin(), m_path.end() );
       
   268 #     endif
       
   269         operator/=( s ); 
       
   270         return *this;
       
   271       }
       
   272 #     ifndef BOOST_NO_MEMBER_TEMPLATES
       
   273         template <class InputIterator>
       
   274           basic_path & assign( InputIterator first, InputIterator last )
       
   275             { m_path.clear(); append( first, last ); return *this; }
       
   276 #     endif
       
   277 
       
   278       // modifiers
       
   279       basic_path & operator/=( const basic_path & rhs )  { return operator /=( rhs.string().c_str() ); }
       
   280       basic_path & operator/=( const string_type & rhs ) { return operator /=( rhs.c_str() ); }
       
   281       basic_path & operator/=( const value_type * s );
       
   282 #     ifndef BOOST_NO_MEMBER_TEMPLATES
       
   283         template <class InputIterator>
       
   284           basic_path & append( InputIterator first, InputIterator last );
       
   285 #     endif
       
   286       
       
   287       void swap( basic_path & rhs )
       
   288       {
       
   289         m_path.swap( rhs.m_path );
       
   290 #       ifdef BOOST_CYGWIN_PATH
       
   291           std::swap( m_cygwin_root, rhs.m_cygwin_root );
       
   292 #       endif
       
   293       }
       
   294 
       
   295       basic_path & remove_leaf();
       
   296 
       
   297       // observers
       
   298       const string_type & string() const         { return m_path; }
       
   299       const string_type file_string() const;
       
   300       const string_type directory_string() const { return file_string(); }
       
   301 
       
   302       const external_string_type external_file_string() const { return Traits::to_external( *this, file_string() ); }
       
   303       const external_string_type external_directory_string() const { return Traits::to_external( *this, directory_string() ); }
       
   304 
       
   305       basic_path   root_path() const;
       
   306       string_type  root_name() const;
       
   307       string_type  root_directory() const;
       
   308       basic_path   relative_path() const;
       
   309       string_type  leaf() const;
       
   310       basic_path   branch_path() const;
       
   311 
       
   312       bool empty() const               { return m_path.empty(); } // name consistent with std containers
       
   313       bool is_complete() const;
       
   314       bool has_root_path() const;
       
   315       bool has_root_name() const;
       
   316       bool has_root_directory() const;
       
   317       bool has_relative_path() const   { return !relative_path().empty(); }
       
   318       bool has_leaf() const            { return !m_path.empty(); }
       
   319       bool has_branch_path() const     { return !branch_path().empty(); }
       
   320 
       
   321       // iterators
       
   322       class iterator : public boost::iterator_facade<
       
   323         iterator,
       
   324         string_type const,
       
   325         boost::bidirectional_traversal_tag >
       
   326       {
       
   327       private:
       
   328         friend class boost::iterator_core_access;
       
   329         friend class boost::BOOST_FILESYSTEM_NAMESPACE::basic_path<String, Traits>;
       
   330 
       
   331         const string_type & dereference() const
       
   332           { return m_name; }
       
   333         bool equal( const iterator & rhs ) const
       
   334           { return m_path_ptr == rhs.m_path_ptr && m_pos == rhs.m_pos; }
       
   335 
       
   336         friend class boost::BOOST_FILESYSTEM_NAMESPACE::detail::iterator_helper<path_type>;
       
   337 
       
   338         void increment()
       
   339         { 
       
   340           boost::BOOST_FILESYSTEM_NAMESPACE::detail::iterator_helper<path_type>::do_increment(
       
   341             *this );
       
   342         }
       
   343         void decrement()
       
   344         { 
       
   345           boost::BOOST_FILESYSTEM_NAMESPACE::detail::iterator_helper<path_type>::do_decrement(
       
   346             *this );
       
   347         }
       
   348 
       
   349         string_type             m_name;     // current element
       
   350         const basic_path *      m_path_ptr; // path being iterated over
       
   351         typename string_type::size_type  m_pos;  // position of name in
       
   352                                             // path_ptr->string(). The
       
   353                                             // end() iterator is indicated by 
       
   354                                             // pos == path_ptr->m_path.size()
       
   355       }; // iterator
       
   356 
       
   357       typedef iterator const_iterator;
       
   358 
       
   359       iterator begin() const;
       
   360       iterator end() const;
       
   361 
       
   362     private:
       
   363       // Note: This is an implementation for POSIX and Windows, where there
       
   364       // are only minor differences between generic and native path grammars.
       
   365       // Private members might be quite different in other implementations,
       
   366       // particularly where there were wide differences between portable and
       
   367       // native path formats, or between file_string() and
       
   368       // directory_string() formats, or simply that the implementation
       
   369       // was willing expend additional memory to achieve greater speed for
       
   370       // some operations at the expense of other operations.
       
   371 
       
   372       string_type  m_path; // invariant: portable path grammar
       
   373                            // on Windows, backslashes converted to slashes
       
   374 
       
   375 #   ifdef BOOST_CYGWIN_PATH
       
   376       bool m_cygwin_root; // if present, m_path[0] was slash. note: initialization
       
   377                           // done by append
       
   378 #   endif  
       
   379 
       
   380       void m_append_separator_if_needed();
       
   381       void m_append( value_type value ); // converts Windows alt_separator
       
   382 
       
   383       // Was qualified; como433beta8 reports:
       
   384       //    warning #427-D: qualified name is not allowed in member declaration 
       
   385       friend class iterator;
       
   386       friend class boost::BOOST_FILESYSTEM_NAMESPACE::detail::iterator_helper<path_type>;
       
   387 
       
   388       // Deprecated features ease transition for existing code. Don't use these
       
   389       // in new code.
       
   390 # ifndef BOOST_FILESYSTEM_NO_DEPRECATED
       
   391     public:
       
   392       typedef bool (*name_check)( const std::string & name );
       
   393       basic_path( const string_type & str, name_check ) { operator/=( str ); }
       
   394       basic_path( const typename string_type::value_type * s, name_check )
       
   395         { operator/=( s );}
       
   396       string_type native_file_string() const { return file_string(); }
       
   397       string_type native_directory_string() const { return directory_string(); }
       
   398       static bool default_name_check_writable() { return false; } 
       
   399       static void default_name_check( name_check ) {}
       
   400       static name_check default_name_check() { return 0; }
       
   401       basic_path & canonize();
       
   402       basic_path & normalize();
       
   403 # endif
       
   404     };
       
   405 
       
   406   //  basic_path non-member functions  ---------------------------------------//
       
   407 
       
   408     template< class String, class Traits >
       
   409     inline void swap( basic_path<String, Traits> & lhs,
       
   410                basic_path<String, Traits> & rhs ) { lhs.swap( rhs ); }
       
   411 
       
   412     template< class String, class Traits >
       
   413     bool operator<( const basic_path<String, Traits> & lhs, const basic_path<String, Traits> & rhs )
       
   414     {
       
   415       return std::lexicographical_compare(
       
   416         lhs.begin(), lhs.end(), rhs.begin(), rhs.end() );
       
   417     }
       
   418 
       
   419     template< class String, class Traits >
       
   420     bool operator<( const typename basic_path<String, Traits>::string_type::value_type * lhs,
       
   421                     const basic_path<String, Traits> & rhs )
       
   422     {
       
   423       basic_path<String, Traits> tmp( lhs );
       
   424       return std::lexicographical_compare(
       
   425         tmp.begin(), tmp.end(), rhs.begin(), rhs.end() );
       
   426     }
       
   427 
       
   428     template< class String, class Traits >
       
   429     bool operator<( const typename basic_path<String, Traits>::string_type & lhs,
       
   430                     const basic_path<String, Traits> & rhs )
       
   431     {
       
   432       basic_path<String, Traits> tmp( lhs );
       
   433       return std::lexicographical_compare(
       
   434         tmp.begin(), tmp.end(), rhs.begin(), rhs.end() );
       
   435     }
       
   436 
       
   437     template< class String, class Traits >
       
   438     bool operator<( const basic_path<String, Traits> & lhs,
       
   439                     const typename basic_path<String, Traits>::string_type::value_type * rhs )
       
   440     {
       
   441       basic_path<String, Traits> tmp( rhs );
       
   442       return std::lexicographical_compare(
       
   443         lhs.begin(), lhs.end(), tmp.begin(), tmp.end() );
       
   444     }
       
   445 
       
   446     template< class String, class Traits >
       
   447     bool operator<( const basic_path<String, Traits> & lhs,
       
   448                     const typename basic_path<String, Traits>::string_type & rhs )
       
   449     {
       
   450       basic_path<String, Traits> tmp( rhs );
       
   451       return std::lexicographical_compare(
       
   452         lhs.begin(), lhs.end(), tmp.begin(), tmp.end() );
       
   453     }
       
   454 
       
   455     template< class String, class Traits >
       
   456     inline bool operator==( const basic_path<String, Traits> & lhs, const basic_path<String, Traits> & rhs )
       
   457     { 
       
   458       return !(lhs < rhs) && !(rhs < lhs);
       
   459     }
       
   460 
       
   461     template< class String, class Traits >
       
   462     inline bool operator==( const typename basic_path<String, Traits>::string_type::value_type * lhs,
       
   463                     const basic_path<String, Traits> & rhs )
       
   464     {
       
   465       basic_path<String, Traits> tmp( lhs );
       
   466       return !(tmp < rhs) && !(rhs < tmp);
       
   467     }
       
   468 
       
   469     template< class String, class Traits >
       
   470     inline bool operator==( const typename basic_path<String, Traits>::string_type & lhs,
       
   471                     const basic_path<String, Traits> & rhs )
       
   472     {
       
   473       basic_path<String, Traits> tmp( lhs );
       
   474       return !(tmp < rhs) && !(rhs < tmp);
       
   475     }
       
   476 
       
   477     template< class String, class Traits >
       
   478     inline bool operator==( const basic_path<String, Traits> & lhs,
       
   479                     const typename basic_path<String, Traits>::string_type::value_type * rhs )
       
   480     {
       
   481       basic_path<String, Traits> tmp( rhs );
       
   482       return !(lhs < tmp) && !(tmp < lhs);
       
   483     }
       
   484 
       
   485     template< class String, class Traits >
       
   486     inline bool operator==( const basic_path<String, Traits> & lhs,
       
   487                     const typename basic_path<String, Traits>::string_type & rhs )
       
   488     {
       
   489       basic_path<String, Traits> tmp( rhs );
       
   490       return !(lhs < tmp) && !(tmp < lhs);
       
   491     }
       
   492 
       
   493     template< class String, class Traits >
       
   494     inline bool operator!=( const basic_path<String, Traits> & lhs, const basic_path<String, Traits> & rhs ) { return !(lhs == rhs); }
       
   495     
       
   496     template< class String, class Traits >
       
   497     inline bool operator!=( const typename basic_path<String, Traits>::string_type::value_type * lhs,
       
   498                     const basic_path<String, Traits> & rhs ) { return !(basic_path<String, Traits>(lhs) == rhs); }
       
   499 
       
   500     template< class String, class Traits >
       
   501     inline bool operator!=( const typename basic_path<String, Traits>::string_type & lhs,
       
   502                     const basic_path<String, Traits> & rhs ) { return !(basic_path<String, Traits>(lhs) == rhs); }
       
   503 
       
   504     template< class String, class Traits >
       
   505     inline bool operator!=( const basic_path<String, Traits> & lhs,
       
   506                     const typename basic_path<String, Traits>::string_type::value_type * rhs )
       
   507                     { return !(lhs == basic_path<String, Traits>(rhs)); }
       
   508 
       
   509     template< class String, class Traits >
       
   510     inline bool operator!=( const basic_path<String, Traits> & lhs,
       
   511                     const typename basic_path<String, Traits>::string_type & rhs )
       
   512                     { return !(lhs == basic_path<String, Traits>(rhs)); }
       
   513 
       
   514     template< class String, class Traits >
       
   515     inline bool operator>( const basic_path<String, Traits> & lhs, const basic_path<String, Traits> & rhs ) { return rhs < lhs; }
       
   516     
       
   517     template< class String, class Traits >
       
   518     inline bool operator>( const typename basic_path<String, Traits>::string_type::value_type * lhs,
       
   519                     const basic_path<String, Traits> & rhs ) { return rhs < basic_path<String, Traits>(lhs); }
       
   520 
       
   521     template< class String, class Traits >
       
   522     inline bool operator>( const typename basic_path<String, Traits>::string_type & lhs,
       
   523                     const basic_path<String, Traits> & rhs ) { return rhs < basic_path<String, Traits>(lhs); }
       
   524 
       
   525     template< class String, class Traits >
       
   526     inline bool operator>( const basic_path<String, Traits> & lhs,
       
   527                     const typename basic_path<String, Traits>::string_type::value_type * rhs )
       
   528                     { return basic_path<String, Traits>(rhs) < lhs; }
       
   529 
       
   530     template< class String, class Traits >
       
   531     inline bool operator>( const basic_path<String, Traits> & lhs,
       
   532                     const typename basic_path<String, Traits>::string_type & rhs )
       
   533                     { return basic_path<String, Traits>(rhs) < lhs; }
       
   534 
       
   535     template< class String, class Traits >
       
   536     inline bool operator<=( const basic_path<String, Traits> & lhs, const basic_path<String, Traits> & rhs ) { return !(rhs < lhs); }
       
   537     
       
   538     template< class String, class Traits >
       
   539     inline bool operator<=( const typename basic_path<String, Traits>::string_type::value_type * lhs,
       
   540                     const basic_path<String, Traits> & rhs ) { return !(rhs < basic_path<String, Traits>(lhs)); }
       
   541 
       
   542     template< class String, class Traits >
       
   543     inline bool operator<=( const typename basic_path<String, Traits>::string_type & lhs,
       
   544                     const basic_path<String, Traits> & rhs ) { return !(rhs < basic_path<String, Traits>(lhs)); }
       
   545 
       
   546     template< class String, class Traits >
       
   547     inline bool operator<=( const basic_path<String, Traits> & lhs,
       
   548                     const typename basic_path<String, Traits>::string_type::value_type * rhs )
       
   549                     { return !(basic_path<String, Traits>(rhs) < lhs); }
       
   550 
       
   551     template< class String, class Traits >
       
   552     inline bool operator<=( const basic_path<String, Traits> & lhs,
       
   553                     const typename basic_path<String, Traits>::string_type & rhs )
       
   554                     { return !(basic_path<String, Traits>(rhs) < lhs); }
       
   555 
       
   556     template< class String, class Traits >
       
   557     inline bool operator>=( const basic_path<String, Traits> & lhs, const basic_path<String, Traits> & rhs ) { return !(lhs < rhs); }
       
   558     
       
   559     template< class String, class Traits >
       
   560     inline bool operator>=( const typename basic_path<String, Traits>::string_type::value_type * lhs,
       
   561                     const basic_path<String, Traits> & rhs ) { return !(lhs < basic_path<String, Traits>(rhs)); }
       
   562 
       
   563     template< class String, class Traits >
       
   564     inline bool operator>=( const typename basic_path<String, Traits>::string_type & lhs,
       
   565                     const basic_path<String, Traits> & rhs ) { return !(lhs < basic_path<String, Traits>(rhs)); }
       
   566 
       
   567     template< class String, class Traits >
       
   568     inline bool operator>=( const basic_path<String, Traits> & lhs,
       
   569                     const typename basic_path<String, Traits>::string_type::value_type * rhs )
       
   570                     { return !(basic_path<String, Traits>(lhs) < rhs); }
       
   571 
       
   572     template< class String, class Traits >
       
   573     inline bool operator>=( const basic_path<String, Traits> & lhs,
       
   574                     const typename basic_path<String, Traits>::string_type & rhs )
       
   575                     { return !(basic_path<String, Traits>(lhs) < rhs); }
       
   576 
       
   577     // operator /
       
   578 
       
   579     template< class String, class Traits >
       
   580     inline basic_path<String, Traits> operator/( 
       
   581       const basic_path<String, Traits> & lhs,
       
   582       const basic_path<String, Traits> & rhs )
       
   583       { return basic_path<String, Traits>( lhs ) /= rhs; }
       
   584 
       
   585     template< class String, class Traits >
       
   586     inline basic_path<String, Traits> operator/( 
       
   587       const basic_path<String, Traits> & lhs,
       
   588       const typename String::value_type * rhs )
       
   589       { return basic_path<String, Traits>( lhs ) /=
       
   590           basic_path<String, Traits>( rhs ); }
       
   591 
       
   592     template< class String, class Traits >
       
   593     inline basic_path<String, Traits> operator/( 
       
   594       const basic_path<String, Traits> & lhs, const String & rhs )
       
   595       { return basic_path<String, Traits>( lhs ) /=
       
   596           basic_path<String, Traits>( rhs ); }
       
   597 
       
   598     template< class String, class Traits >
       
   599     inline basic_path<String, Traits> operator/( 
       
   600       const typename String::value_type * lhs,
       
   601       const basic_path<String, Traits> & rhs )
       
   602       { return basic_path<String, Traits>( lhs ) /= rhs; }
       
   603 
       
   604     template< class String, class Traits >
       
   605     inline basic_path<String, Traits> operator/(
       
   606       const String & lhs, const basic_path<String, Traits> & rhs )
       
   607       { return basic_path<String, Traits>( lhs ) /= rhs; }
       
   608    
       
   609     //  inserters and extractors  --------------------------------------------//
       
   610 
       
   611 // bypass VC++ 7.0 and earlier, and broken Borland compilers
       
   612 # if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) && !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
       
   613     template< class Path >
       
   614     std::basic_ostream< typename Path::string_type::value_type,
       
   615       typename Path::string_type::traits_type > &
       
   616       operator<<
       
   617       ( std::basic_ostream< typename Path::string_type::value_type,
       
   618       typename Path::string_type::traits_type >& os, const Path & ph )
       
   619     {
       
   620       os << ph.string();
       
   621       return os;
       
   622     }
       
   623 
       
   624     template< class Path >
       
   625     std::basic_istream< typename Path::string_type::value_type,
       
   626       typename Path::string_type::traits_type > &
       
   627       operator>>
       
   628       ( std::basic_istream< typename Path::string_type::value_type,
       
   629       typename Path::string_type::traits_type >& is, Path & ph )
       
   630     {
       
   631       typename Path::string_type str;
       
   632       is >> str;
       
   633       ph = str;
       
   634       return is;
       
   635     }
       
   636 # elif BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
       
   637     template< class String, class Traits >
       
   638     std::basic_ostream< BOOST_DEDUCED_TYPENAME String::value_type,
       
   639       BOOST_DEDUCED_TYPENAME String::traits_type > &
       
   640       operator<<
       
   641       ( std::basic_ostream< BOOST_DEDUCED_TYPENAME String::value_type,
       
   642           BOOST_DEDUCED_TYPENAME String::traits_type >& os, 
       
   643         const basic_path< String, Traits > & ph )
       
   644     {
       
   645       os << ph.string();
       
   646       return os;
       
   647     }
       
   648 
       
   649     template< class String, class Traits >
       
   650     std::basic_istream< BOOST_DEDUCED_TYPENAME String::value_type, 
       
   651       BOOST_DEDUCED_TYPENAME String::traits_type > &
       
   652       operator>>
       
   653       ( std::basic_istream< BOOST_DEDUCED_TYPENAME String::value_type,
       
   654           BOOST_DEDUCED_TYPENAME String::traits_type> & is,
       
   655         basic_path< String, Traits > & ph )
       
   656     {
       
   657       String str;
       
   658       is >> str;
       
   659       ph = str;
       
   660       return is;
       
   661     }
       
   662 # endif
       
   663 
       
   664   //  path::name_checks  -----------------------------------------------------//
       
   665 
       
   666     BOOST_FILESYSTEM_DECL bool portable_posix_name( const std::string & name );
       
   667     BOOST_FILESYSTEM_DECL bool windows_name( const std::string & name );
       
   668     BOOST_FILESYSTEM_DECL bool portable_name( const std::string & name );
       
   669     BOOST_FILESYSTEM_DECL bool portable_directory_name( const std::string & name );
       
   670     BOOST_FILESYSTEM_DECL bool portable_file_name( const std::string & name );
       
   671     BOOST_FILESYSTEM_DECL bool native( const std::string & name );
       
   672     inline bool no_check( const std::string & )
       
   673       { return true; }
       
   674 
       
   675 // implementation  -----------------------------------------------------------//
       
   676 
       
   677     namespace detail
       
   678     {
       
   679 
       
   680       //  is_separator helper ------------------------------------------------//
       
   681 
       
   682       template<class Path>
       
   683       inline  bool is_separator( typename Path::string_type::value_type c )
       
   684       {
       
   685         return c == slash<Path>::value
       
   686 #     ifdef BOOST_WINDOWS_PATH
       
   687           || c == path_alt_separator<Path>::value
       
   688 #     endif
       
   689           ;
       
   690       }
       
   691 
       
   692       // leaf_pos helper  ----------------------------------------------------//
       
   693 
       
   694       template<class String, class Traits>
       
   695       typename String::size_type leaf_pos(
       
   696         const String & str, // precondition: portable generic path grammar
       
   697         typename String::size_type end_pos ) // end_pos is past-the-end position
       
   698       // return 0 if str itself is leaf (or empty)
       
   699       {
       
   700         typedef typename
       
   701           boost::BOOST_FILESYSTEM_NAMESPACE::basic_path<String, Traits> path_type;
       
   702 
       
   703         // case: "//"
       
   704         if ( end_pos == 2 
       
   705           && str[0] == slash<path_type>::value
       
   706           && str[1] == slash<path_type>::value ) return 0;
       
   707 
       
   708         // case: ends in "/"
       
   709         if ( end_pos && str[end_pos-1] == slash<path_type>::value )
       
   710           return end_pos-1;
       
   711         
       
   712         // set pos to start of last element
       
   713         typename String::size_type pos(
       
   714           str.find_last_of( slash<path_type>::value, end_pos-1 ) );
       
   715 #       ifdef BOOST_WINDOWS_PATH
       
   716         if ( pos == String::npos )
       
   717           pos = str.find_last_of( path_alt_separator<path_type>::value, end_pos-1 );
       
   718         if ( pos == String::npos )
       
   719           pos = str.find_last_of( colon<path_type>::value, end_pos-2 );
       
   720 #       endif
       
   721 
       
   722         return ( pos == String::npos // path itself must be a leaf (or empty)
       
   723           || (pos == 1 && str[0] == slash<path_type>::value) ) // or net
       
   724             ? 0 // so leaf is entire string
       
   725             : pos + 1; // or starts after delimiter
       
   726       }
       
   727 
       
   728       // first_element helper  -----------------------------------------------//
       
   729       //   sets pos and len of first element, excluding extra separators
       
   730       //   if src.empty(), sets pos,len, to 0,0.
       
   731 
       
   732       template<class String, class Traits>
       
   733         void first_element(
       
   734           const String & src, // precondition: portable generic path grammar
       
   735           typename String::size_type & element_pos,
       
   736           typename String::size_type & element_size,
       
   737 #       if !BOOST_WORKAROUND( BOOST_MSVC, <= 1310 ) // VC++ 7.1
       
   738           typename String::size_type size = String::npos
       
   739 #       else
       
   740           typename String::size_type size = -1
       
   741 #       endif
       
   742           )
       
   743       {
       
   744         if ( size == String::npos ) size = src.size();
       
   745         element_pos = 0;
       
   746         element_size = 0;
       
   747         if ( src.empty() ) return;
       
   748 
       
   749         typedef typename boost::BOOST_FILESYSTEM_NAMESPACE::basic_path<String, Traits> path_type;
       
   750 
       
   751         typename String::size_type cur(0);
       
   752         
       
   753         // deal with // [network]
       
   754         if ( size >= 2 && src[0] == slash<path_type>::value
       
   755           && src[1] == slash<path_type>::value
       
   756           && (size == 2
       
   757             || src[2] != slash<path_type>::value) )
       
   758         { 
       
   759           cur += 2;
       
   760           element_size += 2;
       
   761         }
       
   762 
       
   763         // leading (not non-network) separator
       
   764         else if ( src[0] == slash<path_type>::value )
       
   765         {
       
   766           ++element_size;
       
   767           // bypass extra leading separators
       
   768           while ( cur+1 < size
       
   769             && src[cur+1] == slash<path_type>::value )
       
   770           {
       
   771             ++cur;
       
   772             ++element_pos;
       
   773           }
       
   774           return;
       
   775         }
       
   776 
       
   777         // at this point, we have either a plain name, a network name,
       
   778         // or (on Windows only) a device name
       
   779 
       
   780         // find the end
       
   781         while ( cur < size
       
   782 #         ifdef BOOST_WINDOWS_PATH
       
   783           && src[cur] != colon<path_type>::value
       
   784 #         endif
       
   785           && src[cur] != slash<path_type>::value )
       
   786         {
       
   787           ++cur;
       
   788           ++element_size;
       
   789         }
       
   790 
       
   791 #       ifdef BOOST_WINDOWS_PATH
       
   792         if ( cur == size ) return;
       
   793         // include device delimiter
       
   794         if ( src[cur] == colon<path_type>::value )
       
   795           { ++element_size; }
       
   796 #       endif
       
   797 
       
   798         return;
       
   799       }
       
   800 
       
   801       // root_directory_start helper  ----------------------------------------//
       
   802 
       
   803       template<class String, class Traits>
       
   804       typename String::size_type root_directory_start(
       
   805         const String & s, // precondition: portable generic path grammar
       
   806         typename String::size_type size )
       
   807       // return npos if no root_directory found
       
   808       {
       
   809         typedef typename boost::BOOST_FILESYSTEM_NAMESPACE::basic_path<String, Traits> path_type;
       
   810 
       
   811 #     ifdef BOOST_WINDOWS_PATH
       
   812         // case "c:/"
       
   813         if ( size > 2
       
   814           && s[1] == colon<path_type>::value
       
   815           && s[2] == slash<path_type>::value ) return 2;
       
   816 #     endif
       
   817 
       
   818         // case "//"
       
   819         if ( size == 2
       
   820           && s[0] == slash<path_type>::value
       
   821           && s[1] == slash<path_type>::value ) return String::npos;
       
   822 
       
   823         // case "//net {/}"
       
   824         if ( size > 3
       
   825           && s[0] == slash<path_type>::value
       
   826           && s[1] == slash<path_type>::value
       
   827           && s[2] != slash<path_type>::value )
       
   828         {
       
   829           typename String::size_type pos(
       
   830             s.find( slash<path_type>::value, 2 ) );
       
   831           return pos < size ? pos : String::npos;
       
   832         }
       
   833         
       
   834         // case "/"
       
   835         if ( size > 0 && s[0] == slash<path_type>::value ) return 0;
       
   836 
       
   837         return String::npos;
       
   838       }
       
   839 
       
   840       // is_non_root_slash helper  -------------------------------------------//
       
   841 
       
   842       template<class String, class Traits>
       
   843       bool is_non_root_slash( const String & str,
       
   844         typename String::size_type pos ) // pos is position of the slash
       
   845       {
       
   846         typedef typename
       
   847           boost::BOOST_FILESYSTEM_NAMESPACE::basic_path<String, Traits>
       
   848             path_type;
       
   849 
       
   850         assert( !str.empty() && str[pos] == slash<path_type>::value
       
   851           && "precondition violation" );
       
   852 
       
   853         // subsequent logic expects pos to be for leftmost slash of a set
       
   854         while ( pos > 0 && str[pos-1] == slash<path_type>::value )
       
   855           --pos;
       
   856 
       
   857         return  pos != 0
       
   858           && (pos <= 2 || str[1] != slash<path_type>::value
       
   859             || str.find( slash<path_type>::value, 2 ) != pos)
       
   860 #       ifdef BOOST_WINDOWS_PATH
       
   861           && (pos !=2 || str[1] != colon<path_type>::value)
       
   862 #       endif
       
   863             ;
       
   864       }
       
   865     } // namespace detail
       
   866 
       
   867     // decomposition functions  ----------------------------------------------//
       
   868 
       
   869     template<class String, class Traits>
       
   870     String basic_path<String, Traits>::leaf() const
       
   871     {
       
   872       typename String::size_type end_pos(
       
   873         detail::leaf_pos<String, Traits>( m_path, m_path.size() ) );
       
   874       return (m_path.size()
       
   875                 && end_pos
       
   876                 && m_path[end_pos] == slash<path_type>::value
       
   877                 && detail::is_non_root_slash< String, Traits >(m_path, end_pos))
       
   878         ? String( 1, dot<path_type>::value )
       
   879         : m_path.substr( end_pos );
       
   880     }
       
   881 
       
   882     template<class String, class Traits>
       
   883     basic_path<String, Traits> basic_path<String, Traits>::branch_path() const
       
   884     {
       
   885       typename String::size_type end_pos(
       
   886         detail::leaf_pos<String, Traits>( m_path, m_path.size() ) );
       
   887 
       
   888       bool leaf_was_separator( m_path.size()
       
   889         && m_path[end_pos] == slash<path_type>::value );
       
   890 
       
   891       // skip separators unless root directory
       
   892       typename string_type::size_type root_dir_pos( detail::root_directory_start
       
   893         <string_type, traits_type>( m_path, end_pos ) );
       
   894       for ( ; 
       
   895         end_pos > 0
       
   896         && (end_pos-1) != root_dir_pos
       
   897         && m_path[end_pos-1] == slash<path_type>::value
       
   898         ;
       
   899         --end_pos ) {}
       
   900 
       
   901      return (end_pos == 1 && root_dir_pos == 0 && leaf_was_separator)
       
   902        ? path_type()
       
   903        : path_type( m_path.substr( 0, end_pos ) );
       
   904     }
       
   905 
       
   906     template<class String, class Traits>
       
   907     basic_path<String, Traits> basic_path<String, Traits>::relative_path() const
       
   908     {
       
   909       iterator itr( begin() );
       
   910       for ( ; itr.m_pos != m_path.size()
       
   911           && (itr.m_name[0] == slash<path_type>::value
       
   912 #     ifdef BOOST_WINDOWS_PATH
       
   913           || itr.m_name[itr.m_name.size()-1]
       
   914             == colon<path_type>::value
       
   915 #     endif
       
   916              ); ++itr ) {}
       
   917 
       
   918       return basic_path<String, Traits>( m_path.substr( itr.m_pos ) );
       
   919     }
       
   920 
       
   921     template<class String, class Traits>
       
   922     String basic_path<String, Traits>::root_name() const
       
   923     {
       
   924       iterator itr( begin() );
       
   925 
       
   926       return ( itr.m_pos != m_path.size()
       
   927         && (
       
   928             ( itr.m_name.size() > 1
       
   929               && itr.m_name[0] == slash<path_type>::value
       
   930               && itr.m_name[1] == slash<path_type>::value
       
   931             )
       
   932 #     ifdef BOOST_WINDOWS_PATH
       
   933           || itr.m_name[itr.m_name.size()-1]
       
   934             == colon<path_type>::value
       
   935 #     endif
       
   936            ) )
       
   937         ? *itr
       
   938         : String();
       
   939     }
       
   940 
       
   941     template<class String, class Traits>
       
   942     String basic_path<String, Traits>::root_directory() const
       
   943     {
       
   944       typename string_type::size_type start(
       
   945         detail::root_directory_start<String, Traits>( m_path, m_path.size() ) );
       
   946 
       
   947       return start == string_type::npos
       
   948         ? string_type()
       
   949         : m_path.substr( start, 1 );
       
   950     }
       
   951 
       
   952     template<class String, class Traits>
       
   953     basic_path<String, Traits> basic_path<String, Traits>::root_path() const
       
   954     {
       
   955       // even on POSIX, root_name() is non-empty() on network paths
       
   956       return basic_path<String, Traits>( root_name() ) /= root_directory();
       
   957     }
       
   958 
       
   959     // path query functions  -------------------------------------------------//
       
   960 
       
   961     template<class String, class Traits>
       
   962     inline bool basic_path<String, Traits>::is_complete() const
       
   963     {
       
   964 #   ifdef BOOST_WINDOWS_PATH
       
   965       return has_root_name() && has_root_directory();
       
   966 #   else
       
   967       return has_root_directory();
       
   968 #   endif
       
   969     }
       
   970 
       
   971     template<class String, class Traits>
       
   972     inline bool basic_path<String, Traits>::has_root_path() const
       
   973     {
       
   974       return !root_path().empty();
       
   975     }
       
   976 
       
   977     template<class String, class Traits>
       
   978     inline bool basic_path<String, Traits>::has_root_name() const
       
   979     {
       
   980       return !root_name().empty();
       
   981     }
       
   982 
       
   983     template<class String, class Traits>
       
   984     inline bool basic_path<String, Traits>::has_root_directory() const
       
   985     {
       
   986       return !root_directory().empty();
       
   987     }
       
   988 
       
   989     // append  ---------------------------------------------------------------//
       
   990 
       
   991     template<class String, class Traits>
       
   992     void basic_path<String, Traits>::m_append_separator_if_needed()
       
   993     // requires: !empty()
       
   994     {
       
   995       if (
       
   996 #       ifdef BOOST_WINDOWS_PATH
       
   997         *(m_path.end()-1) != colon<path_type>::value && 
       
   998 #       endif
       
   999         *(m_path.end()-1) != slash<path_type>::value )
       
  1000       {
       
  1001         m_path += slash<path_type>::value;
       
  1002       }
       
  1003     }
       
  1004       
       
  1005     template<class String, class Traits>
       
  1006     void basic_path<String, Traits>::m_append( value_type value )
       
  1007     {
       
  1008 #   ifdef BOOST_CYGWIN_PATH
       
  1009       if ( m_path.empty() ) m_cygwin_root = (value == slash<path_type>::value);
       
  1010 #   endif
       
  1011 
       
  1012 #   ifdef BOOST_WINDOWS_PATH
       
  1013       // for BOOST_WINDOWS_PATH, convert alt_separator ('\') to separator ('/')
       
  1014       m_path += ( value == path_alt_separator<path_type>::value
       
  1015         ? slash<path_type>::value
       
  1016         : value );
       
  1017 #   else
       
  1018       m_path += value;
       
  1019 #   endif
       
  1020     }
       
  1021     
       
  1022     // except that it wouldn't work for BOOST_NO_MEMBER_TEMPLATES compilers,
       
  1023     // the append() member template could replace this code.
       
  1024     template<class String, class Traits>
       
  1025     basic_path<String, Traits> & basic_path<String, Traits>::operator /=
       
  1026       ( const value_type * next_p )
       
  1027     {
       
  1028       // ignore escape sequence on POSIX or Windows
       
  1029       if ( *next_p == slash<path_type>::value
       
  1030         && *(next_p+1) == slash<path_type>::value
       
  1031         && *(next_p+2) == colon<path_type>::value ) next_p += 3;
       
  1032       
       
  1033       // append slash<path_type>::value if needed
       
  1034       if ( !empty() && *next_p != 0
       
  1035         && !detail::is_separator<path_type>( *next_p ) )
       
  1036       { m_append_separator_if_needed(); }
       
  1037 
       
  1038       for ( ; *next_p != 0; ++next_p ) m_append( *next_p );
       
  1039       return *this;
       
  1040     }
       
  1041 
       
  1042 # ifndef BOOST_NO_MEMBER_TEMPLATES
       
  1043     template<class String, class Traits> template <class InputIterator>
       
  1044       basic_path<String, Traits> & basic_path<String, Traits>::append(
       
  1045         InputIterator first, InputIterator last )
       
  1046     {
       
  1047       // append slash<path_type>::value if needed
       
  1048       if ( !empty() && first != last
       
  1049         && !detail::is_separator<path_type>( *first ) )
       
  1050       { m_append_separator_if_needed(); }
       
  1051 
       
  1052       // song-and-dance to avoid violating InputIterator requirements
       
  1053       // (which prohibit lookahead) in detecting a possible escape sequence
       
  1054       // (escape sequences are simply ignored on POSIX and Windows)
       
  1055       bool was_escape_sequence(true);
       
  1056       std::size_t append_count(0);
       
  1057       typename String::size_type initial_pos( m_path.size() );
       
  1058 
       
  1059       for ( ; first != last && *first; ++first )
       
  1060       {
       
  1061         if ( append_count == 0 && *first != slash<path_type>::value )
       
  1062           was_escape_sequence = false;
       
  1063         if ( append_count == 1 && *first != slash<path_type>::value )
       
  1064           was_escape_sequence = false;
       
  1065         if ( append_count == 2 && *first != colon<path_type>::value )
       
  1066           was_escape_sequence = false;
       
  1067         m_append( *first );
       
  1068         ++append_count;
       
  1069       }
       
  1070 
       
  1071       // erase escape sequence if any
       
  1072       if ( was_escape_sequence && append_count >= 3 )
       
  1073         m_path.erase( initial_pos, 3 );
       
  1074 
       
  1075       return *this;
       
  1076     }
       
  1077 # endif
       
  1078 
       
  1079 # ifndef BOOST_FILESYSTEM_NO_DEPRECATED
       
  1080 
       
  1081     // canonize  ------------------------------------------------------------//
       
  1082 
       
  1083     template<class String, class Traits>
       
  1084     basic_path<String, Traits> & basic_path<String, Traits>::canonize()
       
  1085     {
       
  1086       static const typename string_type::value_type dot_str[]
       
  1087         = { dot<path_type>::value, 0 };
       
  1088 
       
  1089       if ( m_path.empty() ) return *this;
       
  1090         
       
  1091       path_type temp;
       
  1092 
       
  1093       for ( iterator itr( begin() ); itr != end(); ++itr )
       
  1094       {
       
  1095         temp /= *itr;
       
  1096       };
       
  1097 
       
  1098       if ( temp.empty() ) temp /= dot_str;
       
  1099       m_path = temp.m_path;
       
  1100       return *this;
       
  1101     }
       
  1102 
       
  1103     // normalize  ------------------------------------------------------------//
       
  1104 
       
  1105     template<class String, class Traits>
       
  1106     basic_path<String, Traits> & basic_path<String, Traits>::normalize()
       
  1107     {
       
  1108       static const typename string_type::value_type dot_str[]
       
  1109         = { dot<path_type>::value, 0 };
       
  1110 
       
  1111       if ( m_path.empty() ) return *this;
       
  1112         
       
  1113       path_type temp;
       
  1114       iterator start( begin() );
       
  1115       iterator last( end() );
       
  1116       iterator stop( last-- );
       
  1117       for ( iterator itr( start ); itr != stop; ++itr )
       
  1118       {
       
  1119         // ignore "." except at start and last
       
  1120         if ( itr->size() == 1
       
  1121           && (*itr)[0] == dot<path_type>::value
       
  1122           && itr != start
       
  1123           && itr != last ) continue;
       
  1124 
       
  1125         // ignore a name and following ".."
       
  1126         if ( !temp.empty()
       
  1127           && itr->size() == 2
       
  1128           && (*itr)[0] == dot<path_type>::value
       
  1129           && (*itr)[1] == dot<path_type>::value ) // dot dot
       
  1130         {
       
  1131           string_type lf( temp.leaf() );  
       
  1132           if ( lf.size() > 0  
       
  1133             && (lf.size() != 1
       
  1134               || (lf[0] != dot<path_type>::value
       
  1135                 && lf[0] != slash<path_type>::value))
       
  1136             && (lf.size() != 2 
       
  1137               || (lf[0] != dot<path_type>::value
       
  1138                 && lf[1] != dot<path_type>::value
       
  1139 #             ifdef BOOST_WINDOWS_PATH
       
  1140                 && lf[1] != colon<path_type>::value
       
  1141 #             endif
       
  1142                  )
       
  1143                )
       
  1144             )
       
  1145           {
       
  1146             temp.remove_leaf();
       
  1147             // if not root directory, must also remove "/" if any
       
  1148             if ( temp.m_path.size() > 0
       
  1149               && temp.m_path[temp.m_path.size()-1]
       
  1150                 == slash<path_type>::value )
       
  1151             {
       
  1152               typename string_type::size_type rds(
       
  1153                 detail::root_directory_start<String,Traits>( temp.m_path,
       
  1154                   temp.m_path.size() ) );
       
  1155               if ( rds == string_type::npos
       
  1156                 || rds != temp.m_path.size()-1 ) 
       
  1157                 { temp.m_path.erase( temp.m_path.size()-1 ); }
       
  1158             }
       
  1159 
       
  1160             iterator next( itr );
       
  1161             if ( temp.empty() && ++next != stop
       
  1162               && next == last && *last == dot_str ) temp /= dot_str;
       
  1163             continue;
       
  1164           }
       
  1165         }
       
  1166 
       
  1167         temp /= *itr;
       
  1168       };
       
  1169 
       
  1170       if ( temp.empty() ) temp /= dot_str;
       
  1171       m_path = temp.m_path;
       
  1172       return *this;
       
  1173     }
       
  1174 
       
  1175 # endif
       
  1176 
       
  1177     // remove_leaf  ----------------------------------------------------------//
       
  1178 
       
  1179     template<class String, class Traits>
       
  1180     basic_path<String, Traits> & basic_path<String, Traits>::remove_leaf()
       
  1181     {
       
  1182       m_path.erase(
       
  1183         detail::leaf_pos<String, Traits>( m_path, m_path.size() ) );
       
  1184       return *this;
       
  1185     }
       
  1186 
       
  1187     // path conversion functions  --------------------------------------------//
       
  1188 
       
  1189     template<class String, class Traits>
       
  1190     const String
       
  1191     basic_path<String, Traits>::file_string() const
       
  1192     {
       
  1193 #   ifdef BOOST_WINDOWS_PATH
       
  1194       // for Windows, use the alternate separator, and bypass extra 
       
  1195       // root separators
       
  1196 
       
  1197       typename string_type::size_type root_dir_start(
       
  1198         detail::root_directory_start<String, Traits>( m_path, m_path.size() ) );
       
  1199       bool in_root( root_dir_start != string_type::npos );
       
  1200       String s;
       
  1201       for ( typename string_type::size_type pos( 0 );
       
  1202         pos != m_path.size(); ++pos )
       
  1203       {
       
  1204         // special case // [net]
       
  1205         if ( pos == 0 && m_path.size() > 1
       
  1206           && m_path[0] == slash<path_type>::value
       
  1207           && m_path[1] == slash<path_type>::value
       
  1208           && ( m_path.size() == 2 
       
  1209             || !detail::is_separator<path_type>( m_path[2] )
       
  1210              ) )
       
  1211         {
       
  1212           ++pos;
       
  1213           s += path_alt_separator<path_type>::value;
       
  1214           s += path_alt_separator<path_type>::value;
       
  1215           continue;
       
  1216         }   
       
  1217 
       
  1218         // bypass extra root separators
       
  1219         if ( in_root )
       
  1220         { 
       
  1221           if ( s.size() > 0
       
  1222             && s[s.size()-1] == path_alt_separator<path_type>::value
       
  1223             && m_path[pos] == slash<path_type>::value
       
  1224             ) continue;
       
  1225         }
       
  1226 
       
  1227         if ( m_path[pos] == slash<path_type>::value )
       
  1228           s += path_alt_separator<path_type>::value;
       
  1229         else
       
  1230           s += m_path[pos];
       
  1231 
       
  1232         if ( pos > root_dir_start
       
  1233           && m_path[pos] == slash<path_type>::value )
       
  1234           { in_root = false; }
       
  1235       }
       
  1236 #   ifdef BOOST_CYGWIN_PATH
       
  1237       if ( m_cygwin_root ) s[0] = slash<path_type>::value;
       
  1238 #   endif
       
  1239       return s;
       
  1240 #   else
       
  1241       return m_path;
       
  1242 #   endif
       
  1243     }
       
  1244 
       
  1245     // iterator functions  ---------------------------------------------------//
       
  1246 
       
  1247     template<class String, class Traits>
       
  1248     typename basic_path<String, Traits>::iterator basic_path<String, Traits>::begin() const
       
  1249     {
       
  1250       iterator itr;
       
  1251       itr.m_path_ptr = this;
       
  1252       typename string_type::size_type element_size;
       
  1253       detail::first_element<String, Traits>( m_path, itr.m_pos, element_size );
       
  1254       itr.m_name = m_path.substr( itr.m_pos, element_size );
       
  1255       return itr;
       
  1256     }
       
  1257 
       
  1258     template<class String, class Traits>
       
  1259     typename basic_path<String, Traits>::iterator basic_path<String, Traits>::end() const
       
  1260       {
       
  1261         iterator itr;
       
  1262         itr.m_path_ptr = this;
       
  1263         itr.m_pos = m_path.size();
       
  1264         return itr;
       
  1265       }
       
  1266 
       
  1267     namespace detail
       
  1268     {
       
  1269       //  do_increment  ------------------------------------------------------//
       
  1270 
       
  1271       template<class Path>
       
  1272       void iterator_helper<Path>::do_increment( iterator & itr )
       
  1273       {
       
  1274         typedef typename Path::string_type string_type;
       
  1275         typedef typename Path::traits_type traits_type;
       
  1276 
       
  1277         assert( itr.m_pos < itr.m_path_ptr->m_path.size() && "basic_path::iterator increment past end()" );
       
  1278 
       
  1279         bool was_net( itr.m_name.size() > 2
       
  1280           && itr.m_name[0] == slash<Path>::value
       
  1281           && itr.m_name[1] == slash<Path>::value
       
  1282           && itr.m_name[2] != slash<Path>::value );
       
  1283 
       
  1284         // increment to position past current element
       
  1285         itr.m_pos += itr.m_name.size();
       
  1286 
       
  1287         // if end reached, create end iterator
       
  1288         if ( itr.m_pos == itr.m_path_ptr->m_path.size() )
       
  1289         {
       
  1290           itr.m_name.erase( itr.m_name.begin(), itr.m_name.end() ); // VC++ 6.0 lib didn't supply clear() 
       
  1291           return;
       
  1292         }
       
  1293 
       
  1294         // process separator (Windows drive spec is only case not a separator)
       
  1295         if ( itr.m_path_ptr->m_path[itr.m_pos] == slash<Path>::value )
       
  1296         {
       
  1297           // detect root directory
       
  1298           if ( was_net
       
  1299   #       ifdef BOOST_WINDOWS_PATH
       
  1300             // case "c:/"
       
  1301             || itr.m_name[itr.m_name.size()-1] == colon<Path>::value
       
  1302   #       endif
       
  1303              )
       
  1304           {
       
  1305             itr.m_name = slash<Path>::value;
       
  1306             return;
       
  1307           }
       
  1308 
       
  1309           // bypass separators
       
  1310           while ( itr.m_pos != itr.m_path_ptr->m_path.size()
       
  1311             && itr.m_path_ptr->m_path[itr.m_pos] == slash<Path>::value )
       
  1312             { ++itr.m_pos; }
       
  1313 
       
  1314           // detect trailing separator, and treat it as ".", per POSIX spec
       
  1315           if ( itr.m_pos == itr.m_path_ptr->m_path.size()
       
  1316             && detail::is_non_root_slash< string_type, traits_type >(
       
  1317                 itr.m_path_ptr->m_path, itr.m_pos-1 ) ) 
       
  1318           {
       
  1319             --itr.m_pos;
       
  1320             itr.m_name = dot<Path>::value;
       
  1321             return;
       
  1322           }
       
  1323         }
       
  1324 
       
  1325         // get next element
       
  1326         typename string_type::size_type end_pos(
       
  1327           itr.m_path_ptr->m_path.find( slash<Path>::value, itr.m_pos ) );
       
  1328         itr.m_name = itr.m_path_ptr->m_path.substr( itr.m_pos, end_pos - itr.m_pos );
       
  1329       } 
       
  1330 
       
  1331       //  do_decrement  ------------------------------------------------------//
       
  1332 
       
  1333       template<class Path>
       
  1334       void iterator_helper<Path>::do_decrement( iterator & itr )
       
  1335       {                                                                                
       
  1336         assert( itr.m_pos && "basic_path::iterator decrement past begin()"  );
       
  1337 
       
  1338         typedef typename Path::string_type string_type;
       
  1339         typedef typename Path::traits_type traits_type;
       
  1340 
       
  1341         typename string_type::size_type end_pos( itr.m_pos );
       
  1342 
       
  1343         typename string_type::size_type root_dir_pos(
       
  1344           detail::root_directory_start<string_type, traits_type>(
       
  1345             itr.m_path_ptr->m_path, end_pos ) );
       
  1346 
       
  1347         // if at end and there was a trailing non-root '/', return "."
       
  1348         if ( itr.m_pos == itr.m_path_ptr->m_path.size()
       
  1349           && itr.m_path_ptr->m_path.size() > 1
       
  1350           && itr.m_path_ptr->m_path[itr.m_pos-1] == slash<Path>::value
       
  1351           && detail::is_non_root_slash< string_type, traits_type >(
       
  1352                itr.m_path_ptr->m_path, itr.m_pos-1 ) 
       
  1353            )
       
  1354         {
       
  1355           --itr.m_pos;
       
  1356             itr.m_name = dot<Path>::value;
       
  1357             return;
       
  1358         }
       
  1359 
       
  1360         // skip separators unless root directory
       
  1361         for ( 
       
  1362           ; 
       
  1363           end_pos > 0
       
  1364           && (end_pos-1) != root_dir_pos
       
  1365           && itr.m_path_ptr->m_path[end_pos-1] == slash<Path>::value
       
  1366           ;
       
  1367           --end_pos ) {}
       
  1368 
       
  1369         itr.m_pos = detail::leaf_pos<string_type, traits_type>
       
  1370             ( itr.m_path_ptr->m_path, end_pos );
       
  1371         itr.m_name = itr.m_path_ptr->m_path.substr( itr.m_pos, end_pos - itr.m_pos );
       
  1372       }
       
  1373     } // namespace detail
       
  1374 
       
  1375     //  basic_filesystem_error implementation --------------------------------//
       
  1376 
       
  1377     template<class Path>
       
  1378     basic_filesystem_error<Path>::basic_filesystem_error(
       
  1379       const std::string & what, system_error_type sys_err_code )
       
  1380       : filesystem_error(what, sys_err_code)
       
  1381     {
       
  1382       try
       
  1383       {
       
  1384         m_imp_ptr.reset( new m_imp );
       
  1385       }
       
  1386       catch (...) { m_imp_ptr.reset(); }
       
  1387     }
       
  1388 
       
  1389     template<class Path>
       
  1390     basic_filesystem_error<Path>::basic_filesystem_error(
       
  1391       const std::string & what, const path_type & path1,
       
  1392       system_error_type sys_err_code )
       
  1393       : filesystem_error(what, sys_err_code)
       
  1394     {
       
  1395       try
       
  1396       {
       
  1397         m_imp_ptr.reset( new m_imp );
       
  1398         m_imp_ptr->m_path1 = path1;
       
  1399       }
       
  1400       catch (...) { m_imp_ptr.reset(); }
       
  1401     }
       
  1402 
       
  1403     template<class Path>
       
  1404     basic_filesystem_error<Path>::basic_filesystem_error(
       
  1405       const std::string & what, const path_type & path1,
       
  1406       const path_type & path2, system_error_type sys_err_code )
       
  1407       : filesystem_error(what, sys_err_code)
       
  1408     {
       
  1409       try
       
  1410       {
       
  1411         m_imp_ptr.reset( new m_imp );
       
  1412         m_imp_ptr->m_path1 = path1;
       
  1413         m_imp_ptr->m_path2 = path2;
       
  1414       }
       
  1415       catch (...) { m_imp_ptr.reset(); }
       
  1416     }
       
  1417 
       
  1418   } // namespace BOOST_FILESYSTEM_NAMESPACE
       
  1419 } // namespace boost
       
  1420 
       
  1421 #include <boost/config/abi_suffix.hpp> // pops abi_prefix.hpp pragmas
       
  1422 
       
  1423 #endif // BOOST_FILESYSTEM_PATH_HPP