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>
29 #include <algorithm> // for lexicographical_compare
30 #include <iosfwd> // needed by basic_path inserter and extractor
34 # ifndef BOOST_FILESYSTEM_NARROW_ONLY
38 #include <boost/config/abi_prefix.hpp> // must be the last #include
40 //----------------------------------------------------------------------------//
44 namespace BOOST_FILESYSTEM_NAMESPACE
46 template<class String
, class Traits
> class basic_path
;
49 typedef basic_path
< std::string
, path_traits
> path
;
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
; }
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
);
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 ); };
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
':' ); };
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
'\\' ); };
130 // workaround for VC++ 7.0 and earlier issues with nested classes
134 class iterator_helper
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
>
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 );
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
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
); }
176 basic_path
& operator=( const string_type
& s
)
178 # if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, >= 310)
181 m_path
.erase( m_path
.begin(), m_path
.end() );
186 basic_path
& operator=( const value_type
* s
)
188 # if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, >= 310)
191 m_path
.erase( m_path
.begin(), m_path
.end() );
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; }
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
);
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
);
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(); }
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(); }
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(); }
260 class iterator
: public boost::iterator_facade
<
263 boost::bidirectional_traversal_tag
>
266 friend class boost::iterator_core_access
;
267 friend class boost::BOOST_FILESYSTEM_NAMESPACE::basic_path
<String
, Traits
>;
269 const string_type
& dereference() const
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
>;
278 boost::BOOST_FILESYSTEM_NAMESPACE::detail::iterator_helper
<path_type
>::do_increment(
283 boost::BOOST_FILESYSTEM_NAMESPACE::detail::iterator_helper
<path_type
>::do_decrement(
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()
295 typedef iterator const_iterator
;
297 iterator
begin() const;
298 iterator
end() const;
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
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
328 # ifndef BOOST_FILESYSTEM_NO_DEPRECATED
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
)
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();
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
); }
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
> &
560 ( std::basic_ostream
< typename
Path::string_type::value_type
,
561 typename
Path::string_type::traits_type
>& os
, const Path
& ph
)
567 template< class Path
>
568 std::basic_istream
< typename
Path::string_type::value_type
,
569 typename
Path::string_type::traits_type
> &
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
;
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
> &
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
)
592 template< class String
, class Traits
>
593 std::basic_istream
< BOOST_DEDUCED_TYPENAME
String::value_type
,
594 BOOST_DEDUCED_TYPENAME
String::traits_type
> &
596 ( std::basic_istream
< BOOST_DEDUCED_TYPENAME
String::value_type
,
597 BOOST_DEDUCED_TYPENAME
String::traits_type
> & is
,
598 basic_path
< String
, Traits
> & ph
)
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.
615 // BOOST_FILESYSTEM_DECL version works for VC++ but not GCC. Go figure!
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() )
628 target
+= path1_arg
.file_string();
631 if ( !path2_arg
.empty() )
634 target
+= path2_arg
.file_string();
638 return target
.c_str();
647 const char * what( const char * sys_err_what
,
648 const Path
& /*path1_arg*/, const Path
& /*path2_arg*/, std::string
& /*target*/ )
654 // basic_filesystem_error ----------------------------------------------//
657 class basic_filesystem_error
: public system::system_error
659 // see http://www.boost.org/more/error_handling.html for design rationale
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
);
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
;
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
& )
722 // implementation -----------------------------------------------------------//
727 // is_separator helper ------------------------------------------------//
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
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)
748 boost::BOOST_FILESYSTEM_NAMESPACE::basic_path
<String
, Traits
> path_type
;
752 && str
[0] == slash
<path_type
>::value
753 && str
[1] == slash
<path_type
>::value
) return 0;
756 if ( end_pos
&& str
[end_pos
-1] == slash
<path_type
>::value
)
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 );
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
>
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
787 typename
String::size_type size
= -1
791 if ( size
== String::npos
) size
= src
.size();
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
804 || src
[2] != slash
<path_type
>::value
) )
810 // leading (not non-network) separator
811 else if ( src
[0] == slash
<path_type
>::value
)
814 // bypass extra leading separators
816 && src
[cur
+1] == slash
<path_type
>::value
)
824 // at this point, we have either a plain name, a network name,
825 // or (on Windows only) a device name
829 # ifdef BOOST_WINDOWS_PATH
830 && src
[cur
] != colon
<path_type
>::value
832 && src
[cur
] != slash
<path_type
>::value
)
838 # ifdef BOOST_WINDOWS_PATH
839 if ( cur
== size
) return;
840 // include device delimiter
841 if ( src
[cur
] == colon
<path_type
>::value
)
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
861 && s
[1] == colon
<path_type
>::value
862 && s
[2] == slash
<path_type
>::value
) return 2;
867 && s
[0] == slash
<path_type
>::value
868 && s
[1] == slash
<path_type
>::value
) return String::npos
;
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
;
882 if ( size
> 0 && s
[0] == slash
<path_type
>::value
) return 0;
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
894 boost::BOOST_FILESYSTEM_NAMESPACE::basic_path
<String
, Traits
>
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
)
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
)
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()
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
);
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
) );
962 && (end_pos
-1) != root_dir_pos
963 && m_path
[end_pos
-1] == slash
<path_type
>::value
967 return (end_pos
== 1 && root_dir_pos
== 0 && filename_was_separator
)
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
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()
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
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
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();
1033 return has_root_directory();
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()
1062 # ifdef BOOST_WINDOWS_PATH
1063 *(m_path
.end()-1) != colon
<path_type
>::value
&&
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
);
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
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
);
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;
1137 // erase escape sequence if any
1138 if ( was_escape_sequence
&& append_count
>= 3 )
1139 m_path
.erase( initial_pos
, 3 );
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;
1159 for ( iterator
itr( begin() ); itr
!= end(); ++itr
)
1164 if ( temp
.empty() ) temp
/= dot_str
;
1165 m_path
= temp
.m_path
;
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;
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
1189 && itr
!= last
) continue;
1191 // ignore a name and following ".."
1194 && (*itr
)[0] == dot
<path_type
>::value
1195 && (*itr
)[1] == dot
<path_type
>::value
) // dot dot
1197 string_type
lf( temp
.filename() );
1200 || (lf
[0] != dot
<path_type
>::value
1201 && lf
[0] != slash
<path_type
>::value
))
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
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
;
1236 if ( temp
.empty() ) temp
/= dot_str
;
1237 m_path
= temp
.m_path
;
1243 // modifiers ------------------------------------------------------------//
1245 template<class String
, class Traits
>
1246 basic_path
<String
, Traits
> & basic_path
<String
, Traits
>::remove_filename()
1249 detail::filename_pos
<String
, Traits
>( m_path
, m_path
.size() ) );
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
;
1271 // path conversion functions --------------------------------------------//
1273 template<class String
, class Traits
>
1275 basic_path
<String
, Traits
>::file_string() const
1277 # ifdef BOOST_WINDOWS_PATH
1278 // for Windows, use the alternate separator, and bypass extra
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
);
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] )
1297 s
+= path_alt_separator
<path_type
>::value
;
1298 s
+= path_alt_separator
<path_type
>::value
;
1302 // bypass extra root separators
1306 && s
[s
.size()-1] == path_alt_separator
<path_type
>::value
1307 && m_path
[pos
] == slash
<path_type
>::value
1311 if ( m_path
[pos
] == slash
<path_type
>::value
)
1312 s
+= path_alt_separator
<path_type
>::value
;
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
;
1329 // iterator functions ---------------------------------------------------//
1331 template<class String
, class Traits
>
1332 typename basic_path
<String
, Traits
>::iterator basic_path
<String
, Traits
>::begin() const
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
);
1342 template<class String
, class Traits
>
1343 typename basic_path
<String
, Traits
>::iterator basic_path
<String
, Traits
>::end() const
1346 itr
.m_path_ptr
= this;
1347 itr
.m_pos
= m_path
.size();
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()
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
1383 # ifdef BOOST_WINDOWS_PATH
1385 || itr
.m_name
[itr
.m_name
.size()-1] == colon
<Path
>::value
1389 itr
.m_name
= slash
<Path
>::value
;
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
)
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 ) )
1404 itr
.m_name
= dot
<Path
>::value
;
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 )
1440 itr
.m_name
= dot
<Path
>::value
;
1444 // skip separators unless root directory
1448 && (end_pos
-1) != root_dir_pos
1449 && itr
.m_path_ptr
->m_path
[end_pos
-1] == slash
<Path
>::value
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