Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/boost/filesystem/path.hpp @ 56

Last change on this file since 56 was 29, checked in by landauf, 16 years ago

updated boost from 1_33_1 to 1_34_1

File size: 50.1 KB
Line 
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
36namespace 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
Note: See TracBrowser for help on using the repository browser.