]> AND Private Git Repository - canny.git/blob - stc/exp/ml_stc_linux_make_v1.0/include/boost/filesystem/path.hpp
Logo AND Algorithmique Numérique Distribuée

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