fix doc example typo
[boost.git] / boost / filesystem / path.hpp
blobbfb1aab997b9aec06a8e8c763c1936fc0f1d4764
1 // boost/filesystem/path.hpp -----------------------------------------------//
3 // Copyright Beman Dawes 2002-2005
4 // Copyright Vladimir Prus 2002
6 // Distributed under the Boost Software License, Version 1.0. (See accompanying
7 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9 // See library home page at http://www.boost.org/libs/filesystem
11 // basic_path's stem(), extension(), and replace_extension() are based on
12 // basename(), extension(), and change_extension() from the original
13 // filesystem/convenience.hpp header by Vladimir Prus.
15 //----------------------------------------------------------------------------//
17 #ifndef BOOST_FILESYSTEM_PATH_HPP
18 #define BOOST_FILESYSTEM_PATH_HPP
20 #include <boost/filesystem/config.hpp>
21 #include <boost/system/system_error.hpp>
22 #include <boost/iterator/iterator_facade.hpp>
23 #include <boost/throw_exception.hpp>
24 #include <boost/shared_ptr.hpp>
25 #include <boost/type_traits/is_same.hpp>
26 #include <boost/static_assert.hpp>
28 #include <string>
29 #include <algorithm> // for lexicographical_compare
30 #include <iosfwd> // needed by basic_path inserter and extractor
31 #include <stdexcept>
32 #include <cassert>
34 # ifndef BOOST_FILESYSTEM_NARROW_ONLY
35 # include <locale>
36 # endif
38 #include <boost/config/abi_prefix.hpp> // must be the last #include
40 //----------------------------------------------------------------------------//
42 namespace boost
44 namespace BOOST_FILESYSTEM_NAMESPACE
46 template<class String, class Traits> class basic_path;
48 struct path_traits;
49 typedef basic_path< std::string, path_traits > path;
51 struct path_traits
53 typedef std::string internal_string_type;
54 typedef std::string external_string_type;
55 static external_string_type to_external( const path &,
56 const internal_string_type & src ) { return src; }
57 static internal_string_type to_internal(
58 const external_string_type & src ) { return src; }
61 # ifndef BOOST_FILESYSTEM_NARROW_ONLY
63 struct BOOST_FILESYSTEM_DECL wpath_traits;
65 typedef basic_path< std::wstring, wpath_traits > wpath;
67 struct BOOST_FILESYSTEM_DECL wpath_traits
69 typedef std::wstring internal_string_type;
70 # ifdef BOOST_WINDOWS_API
71 typedef std::wstring external_string_type;
72 static external_string_type to_external( const wpath &,
73 const internal_string_type & src ) { return src; }
74 static internal_string_type to_internal(
75 const external_string_type & src ) { return src; }
76 # else
77 typedef std::string external_string_type;
78 static external_string_type to_external( const wpath & ph,
79 const internal_string_type & src );
80 static internal_string_type to_internal(
81 const external_string_type & src );
82 # endif
83 static void imbue( const std::locale & loc );
84 static bool imbue( const std::locale & loc, const std::nothrow_t & );
87 # endif // ifndef BOOST_FILESYSTEM_NARROW_ONLY
89 // path traits ---------------------------------------------------------//
91 template<class Path> struct is_basic_path
92 { BOOST_STATIC_CONSTANT( bool, value = false ); };
93 template<> struct is_basic_path<path>
94 { BOOST_STATIC_CONSTANT( bool, value = true ); };
95 # ifndef BOOST_FILESYSTEM_NARROW_ONLY
96 template<> struct is_basic_path<wpath>
97 { BOOST_STATIC_CONSTANT( bool, value = true ); };
98 # endif
100 // These only have to be specialized if Path::string_type::value_type
101 // is not convertible from char, although specializations may eliminate
102 // compiler warnings. See ticket 2543.
103 template<class Path> struct slash
104 { BOOST_STATIC_CONSTANT( char, value = '/' ); };
106 template<class Path> struct dot
107 { BOOST_STATIC_CONSTANT( char, value = '.' ); };
109 template<class Path> struct colon
110 { BOOST_STATIC_CONSTANT( char, value = ':' ); };
112 # ifndef BOOST_FILESYSTEM_NARROW_ONLY
113 template<> struct slash<wpath>
114 { BOOST_STATIC_CONSTANT( wchar_t, value = L'/' ); };
115 template<> struct dot<wpath>
116 { BOOST_STATIC_CONSTANT( wchar_t, value = L'.' ); };
117 template<> struct colon<wpath>
118 { BOOST_STATIC_CONSTANT( wchar_t, value = L':' ); };
119 # endif
121 # ifdef BOOST_WINDOWS_PATH
122 template<class Path> struct path_alt_separator
123 { BOOST_STATIC_CONSTANT( char, value = '\\' ); };
124 # ifndef BOOST_FILESYSTEM_NARROW_ONLY
125 template<> struct path_alt_separator<wpath>
126 { BOOST_STATIC_CONSTANT( wchar_t, value = L'\\' ); };
127 # endif
128 # endif
130 // workaround for VC++ 7.0 and earlier issues with nested classes
131 namespace detail
133 template<class Path>
134 class iterator_helper
136 public:
137 typedef typename Path::iterator iterator;
138 static void do_increment( iterator & ph );
139 static void do_decrement( iterator & ph );
143 // basic_path ----------------------------------------------------------//
145 template<class String, class Traits>
146 class basic_path
148 // invariant: m_path valid according to the portable generic path grammar
150 // validate template arguments
151 // TODO: get these working
152 // BOOST_STATIC_ASSERT( ::boost::is_same<String,typename Traits::internal_string_type>::value );
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 );
155 public:
156 // compiler generates copy constructor and copy assignment
158 typedef basic_path<String, Traits> path_type;
159 typedef String string_type;
160 typedef typename String::value_type value_type;
161 typedef Traits traits_type;
162 typedef typename Traits::external_string_type external_string_type;
164 // constructors/destructor
165 basic_path() {}
166 basic_path( const string_type & s ) { operator/=( s ); }
167 basic_path( const value_type * s ) { operator/=( s ); }
168 # ifndef BOOST_NO_MEMBER_TEMPLATES
169 template <class InputIterator>
170 basic_path( InputIterator first, InputIterator last )
171 { append( first, last ); }
172 # endif
173 ~basic_path() {}
175 // assignments
176 basic_path & operator=( const string_type & s )
178 # if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, >= 310)
179 m_path.clear();
180 # else
181 m_path.erase( m_path.begin(), m_path.end() );
182 # endif
183 operator/=( s );
184 return *this;
186 basic_path & operator=( const value_type * s )
188 # if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, >= 310)
189 m_path.clear();
190 # else
191 m_path.erase( m_path.begin(), m_path.end() );
192 # endif
193 operator/=( s );
194 return *this;
196 # ifndef BOOST_NO_MEMBER_TEMPLATES
197 template <class InputIterator>
198 basic_path & assign( InputIterator first, InputIterator last )
199 { m_path.clear(); append( first, last ); return *this; }
200 # endif
202 // modifiers
203 basic_path & operator/=( const basic_path & rhs ) { return operator /=( rhs.string().c_str() ); }
204 basic_path & operator/=( const string_type & rhs ) { return operator /=( rhs.c_str() ); }
205 basic_path & operator/=( const value_type * s );
206 # ifndef BOOST_NO_MEMBER_TEMPLATES
207 template <class InputIterator>
208 basic_path & append( InputIterator first, InputIterator last );
209 # endif
211 void swap( basic_path & rhs )
213 m_path.swap( rhs.m_path );
214 # ifdef BOOST_CYGWIN_PATH
215 std::swap( m_cygwin_root, rhs.m_cygwin_root );
216 # endif
219 basic_path & remove_filename();
220 basic_path & replace_extension( const string_type & new_extension = string_type() );
222 # ifndef BOOST_FILESYSTEM_NO_DEPRECATED
223 basic_path & remove_leaf() { return remove_filename(); }
224 # endif
226 // observers
227 const string_type & string() const { return m_path; }
228 const string_type file_string() const;
229 const string_type directory_string() const { return file_string(); }
231 const external_string_type external_file_string() const { return Traits::to_external( *this, file_string() ); }
232 const external_string_type external_directory_string() const { return Traits::to_external( *this, directory_string() ); }
234 basic_path root_path() const;
235 string_type root_name() const;
236 string_type root_directory() const;
237 basic_path relative_path() const;
238 basic_path parent_path() const;
239 string_type filename() const;
240 string_type stem() const;
241 string_type extension() const;
243 # ifndef BOOST_FILESYSTEM_NO_DEPRECATED
244 string_type leaf() const { return filename(); }
245 basic_path branch_path() const { return parent_path(); }
246 bool has_leaf() const { return !m_path.empty(); }
247 bool has_branch_path() const { return !parent_path().empty(); }
248 # endif
250 bool empty() const { return m_path.empty(); } // name consistent with std containers
251 bool is_complete() const;
252 bool has_root_path() const;
253 bool has_root_name() const;
254 bool has_root_directory() const;
255 bool has_relative_path() const { return !relative_path().empty(); }
256 bool has_filename() const { return !m_path.empty(); }
257 bool has_parent_path() const { return !parent_path().empty(); }
259 // iterators
260 class iterator : public boost::iterator_facade<
261 iterator,
262 string_type const,
263 boost::bidirectional_traversal_tag >
265 private:
266 friend class boost::iterator_core_access;
267 friend class boost::BOOST_FILESYSTEM_NAMESPACE::basic_path<String, Traits>;
269 const string_type & dereference() const
270 { return m_name; }
271 bool equal( const iterator & rhs ) const
272 { return m_path_ptr == rhs.m_path_ptr && m_pos == rhs.m_pos; }
274 friend class boost::BOOST_FILESYSTEM_NAMESPACE::detail::iterator_helper<path_type>;
276 void increment()
278 boost::BOOST_FILESYSTEM_NAMESPACE::detail::iterator_helper<path_type>::do_increment(
279 *this );
281 void decrement()
283 boost::BOOST_FILESYSTEM_NAMESPACE::detail::iterator_helper<path_type>::do_decrement(
284 *this );
287 string_type m_name; // current element
288 const basic_path * m_path_ptr; // path being iterated over
289 typename string_type::size_type m_pos; // position of name in
290 // path_ptr->string(). The
291 // end() iterator is indicated by
292 // pos == path_ptr->m_path.size()
293 }; // iterator
295 typedef iterator const_iterator;
297 iterator begin() const;
298 iterator end() const;
300 private:
301 // Note: This is an implementation for POSIX and Windows, where there
302 // are only minor differences between generic and native path grammars.
303 // Private members might be quite different in other implementations,
304 // particularly where there were wide differences between portable and
305 // native path formats, or between file_string() and
306 // directory_string() formats, or simply that the implementation
307 // was willing expend additional memory to achieve greater speed for
308 // some operations at the expense of other operations.
310 string_type m_path; // invariant: portable path grammar
311 // on Windows, backslashes converted to slashes
313 # ifdef BOOST_CYGWIN_PATH
314 bool m_cygwin_root; // if present, m_path[0] was slash. note: initialization
315 // done by append
316 # endif
318 void m_append_separator_if_needed();
319 void m_append( value_type value ); // converts Windows alt_separator
321 // Was qualified; como433beta8 reports:
322 // warning #427-D: qualified name is not allowed in member declaration
323 friend class iterator;
324 friend class boost::BOOST_FILESYSTEM_NAMESPACE::detail::iterator_helper<path_type>;
326 // Deprecated features ease transition for existing code. Don't use these
327 // in new code.
328 # ifndef BOOST_FILESYSTEM_NO_DEPRECATED
329 public:
330 typedef bool (*name_check)( const std::string & name );
331 basic_path( const string_type & str, name_check ) { operator/=( str ); }
332 basic_path( const typename string_type::value_type * s, name_check )
333 { operator/=( s );}
334 string_type native_file_string() const { return file_string(); }
335 string_type native_directory_string() const { return directory_string(); }
336 static bool default_name_check_writable() { return false; }
337 static void default_name_check( name_check ) {}
338 static name_check default_name_check() { return 0; }
339 basic_path & canonize();
340 basic_path & normalize();
341 # endif
344 // basic_path non-member functions ---------------------------------------//
346 template< class String, class Traits >
347 inline void swap( basic_path<String, Traits> & lhs,
348 basic_path<String, Traits> & rhs ) { lhs.swap( rhs ); }
350 template< class String, class Traits >
351 bool operator<( const basic_path<String, Traits> & lhs, const basic_path<String, Traits> & rhs )
353 return std::lexicographical_compare(
354 lhs.begin(), lhs.end(), rhs.begin(), rhs.end() );
357 template< class String, class Traits >
358 bool operator<( const typename basic_path<String, Traits>::string_type::value_type * lhs,
359 const basic_path<String, Traits> & rhs )
361 basic_path<String, Traits> tmp( lhs );
362 return std::lexicographical_compare(
363 tmp.begin(), tmp.end(), rhs.begin(), rhs.end() );
366 template< class String, class Traits >
367 bool operator<( const typename basic_path<String, Traits>::string_type & lhs,
368 const basic_path<String, Traits> & rhs )
370 basic_path<String, Traits> tmp( lhs );
371 return std::lexicographical_compare(
372 tmp.begin(), tmp.end(), rhs.begin(), rhs.end() );
375 template< class String, class Traits >
376 bool operator<( const basic_path<String, Traits> & lhs,
377 const typename basic_path<String, Traits>::string_type::value_type * rhs )
379 basic_path<String, Traits> tmp( rhs );
380 return std::lexicographical_compare(
381 lhs.begin(), lhs.end(), tmp.begin(), tmp.end() );
384 template< class String, class Traits >
385 bool operator<( const basic_path<String, Traits> & lhs,
386 const typename basic_path<String, Traits>::string_type & rhs )
388 basic_path<String, Traits> tmp( rhs );
389 return std::lexicographical_compare(
390 lhs.begin(), lhs.end(), tmp.begin(), tmp.end() );
393 // operator == uses string compare rather than !(lhs < rhs) && !(rhs < lhs) because
394 // the result is the same yet the direct string compare is much more efficient that
395 // lexicographical_compare, and lexicographical_compare used twice at that.
397 template< class String, class Traits >
398 inline bool operator==( const basic_path<String, Traits> & lhs, const basic_path<String, Traits> & rhs )
400 return lhs.string() == rhs.string();
403 template< class String, class Traits >
404 inline bool operator==( const typename basic_path<String, Traits>::string_type::value_type * lhs,
405 const basic_path<String, Traits> & rhs )
407 return lhs == rhs.string();
410 template< class String, class Traits >
411 inline bool operator==( const typename basic_path<String, Traits>::string_type & lhs,
412 const basic_path<String, Traits> & rhs )
414 return lhs == rhs.string();
417 template< class String, class Traits >
418 inline bool operator==( const basic_path<String, Traits> & lhs,
419 const typename basic_path<String, Traits>::string_type::value_type * rhs )
421 return lhs.string() == rhs;
424 template< class String, class Traits >
425 inline bool operator==( const basic_path<String, Traits> & lhs,
426 const typename basic_path<String, Traits>::string_type & rhs )
428 return lhs.string() == rhs;
431 template< class String, class Traits >
432 inline bool operator!=( const basic_path<String, Traits> & lhs,
433 const basic_path<String, Traits> & rhs )
434 { return !(lhs == rhs); }
436 template< class String, class Traits >
437 inline bool operator!=( const typename basic_path<String,
438 Traits>::string_type::value_type * lhs,
439 const basic_path<String, Traits> & rhs )
440 { return !(lhs == rhs); }
442 template< class String, class Traits >
443 inline bool operator!=( const typename basic_path<String, Traits>::string_type & lhs,
444 const basic_path<String, Traits> & rhs )
445 { return !(lhs == rhs); }
447 template< class String, class Traits >
448 inline bool operator!=( const basic_path<String, Traits> & lhs,
449 const typename basic_path<String, Traits>::string_type::value_type * rhs )
450 { return !(lhs == rhs); }
452 template< class String, class Traits >
453 inline bool operator!=( const basic_path<String, Traits> & lhs,
454 const typename basic_path<String, Traits>::string_type & rhs )
455 { return !(lhs == rhs); }
457 template< class String, class Traits >
458 inline bool operator>( const basic_path<String, Traits> & lhs, const basic_path<String, Traits> & rhs ) { return rhs < lhs; }
460 template< class String, class Traits >
461 inline bool operator>( const typename basic_path<String, Traits>::string_type::value_type * lhs,
462 const basic_path<String, Traits> & rhs ) { return rhs < basic_path<String, Traits>(lhs); }
464 template< class String, class Traits >
465 inline bool operator>( const typename basic_path<String, Traits>::string_type & lhs,
466 const basic_path<String, Traits> & rhs ) { return rhs < basic_path<String, Traits>(lhs); }
468 template< class String, class Traits >
469 inline bool operator>( const basic_path<String, Traits> & lhs,
470 const typename basic_path<String, Traits>::string_type::value_type * rhs )
471 { return basic_path<String, Traits>(rhs) < lhs; }
473 template< class String, class Traits >
474 inline bool operator>( const basic_path<String, Traits> & lhs,
475 const typename basic_path<String, Traits>::string_type & rhs )
476 { return basic_path<String, Traits>(rhs) < lhs; }
478 template< class String, class Traits >
479 inline bool operator<=( const basic_path<String, Traits> & lhs, const basic_path<String, Traits> & rhs ) { return !(rhs < lhs); }
481 template< class String, class Traits >
482 inline bool operator<=( const typename basic_path<String, Traits>::string_type::value_type * lhs,
483 const basic_path<String, Traits> & rhs ) { return !(rhs < basic_path<String, Traits>(lhs)); }
485 template< class String, class Traits >
486 inline bool operator<=( const typename basic_path<String, Traits>::string_type & lhs,
487 const basic_path<String, Traits> & rhs ) { return !(rhs < basic_path<String, Traits>(lhs)); }
489 template< class String, class Traits >
490 inline bool operator<=( const basic_path<String, Traits> & lhs,
491 const typename basic_path<String, Traits>::string_type::value_type * rhs )
492 { return !(basic_path<String, Traits>(rhs) < lhs); }
494 template< class String, class Traits >
495 inline bool operator<=( const basic_path<String, Traits> & lhs,
496 const typename basic_path<String, Traits>::string_type & rhs )
497 { return !(basic_path<String, Traits>(rhs) < lhs); }
499 template< class String, class Traits >
500 inline bool operator>=( const basic_path<String, Traits> & lhs, const basic_path<String, Traits> & rhs ) { return !(lhs < rhs); }
502 template< class String, class Traits >
503 inline bool operator>=( const typename basic_path<String, Traits>::string_type::value_type * lhs,
504 const basic_path<String, Traits> & rhs ) { return !(lhs < basic_path<String, Traits>(rhs)); }
506 template< class String, class Traits >
507 inline bool operator>=( const typename basic_path<String, Traits>::string_type & lhs,
508 const basic_path<String, Traits> & rhs ) { return !(lhs < basic_path<String, Traits>(rhs)); }
510 template< class String, class Traits >
511 inline bool operator>=( const basic_path<String, Traits> & lhs,
512 const typename basic_path<String, Traits>::string_type::value_type * rhs )
513 { return !(basic_path<String, Traits>(lhs) < rhs); }
515 template< class String, class Traits >
516 inline bool operator>=( const basic_path<String, Traits> & lhs,
517 const typename basic_path<String, Traits>::string_type & rhs )
518 { return !(basic_path<String, Traits>(lhs) < rhs); }
520 // operator /
522 template< class String, class Traits >
523 inline basic_path<String, Traits> operator/(
524 const basic_path<String, Traits> & lhs,
525 const basic_path<String, Traits> & rhs )
526 { return basic_path<String, Traits>( lhs ) /= rhs; }
528 template< class String, class Traits >
529 inline basic_path<String, Traits> operator/(
530 const basic_path<String, Traits> & lhs,
531 const typename String::value_type * rhs )
532 { return basic_path<String, Traits>( lhs ) /=
533 basic_path<String, Traits>( rhs ); }
535 template< class String, class Traits >
536 inline basic_path<String, Traits> operator/(
537 const basic_path<String, Traits> & lhs, const String & rhs )
538 { return basic_path<String, Traits>( lhs ) /=
539 basic_path<String, Traits>( rhs ); }
541 template< class String, class Traits >
542 inline basic_path<String, Traits> operator/(
543 const typename String::value_type * lhs,
544 const basic_path<String, Traits> & rhs )
545 { return basic_path<String, Traits>( lhs ) /= rhs; }
547 template< class String, class Traits >
548 inline basic_path<String, Traits> operator/(
549 const String & lhs, const basic_path<String, Traits> & rhs )
550 { return basic_path<String, Traits>( lhs ) /= rhs; }
552 // inserters and extractors --------------------------------------------//
554 // bypass VC++ 7.0 and earlier, and broken Borland compilers
555 # if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) && !BOOST_WORKAROUND(__BORLANDC__, < 0x610)
556 template< class Path >
557 std::basic_ostream< typename Path::string_type::value_type,
558 typename Path::string_type::traits_type > &
559 operator<<
560 ( std::basic_ostream< typename Path::string_type::value_type,
561 typename Path::string_type::traits_type >& os, const Path & ph )
563 os << ph.string();
564 return os;
567 template< class Path >
568 std::basic_istream< typename Path::string_type::value_type,
569 typename Path::string_type::traits_type > &
570 operator>>
571 ( std::basic_istream< typename Path::string_type::value_type,
572 typename Path::string_type::traits_type >& is, Path & ph )
574 typename Path::string_type str;
575 is >> str;
576 ph = str;
577 return is;
579 # elif BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
580 template< class String, class Traits >
581 std::basic_ostream< BOOST_DEDUCED_TYPENAME String::value_type,
582 BOOST_DEDUCED_TYPENAME String::traits_type > &
583 operator<<
584 ( std::basic_ostream< BOOST_DEDUCED_TYPENAME String::value_type,
585 BOOST_DEDUCED_TYPENAME String::traits_type >& os,
586 const basic_path< String, Traits > & ph )
588 os << ph.string();
589 return os;
592 template< class String, class Traits >
593 std::basic_istream< BOOST_DEDUCED_TYPENAME String::value_type,
594 BOOST_DEDUCED_TYPENAME String::traits_type > &
595 operator>>
596 ( std::basic_istream< BOOST_DEDUCED_TYPENAME String::value_type,
597 BOOST_DEDUCED_TYPENAME String::traits_type> & is,
598 basic_path< String, Traits > & ph )
600 String str;
601 is >> str;
602 ph = str;
603 return is;
605 # endif
607 // basic_filesystem_error helpers --------------------------------------//
609 // Originally choice of implementation was done via specialization of
610 // basic_filesystem_error::what(). Several compilers (GCC, aCC, etc.)
611 // couldn't handle that, so the choice is now accomplished by overloading.
613 namespace detail
615 // BOOST_FILESYSTEM_DECL version works for VC++ but not GCC. Go figure!
616 inline
617 const char * what( const char * sys_err_what,
618 const path & path1_arg, const path & path2_arg, std::string & target )
622 if ( target.empty() )
624 target = sys_err_what;
625 if ( !path1_arg.empty() )
627 target += ": \"";
628 target += path1_arg.file_string();
629 target += "\"";
631 if ( !path2_arg.empty() )
633 target += ", \"";
634 target += path2_arg.file_string();
635 target += "\"";
638 return target.c_str();
640 catch (...)
642 return sys_err_what;
646 template<class Path>
647 const char * what( const char * sys_err_what,
648 const Path & /*path1_arg*/, const Path & /*path2_arg*/, std::string & /*target*/ )
650 return sys_err_what;
654 // basic_filesystem_error ----------------------------------------------//
656 template<class Path>
657 class basic_filesystem_error : public system::system_error
659 // see http://www.boost.org/more/error_handling.html for design rationale
660 public:
661 // compiler generates copy constructor and copy assignment
663 typedef Path path_type;
665 basic_filesystem_error( const std::string & what_arg,
666 system::error_code ec );
668 basic_filesystem_error( const std::string & what_arg,
669 const path_type & path1_arg, system::error_code ec );
671 basic_filesystem_error( const std::string & what_arg, const path_type & path1_arg,
672 const path_type & path2_arg, system::error_code ec );
674 ~basic_filesystem_error() throw() {}
676 const path_type & path1() const
678 static const path_type empty_path;
679 return m_imp_ptr.get() ? m_imp_ptr->m_path1 : empty_path ;
681 const path_type & path2() const
683 static const path_type empty_path;
684 return m_imp_ptr.get() ? m_imp_ptr->m_path2 : empty_path ;
687 const char * what() const throw()
689 if ( !m_imp_ptr.get() )
690 return system::system_error::what();
691 return detail::what( system::system_error::what(), m_imp_ptr->m_path1,
692 m_imp_ptr->m_path2, m_imp_ptr->m_what );
695 private:
696 struct m_imp
698 path_type m_path1; // may be empty()
699 path_type m_path2; // may be empty()
700 std::string m_what; // not built until needed
702 boost::shared_ptr<m_imp> m_imp_ptr;
705 typedef basic_filesystem_error<path> filesystem_error;
707 # ifndef BOOST_FILESYSTEM_NARROW_ONLY
708 typedef basic_filesystem_error<wpath> wfilesystem_error;
709 # endif
711 // path::name_checks -----------------------------------------------------//
713 BOOST_FILESYSTEM_DECL bool portable_posix_name( const std::string & name );
714 BOOST_FILESYSTEM_DECL bool windows_name( const std::string & name );
715 BOOST_FILESYSTEM_DECL bool portable_name( const std::string & name );
716 BOOST_FILESYSTEM_DECL bool portable_directory_name( const std::string & name );
717 BOOST_FILESYSTEM_DECL bool portable_file_name( const std::string & name );
718 BOOST_FILESYSTEM_DECL bool native( const std::string & name );
719 inline bool no_check( const std::string & )
720 { return true; }
722 // implementation -----------------------------------------------------------//
724 namespace detail
727 // is_separator helper ------------------------------------------------//
729 template<class Path>
730 inline bool is_separator( typename Path::string_type::value_type c )
732 return c == slash<Path>::value
733 # ifdef BOOST_WINDOWS_PATH
734 || c == path_alt_separator<Path>::value
735 # endif
739 // filename_pos helper ----------------------------------------------------//
741 template<class String, class Traits>
742 typename String::size_type filename_pos(
743 const String & str, // precondition: portable generic path grammar
744 typename String::size_type end_pos ) // end_pos is past-the-end position
745 // return 0 if str itself is filename (or empty)
747 typedef typename
748 boost::BOOST_FILESYSTEM_NAMESPACE::basic_path<String, Traits> path_type;
750 // case: "//"
751 if ( end_pos == 2
752 && str[0] == slash<path_type>::value
753 && str[1] == slash<path_type>::value ) return 0;
755 // case: ends in "/"
756 if ( end_pos && str[end_pos-1] == slash<path_type>::value )
757 return end_pos-1;
759 // set pos to start of last element
760 typename String::size_type pos(
761 str.find_last_of( slash<path_type>::value, end_pos-1 ) );
762 # ifdef BOOST_WINDOWS_PATH
763 if ( pos == String::npos )
764 pos = str.find_last_of( path_alt_separator<path_type>::value, end_pos-1 );
765 if ( pos == String::npos )
766 pos = str.find_last_of( colon<path_type>::value, end_pos-2 );
767 # endif
769 return ( pos == String::npos // path itself must be a filename (or empty)
770 || (pos == 1 && str[0] == slash<path_type>::value) ) // or net
771 ? 0 // so filename is entire string
772 : pos + 1; // or starts after delimiter
775 // first_element helper -----------------------------------------------//
776 // sets pos and len of first element, excluding extra separators
777 // if src.empty(), sets pos,len, to 0,0.
779 template<class String, class Traits>
780 void first_element(
781 const String & src, // precondition: portable generic path grammar
782 typename String::size_type & element_pos,
783 typename String::size_type & element_size,
784 # if !BOOST_WORKAROUND( BOOST_MSVC, <= 1310 ) // VC++ 7.1
785 typename String::size_type size = String::npos
786 # else
787 typename String::size_type size = -1
788 # endif
791 if ( size == String::npos ) size = src.size();
792 element_pos = 0;
793 element_size = 0;
794 if ( src.empty() ) return;
796 typedef typename boost::BOOST_FILESYSTEM_NAMESPACE::basic_path<String, Traits> path_type;
798 typename String::size_type cur(0);
800 // deal with // [network]
801 if ( size >= 2 && src[0] == slash<path_type>::value
802 && src[1] == slash<path_type>::value
803 && (size == 2
804 || src[2] != slash<path_type>::value) )
806 cur += 2;
807 element_size += 2;
810 // leading (not non-network) separator
811 else if ( src[0] == slash<path_type>::value )
813 ++element_size;
814 // bypass extra leading separators
815 while ( cur+1 < size
816 && src[cur+1] == slash<path_type>::value )
818 ++cur;
819 ++element_pos;
821 return;
824 // at this point, we have either a plain name, a network name,
825 // or (on Windows only) a device name
827 // find the end
828 while ( cur < size
829 # ifdef BOOST_WINDOWS_PATH
830 && src[cur] != colon<path_type>::value
831 # endif
832 && src[cur] != slash<path_type>::value )
834 ++cur;
835 ++element_size;
838 # ifdef BOOST_WINDOWS_PATH
839 if ( cur == size ) return;
840 // include device delimiter
841 if ( src[cur] == colon<path_type>::value )
842 { ++element_size; }
843 # endif
845 return;
848 // root_directory_start helper ----------------------------------------//
850 template<class String, class Traits>
851 typename String::size_type root_directory_start(
852 const String & s, // precondition: portable generic path grammar
853 typename String::size_type size )
854 // return npos if no root_directory found
856 typedef typename boost::BOOST_FILESYSTEM_NAMESPACE::basic_path<String, Traits> path_type;
858 # ifdef BOOST_WINDOWS_PATH
859 // case "c:/"
860 if ( size > 2
861 && s[1] == colon<path_type>::value
862 && s[2] == slash<path_type>::value ) return 2;
863 # endif
865 // case "//"
866 if ( size == 2
867 && s[0] == slash<path_type>::value
868 && s[1] == slash<path_type>::value ) return String::npos;
870 // case "//net {/}"
871 if ( size > 3
872 && s[0] == slash<path_type>::value
873 && s[1] == slash<path_type>::value
874 && s[2] != slash<path_type>::value )
876 typename String::size_type pos(
877 s.find( slash<path_type>::value, 2 ) );
878 return pos < size ? pos : String::npos;
881 // case "/"
882 if ( size > 0 && s[0] == slash<path_type>::value ) return 0;
884 return String::npos;
887 // is_non_root_slash helper -------------------------------------------//
889 template<class String, class Traits>
890 bool is_non_root_slash( const String & str,
891 typename String::size_type pos ) // pos is position of the slash
893 typedef typename
894 boost::BOOST_FILESYSTEM_NAMESPACE::basic_path<String, Traits>
895 path_type;
897 assert( !str.empty() && str[pos] == slash<path_type>::value
898 && "precondition violation" );
900 // subsequent logic expects pos to be for leftmost slash of a set
901 while ( pos > 0 && str[pos-1] == slash<path_type>::value )
902 --pos;
904 return pos != 0
905 && (pos <= 2 || str[1] != slash<path_type>::value
906 || str.find( slash<path_type>::value, 2 ) != pos)
907 # ifdef BOOST_WINDOWS_PATH
908 && (pos !=2 || str[1] != colon<path_type>::value)
909 # endif
912 } // namespace detail
914 // decomposition functions ----------------------------------------------//
916 template<class String, class Traits>
917 String basic_path<String, Traits>::filename() const
919 typename String::size_type end_pos(
920 detail::filename_pos<String, Traits>( m_path, m_path.size() ) );
921 return (m_path.size()
922 && end_pos
923 && m_path[end_pos] == slash<path_type>::value
924 && detail::is_non_root_slash< String, Traits >(m_path, end_pos))
925 ? String( 1, dot<path_type>::value )
926 : m_path.substr( end_pos );
929 template<class String, class Traits>
930 String basic_path<String, Traits>::stem() const
932 string_type name = filename();
933 typename string_type::size_type n = name.rfind('.');
934 return name.substr(0, n);
937 template<class String, class Traits>
938 String basic_path<String, Traits>::extension() const
940 string_type name = filename();
941 typename string_type::size_type n = name.rfind('.');
942 if (n != string_type::npos)
943 return name.substr(n);
944 else
945 return string_type();
948 template<class String, class Traits>
949 basic_path<String, Traits> basic_path<String, Traits>::parent_path() const
951 typename String::size_type end_pos(
952 detail::filename_pos<String, Traits>( m_path, m_path.size() ) );
954 bool filename_was_separator( m_path.size()
955 && m_path[end_pos] == slash<path_type>::value );
957 // skip separators unless root directory
958 typename string_type::size_type root_dir_pos( detail::root_directory_start
959 <string_type, traits_type>( m_path, end_pos ) );
960 for ( ;
961 end_pos > 0
962 && (end_pos-1) != root_dir_pos
963 && m_path[end_pos-1] == slash<path_type>::value
965 --end_pos ) {}
967 return (end_pos == 1 && root_dir_pos == 0 && filename_was_separator)
968 ? path_type()
969 : path_type( m_path.substr( 0, end_pos ) );
972 template<class String, class Traits>
973 basic_path<String, Traits> basic_path<String, Traits>::relative_path() const
975 iterator itr( begin() );
976 for ( ; itr.m_pos != m_path.size()
977 && (itr.m_name[0] == slash<path_type>::value
978 # ifdef BOOST_WINDOWS_PATH
979 || itr.m_name[itr.m_name.size()-1]
980 == colon<path_type>::value
981 # endif
982 ); ++itr ) {}
984 return basic_path<String, Traits>( m_path.substr( itr.m_pos ) );
987 template<class String, class Traits>
988 String basic_path<String, Traits>::root_name() const
990 iterator itr( begin() );
992 return ( itr.m_pos != m_path.size()
993 && (
994 ( itr.m_name.size() > 1
995 && itr.m_name[0] == slash<path_type>::value
996 && itr.m_name[1] == slash<path_type>::value
998 # ifdef BOOST_WINDOWS_PATH
999 || itr.m_name[itr.m_name.size()-1]
1000 == colon<path_type>::value
1001 # endif
1003 ? *itr
1004 : String();
1007 template<class String, class Traits>
1008 String basic_path<String, Traits>::root_directory() const
1010 typename string_type::size_type start(
1011 detail::root_directory_start<String, Traits>( m_path, m_path.size() ) );
1013 return start == string_type::npos
1014 ? string_type()
1015 : m_path.substr( start, 1 );
1018 template<class String, class Traits>
1019 basic_path<String, Traits> basic_path<String, Traits>::root_path() const
1021 // even on POSIX, root_name() is non-empty() on network paths
1022 return basic_path<String, Traits>( root_name() ) /= root_directory();
1025 // path query functions -------------------------------------------------//
1027 template<class String, class Traits>
1028 inline bool basic_path<String, Traits>::is_complete() const
1030 # ifdef BOOST_WINDOWS_PATH
1031 return has_root_name() && has_root_directory();
1032 # else
1033 return has_root_directory();
1034 # endif
1037 template<class String, class Traits>
1038 inline bool basic_path<String, Traits>::has_root_path() const
1040 return !root_path().empty();
1043 template<class String, class Traits>
1044 inline bool basic_path<String, Traits>::has_root_name() const
1046 return !root_name().empty();
1049 template<class String, class Traits>
1050 inline bool basic_path<String, Traits>::has_root_directory() const
1052 return !root_directory().empty();
1055 // append ---------------------------------------------------------------//
1057 template<class String, class Traits>
1058 void basic_path<String, Traits>::m_append_separator_if_needed()
1059 // requires: !empty()
1061 if (
1062 # ifdef BOOST_WINDOWS_PATH
1063 *(m_path.end()-1) != colon<path_type>::value &&
1064 # endif
1065 *(m_path.end()-1) != slash<path_type>::value )
1067 m_path += slash<path_type>::value;
1071 template<class String, class Traits>
1072 void basic_path<String, Traits>::m_append( value_type value )
1074 # ifdef BOOST_CYGWIN_PATH
1075 if ( m_path.empty() ) m_cygwin_root = (value == slash<path_type>::value);
1076 # endif
1078 # ifdef BOOST_WINDOWS_PATH
1079 // for BOOST_WINDOWS_PATH, convert alt_separator ('\') to separator ('/')
1080 m_path += ( value == path_alt_separator<path_type>::value
1081 ? slash<path_type>::value
1082 : value );
1083 # else
1084 m_path += value;
1085 # endif
1088 // except that it wouldn't work for BOOST_NO_MEMBER_TEMPLATES compilers,
1089 // the append() member template could replace this code.
1090 template<class String, class Traits>
1091 basic_path<String, Traits> & basic_path<String, Traits>::operator /=
1092 ( const value_type * next_p )
1094 // ignore escape sequence on POSIX or Windows
1095 if ( *next_p == slash<path_type>::value
1096 && *(next_p+1) == slash<path_type>::value
1097 && *(next_p+2) == colon<path_type>::value ) next_p += 3;
1099 // append slash<path_type>::value if needed
1100 if ( !empty() && *next_p != 0
1101 && !detail::is_separator<path_type>( *next_p ) )
1102 { m_append_separator_if_needed(); }
1104 for ( ; *next_p != 0; ++next_p ) m_append( *next_p );
1105 return *this;
1108 # ifndef BOOST_NO_MEMBER_TEMPLATES
1109 template<class String, class Traits> template <class InputIterator>
1110 basic_path<String, Traits> & basic_path<String, Traits>::append(
1111 InputIterator first, InputIterator last )
1113 // append slash<path_type>::value if needed
1114 if ( !empty() && first != last
1115 && !detail::is_separator<path_type>( *first ) )
1116 { m_append_separator_if_needed(); }
1118 // song-and-dance to avoid violating InputIterator requirements
1119 // (which prohibit lookahead) in detecting a possible escape sequence
1120 // (escape sequences are simply ignored on POSIX and Windows)
1121 bool was_escape_sequence(true);
1122 std::size_t append_count(0);
1123 typename String::size_type initial_pos( m_path.size() );
1125 for ( ; first != last && *first; ++first )
1127 if ( append_count == 0 && *first != slash<path_type>::value )
1128 was_escape_sequence = false;
1129 if ( append_count == 1 && *first != slash<path_type>::value )
1130 was_escape_sequence = false;
1131 if ( append_count == 2 && *first != colon<path_type>::value )
1132 was_escape_sequence = false;
1133 m_append( *first );
1134 ++append_count;
1137 // erase escape sequence if any
1138 if ( was_escape_sequence && append_count >= 3 )
1139 m_path.erase( initial_pos, 3 );
1141 return *this;
1143 # endif
1145 # ifndef BOOST_FILESYSTEM_NO_DEPRECATED
1147 // canonize ------------------------------------------------------------//
1149 template<class String, class Traits>
1150 basic_path<String, Traits> & basic_path<String, Traits>::canonize()
1152 static const typename string_type::value_type dot_str[]
1153 = { dot<path_type>::value, 0 };
1155 if ( m_path.empty() ) return *this;
1157 path_type temp;
1159 for ( iterator itr( begin() ); itr != end(); ++itr )
1161 temp /= *itr;
1164 if ( temp.empty() ) temp /= dot_str;
1165 m_path = temp.m_path;
1166 return *this;
1169 // normalize ------------------------------------------------------------//
1171 template<class String, class Traits>
1172 basic_path<String, Traits> & basic_path<String, Traits>::normalize()
1174 static const typename string_type::value_type dot_str[]
1175 = { dot<path_type>::value, 0 };
1177 if ( m_path.empty() ) return *this;
1179 path_type temp;
1180 iterator start( begin() );
1181 iterator last( end() );
1182 iterator stop( last-- );
1183 for ( iterator itr( start ); itr != stop; ++itr )
1185 // ignore "." except at start and last
1186 if ( itr->size() == 1
1187 && (*itr)[0] == dot<path_type>::value
1188 && itr != start
1189 && itr != last ) continue;
1191 // ignore a name and following ".."
1192 if ( !temp.empty()
1193 && itr->size() == 2
1194 && (*itr)[0] == dot<path_type>::value
1195 && (*itr)[1] == dot<path_type>::value ) // dot dot
1197 string_type lf( temp.filename() );
1198 if ( lf.size() > 0
1199 && (lf.size() != 1
1200 || (lf[0] != dot<path_type>::value
1201 && lf[0] != slash<path_type>::value))
1202 && (lf.size() != 2
1203 || (lf[0] != dot<path_type>::value
1204 && lf[1] != dot<path_type>::value
1205 # ifdef BOOST_WINDOWS_PATH
1206 && lf[1] != colon<path_type>::value
1207 # endif
1212 temp.remove_filename();
1213 // if not root directory, must also remove "/" if any
1214 if ( temp.m_path.size() > 0
1215 && temp.m_path[temp.m_path.size()-1]
1216 == slash<path_type>::value )
1218 typename string_type::size_type rds(
1219 detail::root_directory_start<String,Traits>( temp.m_path,
1220 temp.m_path.size() ) );
1221 if ( rds == string_type::npos
1222 || rds != temp.m_path.size()-1 )
1223 { temp.m_path.erase( temp.m_path.size()-1 ); }
1226 iterator next( itr );
1227 if ( temp.empty() && ++next != stop
1228 && next == last && *last == dot_str ) temp /= dot_str;
1229 continue;
1233 temp /= *itr;
1236 if ( temp.empty() ) temp /= dot_str;
1237 m_path = temp.m_path;
1238 return *this;
1241 # endif
1243 // modifiers ------------------------------------------------------------//
1245 template<class String, class Traits>
1246 basic_path<String, Traits> & basic_path<String, Traits>::remove_filename()
1248 m_path.erase(
1249 detail::filename_pos<String, Traits>( m_path, m_path.size() ) );
1250 return *this;
1253 template<class String, class Traits>
1254 basic_path<String, Traits> &
1255 basic_path<String, Traits>::replace_extension( const string_type & new_ext )
1257 // erase existing extension if any
1258 string_type old_ext = extension();
1259 if ( !old_ext.empty() )
1260 m_path.erase( m_path.size() - old_ext.size() );
1262 if ( !new_ext.empty() && new_ext[0] != dot<path_type>::value )
1263 m_path += dot<path_type>::value;
1265 m_path += new_ext;
1267 return *this;
1271 // path conversion functions --------------------------------------------//
1273 template<class String, class Traits>
1274 const String
1275 basic_path<String, Traits>::file_string() const
1277 # ifdef BOOST_WINDOWS_PATH
1278 // for Windows, use the alternate separator, and bypass extra
1279 // root separators
1281 typename string_type::size_type root_dir_start(
1282 detail::root_directory_start<String, Traits>( m_path, m_path.size() ) );
1283 bool in_root( root_dir_start != string_type::npos );
1284 String s;
1285 for ( typename string_type::size_type pos( 0 );
1286 pos != m_path.size(); ++pos )
1288 // special case // [net]
1289 if ( pos == 0 && m_path.size() > 1
1290 && m_path[0] == slash<path_type>::value
1291 && m_path[1] == slash<path_type>::value
1292 && ( m_path.size() == 2
1293 || !detail::is_separator<path_type>( m_path[2] )
1296 ++pos;
1297 s += path_alt_separator<path_type>::value;
1298 s += path_alt_separator<path_type>::value;
1299 continue;
1302 // bypass extra root separators
1303 if ( in_root )
1305 if ( s.size() > 0
1306 && s[s.size()-1] == path_alt_separator<path_type>::value
1307 && m_path[pos] == slash<path_type>::value
1308 ) continue;
1311 if ( m_path[pos] == slash<path_type>::value )
1312 s += path_alt_separator<path_type>::value;
1313 else
1314 s += m_path[pos];
1316 if ( pos > root_dir_start
1317 && m_path[pos] == slash<path_type>::value )
1318 { in_root = false; }
1320 # ifdef BOOST_CYGWIN_PATH
1321 if ( m_cygwin_root ) s[0] = slash<path_type>::value;
1322 # endif
1323 return s;
1324 # else
1325 return m_path;
1326 # endif
1329 // iterator functions ---------------------------------------------------//
1331 template<class String, class Traits>
1332 typename basic_path<String, Traits>::iterator basic_path<String, Traits>::begin() const
1334 iterator itr;
1335 itr.m_path_ptr = this;
1336 typename string_type::size_type element_size;
1337 detail::first_element<String, Traits>( m_path, itr.m_pos, element_size );
1338 itr.m_name = m_path.substr( itr.m_pos, element_size );
1339 return itr;
1342 template<class String, class Traits>
1343 typename basic_path<String, Traits>::iterator basic_path<String, Traits>::end() const
1345 iterator itr;
1346 itr.m_path_ptr = this;
1347 itr.m_pos = m_path.size();
1348 return itr;
1351 namespace detail
1353 // do_increment ------------------------------------------------------//
1355 template<class Path>
1356 void iterator_helper<Path>::do_increment( iterator & itr )
1358 typedef typename Path::string_type string_type;
1359 typedef typename Path::traits_type traits_type;
1361 assert( itr.m_pos < itr.m_path_ptr->m_path.size() && "basic_path::iterator increment past end()" );
1363 bool was_net( itr.m_name.size() > 2
1364 && itr.m_name[0] == slash<Path>::value
1365 && itr.m_name[1] == slash<Path>::value
1366 && itr.m_name[2] != slash<Path>::value );
1368 // increment to position past current element
1369 itr.m_pos += itr.m_name.size();
1371 // if end reached, create end iterator
1372 if ( itr.m_pos == itr.m_path_ptr->m_path.size() )
1374 itr.m_name.erase( itr.m_name.begin(), itr.m_name.end() ); // VC++ 6.0 lib didn't supply clear()
1375 return;
1378 // process separator (Windows drive spec is only case not a separator)
1379 if ( itr.m_path_ptr->m_path[itr.m_pos] == slash<Path>::value )
1381 // detect root directory
1382 if ( was_net
1383 # ifdef BOOST_WINDOWS_PATH
1384 // case "c:/"
1385 || itr.m_name[itr.m_name.size()-1] == colon<Path>::value
1386 # endif
1389 itr.m_name = slash<Path>::value;
1390 return;
1393 // bypass separators
1394 while ( itr.m_pos != itr.m_path_ptr->m_path.size()
1395 && itr.m_path_ptr->m_path[itr.m_pos] == slash<Path>::value )
1396 { ++itr.m_pos; }
1398 // detect trailing separator, and treat it as ".", per POSIX spec
1399 if ( itr.m_pos == itr.m_path_ptr->m_path.size()
1400 && detail::is_non_root_slash< string_type, traits_type >(
1401 itr.m_path_ptr->m_path, itr.m_pos-1 ) )
1403 --itr.m_pos;
1404 itr.m_name = dot<Path>::value;
1405 return;
1409 // get next element
1410 typename string_type::size_type end_pos(
1411 itr.m_path_ptr->m_path.find( slash<Path>::value, itr.m_pos ) );
1412 itr.m_name = itr.m_path_ptr->m_path.substr( itr.m_pos, end_pos - itr.m_pos );
1415 // do_decrement ------------------------------------------------------//
1417 template<class Path>
1418 void iterator_helper<Path>::do_decrement( iterator & itr )
1420 assert( itr.m_pos && "basic_path::iterator decrement past begin()" );
1422 typedef typename Path::string_type string_type;
1423 typedef typename Path::traits_type traits_type;
1425 typename string_type::size_type end_pos( itr.m_pos );
1427 typename string_type::size_type root_dir_pos(
1428 detail::root_directory_start<string_type, traits_type>(
1429 itr.m_path_ptr->m_path, end_pos ) );
1431 // if at end and there was a trailing non-root '/', return "."
1432 if ( itr.m_pos == itr.m_path_ptr->m_path.size()
1433 && itr.m_path_ptr->m_path.size() > 1
1434 && itr.m_path_ptr->m_path[itr.m_pos-1] == slash<Path>::value
1435 && detail::is_non_root_slash< string_type, traits_type >(
1436 itr.m_path_ptr->m_path, itr.m_pos-1 )
1439 --itr.m_pos;
1440 itr.m_name = dot<Path>::value;
1441 return;
1444 // skip separators unless root directory
1445 for (
1447 end_pos > 0
1448 && (end_pos-1) != root_dir_pos
1449 && itr.m_path_ptr->m_path[end_pos-1] == slash<Path>::value
1451 --end_pos ) {}
1453 itr.m_pos = detail::filename_pos<string_type, traits_type>
1454 ( itr.m_path_ptr->m_path, end_pos );
1455 itr.m_name = itr.m_path_ptr->m_path.substr( itr.m_pos, end_pos - itr.m_pos );
1457 } // namespace detail
1459 // basic_filesystem_error implementation --------------------------------//
1461 template<class Path>
1462 basic_filesystem_error<Path>::basic_filesystem_error(
1463 const std::string & what_arg, system::error_code ec )
1464 : system::system_error(ec, what_arg)
1468 m_imp_ptr.reset( new m_imp );
1470 catch (...) { m_imp_ptr.reset(); }
1473 template<class Path>
1474 basic_filesystem_error<Path>::basic_filesystem_error(
1475 const std::string & what_arg, const path_type & path1_arg,
1476 system::error_code ec )
1477 : system::system_error(ec, what_arg)
1481 m_imp_ptr.reset( new m_imp );
1482 m_imp_ptr->m_path1 = path1_arg;
1484 catch (...) { m_imp_ptr.reset(); }
1487 template<class Path>
1488 basic_filesystem_error<Path>::basic_filesystem_error(
1489 const std::string & what_arg, const path_type & path1_arg,
1490 const path_type & path2_arg, system::error_code ec )
1491 : system::system_error(ec, what_arg)
1495 m_imp_ptr.reset( new m_imp );
1496 m_imp_ptr->m_path1 = path1_arg;
1497 m_imp_ptr->m_path2 = path2_arg;
1499 catch (...) { m_imp_ptr.reset(); }
1502 } // namespace BOOST_FILESYSTEM_NAMESPACE
1503 } // namespace boost
1505 #include <boost/config/abi_suffix.hpp> // pops abi_prefix.hpp pragmas
1507 #endif // BOOST_FILESYSTEM_PATH_HPP