path.hpp 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758
  1. // filesystem path.hpp ---------------------------------------------------------------//
  2. // Copyright Beman Dawes 2002-2005, 2009
  3. // Copyright Vladimir Prus 2002
  4. // Distributed under the Boost Software License, Version 1.0.
  5. // See http://www.boost.org/LICENSE_1_0.txt
  6. // Library home page: http://www.boost.org/libs/filesystem
  7. // path::stem(), extension(), and replace_extension() are based on
  8. // basename(), extension(), and change_extension() from the original
  9. // filesystem/convenience.hpp header by Vladimir Prus.
  10. #ifndef BOOST_FILESYSTEM_PATH_HPP
  11. #define BOOST_FILESYSTEM_PATH_HPP
  12. #include <boost/config.hpp>
  13. # if defined( BOOST_NO_STD_WSTRING )
  14. # error Configuration not supported: Boost.Filesystem V3 and later requires std::wstring support
  15. # endif
  16. #include <boost/filesystem/config.hpp>
  17. #include <boost/filesystem/path_traits.hpp> // includes <cwchar>
  18. #include <boost/system/error_code.hpp>
  19. #include <boost/system/system_error.hpp>
  20. #include <boost/iterator/iterator_facade.hpp>
  21. #include <boost/shared_ptr.hpp>
  22. #include <boost/io/detail/quoted_manip.hpp>
  23. #include <boost/static_assert.hpp>
  24. #include <boost/functional/hash_fwd.hpp>
  25. #include <boost/type_traits/is_integral.hpp>
  26. #include <string>
  27. #include <iterator>
  28. #include <cstring>
  29. #include <iosfwd>
  30. #include <stdexcept>
  31. #include <cassert>
  32. #include <locale>
  33. #include <algorithm>
  34. #include <boost/config/abi_prefix.hpp> // must be the last #include
  35. namespace boost
  36. {
  37. namespace filesystem
  38. {
  39. //------------------------------------------------------------------------------------//
  40. // //
  41. // class path //
  42. // //
  43. //------------------------------------------------------------------------------------//
  44. class BOOST_FILESYSTEM_DECL path
  45. {
  46. public:
  47. // value_type is the character type used by the operating system API to
  48. // represent paths.
  49. # ifdef BOOST_WINDOWS_API
  50. typedef wchar_t value_type;
  51. BOOST_STATIC_CONSTEXPR value_type preferred_separator = L'\\';
  52. # else
  53. typedef char value_type;
  54. BOOST_STATIC_CONSTEXPR value_type preferred_separator = '/';
  55. # endif
  56. typedef std::basic_string<value_type> string_type;
  57. typedef std::codecvt<wchar_t, char,
  58. std::mbstate_t> codecvt_type;
  59. // ----- character encoding conversions -----
  60. // Following the principle of least astonishment, path input arguments
  61. // passed to or obtained from the operating system via objects of
  62. // class path behave as if they were directly passed to or
  63. // obtained from the O/S API, unless conversion is explicitly requested.
  64. //
  65. // POSIX specfies that path strings are passed unchanged to and from the
  66. // API. Note that this is different from the POSIX command line utilities,
  67. // which convert according to a locale.
  68. //
  69. // Thus for POSIX, char strings do not undergo conversion. wchar_t strings
  70. // are converted to/from char using the path locale or, if a conversion
  71. // argument is given, using a conversion object modeled on
  72. // std::wstring_convert.
  73. //
  74. // The path locale, which is global to the thread, can be changed by the
  75. // imbue() function. It is initialized to an implementation defined locale.
  76. //
  77. // For Windows, wchar_t strings do not undergo conversion. char strings
  78. // are converted using the "ANSI" or "OEM" code pages, as determined by
  79. // the AreFileApisANSI() function, or, if a conversion argument is given,
  80. // using a conversion object modeled on std::wstring_convert.
  81. //
  82. // See m_pathname comments for further important rationale.
  83. // TODO: rules needed for operating systems that use / or .
  84. // differently, or format directory paths differently from file paths.
  85. //
  86. // **********************************************************************************
  87. //
  88. // More work needed: How to handle an operating system that may have
  89. // slash characters or dot characters in valid filenames, either because
  90. // it doesn't follow the POSIX standard, or because it allows MBCS
  91. // filename encodings that may contain slash or dot characters. For
  92. // example, ISO/IEC 2022 (JIS) encoding which allows switching to
  93. // JIS x0208-1983 encoding. A valid filename in this set of encodings is
  94. // 0x1B 0x24 0x42 [switch to X0208-1983] 0x24 0x2F [U+304F Kiragana letter KU]
  95. // ^^^^
  96. // Note that 0x2F is the ASCII slash character
  97. //
  98. // **********************************************************************************
  99. // Supported source arguments: half-open iterator range, container, c-array,
  100. // and single pointer to null terminated string.
  101. // All source arguments except pointers to null terminated byte strings support
  102. // multi-byte character strings which may have embedded nulls. Embedded null
  103. // support is required for some Asian languages on Windows.
  104. // [defaults] "const codecvt_type& cvt=codecvt()" default arguments are not used
  105. // because some compilers, such as Microsoft prior to VC++ 10, do not handle defaults
  106. // correctly in templates.
  107. // ----- constructors -----
  108. path(){}
  109. path(const path& p) : m_pathname(p.m_pathname) {}
  110. template <class Source>
  111. path(Source const& source,
  112. typename boost::enable_if<path_traits::is_pathable<
  113. typename boost::decay<Source>::type> >::type* =0)
  114. {
  115. path_traits::dispatch(source, m_pathname, codecvt());
  116. }
  117. // Overloads for the operating system API's native character type. Rationale:
  118. // - Avoids use of codecvt() for native value_type strings. This limits the
  119. // impact of locale("") initialization failures on POSIX systems to programs
  120. // that actually depend on locale(""). It further ensures that exceptions thrown
  121. // as a result of such failues occur after main() has started, so can be caught.
  122. // This is a partial resolution of tickets 4688, 5100, and 5289.
  123. // - A slight optimization for a common use case, particularly on POSIX since
  124. // value_type is char and that is the most common useage.
  125. path(const value_type* s) : m_pathname(s) {}
  126. path(const std::basic_string<value_type>& s) : m_pathname(s) {}
  127. template <class Source>
  128. path(Source const& source, const codecvt_type& cvt)
  129. // see [defaults] note above explaining why codecvt() default arguments are not used
  130. {
  131. path_traits::dispatch(source, m_pathname, cvt);
  132. }
  133. template <class InputIterator>
  134. path(InputIterator begin, InputIterator end)
  135. {
  136. if (begin != end)
  137. {
  138. std::basic_string<typename std::iterator_traits<InputIterator>::value_type>
  139. s(begin, end);
  140. path_traits::convert(s.c_str(), s.c_str()+s.size(), m_pathname, codecvt());
  141. }
  142. }
  143. template <class InputIterator>
  144. path(InputIterator begin, InputIterator end, const codecvt_type& cvt)
  145. {
  146. if (begin != end)
  147. {
  148. std::basic_string<typename std::iterator_traits<InputIterator>::value_type>
  149. s(begin, end);
  150. path_traits::convert(s.c_str(), s.c_str()+s.size(), m_pathname, cvt);
  151. }
  152. }
  153. // ----- assignments -----
  154. path& operator=(const path& p)
  155. {
  156. m_pathname = p.m_pathname;
  157. return *this;
  158. }
  159. path& operator=(const value_type* ptr) // required in case ptr overlaps *this
  160. {
  161. m_pathname = ptr;
  162. return *this;
  163. }
  164. template <class Source>
  165. typename boost::enable_if<path_traits::is_pathable<
  166. typename boost::decay<Source>::type>, path&>::type
  167. operator=(Source const& source)
  168. {
  169. m_pathname.clear();
  170. path_traits::dispatch(source, m_pathname, codecvt());
  171. return *this;
  172. }
  173. path& assign(const value_type* ptr, const codecvt_type&) // required in case ptr overlaps *this
  174. {
  175. m_pathname = ptr;
  176. return *this;
  177. }
  178. template <class Source>
  179. path& assign(Source const& source, const codecvt_type& cvt)
  180. {
  181. m_pathname.clear();
  182. path_traits::dispatch(source, m_pathname, cvt);
  183. return *this;
  184. }
  185. template <class InputIterator>
  186. path& assign(InputIterator begin, InputIterator end)
  187. {
  188. return assign(begin, end, codecvt());
  189. }
  190. template <class InputIterator>
  191. path& assign(InputIterator begin, InputIterator end, const codecvt_type& cvt)
  192. {
  193. m_pathname.clear();
  194. if (begin != end)
  195. {
  196. std::basic_string<typename std::iterator_traits<InputIterator>::value_type>
  197. s(begin, end);
  198. path_traits::convert(s.c_str(), s.c_str()+s.size(), m_pathname, cvt);
  199. }
  200. return *this;
  201. }
  202. // ----- concatenation -----
  203. path& operator+=(const path& p) {m_pathname += p.m_pathname; return *this;}
  204. path& operator+=(const string_type& s) {m_pathname += s; return *this;}
  205. path& operator+=(const value_type* ptr) {m_pathname += ptr; return *this;}
  206. path& operator+=(value_type c) {m_pathname += c; return *this;}
  207. template <class Source>
  208. typename boost::enable_if<path_traits::is_pathable<
  209. typename boost::decay<Source>::type>, path&>::type
  210. operator+=(Source const& source)
  211. {
  212. return concat(source, codecvt());
  213. }
  214. template <class CharT>
  215. typename boost::enable_if<is_integral<CharT>, path&>::type
  216. operator+=(CharT c)
  217. {
  218. CharT tmp[2];
  219. tmp[0] = c;
  220. tmp[1] = 0;
  221. return concat(tmp, codecvt());
  222. }
  223. template <class Source>
  224. path& concat(Source const& source, const codecvt_type& cvt)
  225. {
  226. path_traits::dispatch(source, m_pathname, cvt);
  227. return *this;
  228. }
  229. template <class InputIterator>
  230. path& concat(InputIterator begin, InputIterator end)
  231. {
  232. return concat(begin, end, codecvt());
  233. }
  234. template <class InputIterator>
  235. path& concat(InputIterator begin, InputIterator end, const codecvt_type& cvt)
  236. {
  237. if (begin == end)
  238. return *this;
  239. std::basic_string<typename std::iterator_traits<InputIterator>::value_type>
  240. s(begin, end);
  241. path_traits::convert(s.c_str(), s.c_str()+s.size(), m_pathname, cvt);
  242. return *this;
  243. }
  244. // ----- appends -----
  245. // if a separator is added, it is the preferred separator for the platform;
  246. // slash for POSIX, backslash for Windows
  247. path& operator/=(const path& p);
  248. path& operator/=(const value_type* ptr);
  249. template <class Source>
  250. typename boost::enable_if<path_traits::is_pathable<
  251. typename boost::decay<Source>::type>, path&>::type
  252. operator/=(Source const& source)
  253. {
  254. return append(source, codecvt());
  255. }
  256. path& append(const value_type* ptr, const codecvt_type&) // required in case ptr overlaps *this
  257. {
  258. this->operator/=(ptr);
  259. return *this;
  260. }
  261. template <class Source>
  262. path& append(Source const& source, const codecvt_type& cvt);
  263. template <class InputIterator>
  264. path& append(InputIterator begin, InputIterator end)
  265. {
  266. return append(begin, end, codecvt());
  267. }
  268. template <class InputIterator>
  269. path& append(InputIterator begin, InputIterator end, const codecvt_type& cvt);
  270. // ----- modifiers -----
  271. void clear() { m_pathname.clear(); }
  272. path& make_preferred()
  273. # ifdef BOOST_POSIX_API
  274. { return *this; } // POSIX no effect
  275. # else // BOOST_WINDOWS_API
  276. ; // change slashes to backslashes
  277. # endif
  278. path& remove_filename();
  279. path& replace_extension(const path& new_extension = path());
  280. void swap(path& rhs) { m_pathname.swap(rhs.m_pathname); }
  281. // ----- observers -----
  282. // For operating systems that format file paths differently than directory
  283. // paths, return values from observers are formatted as file names unless there
  284. // is a trailing separator, in which case returns are formatted as directory
  285. // paths. POSIX and Windows make no such distinction.
  286. // Implementations are permitted to return const values or const references.
  287. // The string or path returned by an observer are specified as being formatted
  288. // as "native" or "generic".
  289. //
  290. // For POSIX, these are all the same format; slashes and backslashes are as input and
  291. // are not modified.
  292. //
  293. // For Windows, native: as input; slashes and backslashes are not modified;
  294. // this is the format of the internally stored string.
  295. // generic: backslashes are converted to slashes
  296. // ----- native format observers -----
  297. const string_type& native() const { return m_pathname; } // Throws: nothing
  298. const value_type* c_str() const { return m_pathname.c_str(); } // Throws: nothing
  299. template <class String>
  300. String string() const;
  301. template <class String>
  302. String string(const codecvt_type& cvt) const;
  303. # ifdef BOOST_WINDOWS_API
  304. const std::string string() const { return string(codecvt()); }
  305. const std::string string(const codecvt_type& cvt) const
  306. {
  307. std::string tmp;
  308. if (!m_pathname.empty())
  309. path_traits::convert(&*m_pathname.begin(), &*m_pathname.begin()+m_pathname.size(),
  310. tmp, cvt);
  311. return tmp;
  312. }
  313. // string_type is std::wstring, so there is no conversion
  314. const std::wstring& wstring() const { return m_pathname; }
  315. const std::wstring& wstring(const codecvt_type&) const { return m_pathname; }
  316. # else // BOOST_POSIX_API
  317. // string_type is std::string, so there is no conversion
  318. const std::string& string() const { return m_pathname; }
  319. const std::string& string(const codecvt_type&) const { return m_pathname; }
  320. const std::wstring wstring() const { return wstring(codecvt()); }
  321. const std::wstring wstring(const codecvt_type& cvt) const
  322. {
  323. std::wstring tmp;
  324. if (!m_pathname.empty())
  325. path_traits::convert(&*m_pathname.begin(), &*m_pathname.begin()+m_pathname.size(),
  326. tmp, cvt);
  327. return tmp;
  328. }
  329. # endif
  330. // ----- generic format observers -----
  331. template <class String>
  332. String generic_string() const;
  333. template <class String>
  334. String generic_string(const codecvt_type& cvt) const;
  335. # ifdef BOOST_WINDOWS_API
  336. const std::string generic_string() const { return generic_string(codecvt()); }
  337. const std::string generic_string(const codecvt_type& cvt) const;
  338. const std::wstring generic_wstring() const;
  339. const std::wstring generic_wstring(const codecvt_type&) const { return generic_wstring(); };
  340. # else // BOOST_POSIX_API
  341. // On POSIX-like systems, the generic format is the same as the native format
  342. const std::string& generic_string() const { return m_pathname; }
  343. const std::string& generic_string(const codecvt_type&) const { return m_pathname; }
  344. const std::wstring generic_wstring() const { return wstring(codecvt()); }
  345. const std::wstring generic_wstring(const codecvt_type& cvt) const { return wstring(cvt); }
  346. # endif
  347. // ----- compare -----
  348. int compare(const path& p) const BOOST_NOEXCEPT; // generic, lexicographical
  349. int compare(const std::string& s) const { return compare(path(s)); }
  350. int compare(const value_type* s) const { return compare(path(s)); }
  351. // ----- decomposition -----
  352. path root_path() const;
  353. path root_name() const; // returns 0 or 1 element path
  354. // even on POSIX, root_name() is non-empty() for network paths
  355. path root_directory() const; // returns 0 or 1 element path
  356. path relative_path() const;
  357. path parent_path() const;
  358. path filename() const; // returns 0 or 1 element path
  359. path stem() const; // returns 0 or 1 element path
  360. path extension() const; // returns 0 or 1 element path
  361. // ----- query -----
  362. bool empty() const { return m_pathname.empty(); } // name consistent with std containers
  363. bool has_root_path() const { return has_root_directory() || has_root_name(); }
  364. bool has_root_name() const { return !root_name().empty(); }
  365. bool has_root_directory() const { return !root_directory().empty(); }
  366. bool has_relative_path() const { return !relative_path().empty(); }
  367. bool has_parent_path() const { return !parent_path().empty(); }
  368. bool has_filename() const { return !m_pathname.empty(); }
  369. bool has_stem() const { return !stem().empty(); }
  370. bool has_extension() const { return !extension().empty(); }
  371. bool is_absolute() const
  372. {
  373. # ifdef BOOST_WINDOWS_API
  374. return has_root_name() && has_root_directory();
  375. # else
  376. return has_root_directory();
  377. # endif
  378. }
  379. bool is_relative() const { return !is_absolute(); }
  380. // ----- iterators -----
  381. class iterator;
  382. typedef iterator const_iterator;
  383. iterator begin() const;
  384. iterator end() const;
  385. // ----- static member functions -----
  386. static std::locale imbue(const std::locale& loc);
  387. static const codecvt_type& codecvt();
  388. // ----- deprecated functions -----
  389. # if defined(BOOST_FILESYSTEM_DEPRECATED) && defined(BOOST_FILESYSTEM_NO_DEPRECATED)
  390. # error both BOOST_FILESYSTEM_DEPRECATED and BOOST_FILESYSTEM_NO_DEPRECATED are defined
  391. # endif
  392. # if !defined(BOOST_FILESYSTEM_NO_DEPRECATED)
  393. // recently deprecated functions supplied by default
  394. path& normalize() { return m_normalize(); }
  395. path& remove_leaf() { return remove_filename(); }
  396. path leaf() const { return filename(); }
  397. path branch_path() const { return parent_path(); }
  398. bool has_leaf() const { return !m_pathname.empty(); }
  399. bool has_branch_path() const { return !parent_path().empty(); }
  400. bool is_complete() const { return is_absolute(); }
  401. # endif
  402. # if defined(BOOST_FILESYSTEM_DEPRECATED)
  403. // deprecated functions with enough signature or semantic changes that they are
  404. // not supplied by default
  405. const std::string file_string() const { return string(); }
  406. const std::string directory_string() const { return string(); }
  407. const std::string native_file_string() const { return string(); }
  408. const std::string native_directory_string() const { return string(); }
  409. const string_type external_file_string() const { return native(); }
  410. const string_type external_directory_string() const { return native(); }
  411. // older functions no longer supported
  412. //typedef bool (*name_check)(const std::string & name);
  413. //basic_path(const string_type& str, name_check) { operator/=(str); }
  414. //basic_path(const typename string_type::value_type* s, name_check)
  415. // { operator/=(s);}
  416. //static bool default_name_check_writable() { return false; }
  417. //static void default_name_check(name_check) {}
  418. //static name_check default_name_check() { return 0; }
  419. //basic_path& canonize();
  420. # endif
  421. //--------------------------------------------------------------------------------------//
  422. // class path private members //
  423. //--------------------------------------------------------------------------------------//
  424. private:
  425. # if defined(_MSC_VER)
  426. # pragma warning(push) // Save warning settings
  427. # pragma warning(disable : 4251) // disable warning: class 'std::basic_string<_Elem,_Traits,_Ax>'
  428. # endif // needs to have dll-interface...
  429. /*
  430. m_pathname has the type, encoding, and format required by the native
  431. operating system. Thus for POSIX and Windows there is no conversion for
  432. passing m_pathname.c_str() to the O/S API or when obtaining a path from the
  433. O/S API. POSIX encoding is unspecified other than for dot and slash
  434. characters; POSIX just treats paths as a sequence of bytes. Windows
  435. encoding is UCS-2 or UTF-16 depending on the version.
  436. */
  437. string_type m_pathname; // Windows: as input; backslashes NOT converted to slashes,
  438. // slashes NOT converted to backslashes
  439. # if defined(_MSC_VER)
  440. # pragma warning(pop) // restore warning settings.
  441. # endif
  442. string_type::size_type m_append_separator_if_needed();
  443. // Returns: If separator is to be appended, m_pathname.size() before append. Otherwise 0.
  444. // Note: An append is never performed if size()==0, so a returned 0 is unambiguous.
  445. void m_erase_redundant_separator(string_type::size_type sep_pos);
  446. string_type::size_type m_parent_path_end() const;
  447. path& m_normalize();
  448. // Was qualified; como433beta8 reports:
  449. // warning #427-D: qualified name is not allowed in member declaration
  450. friend class iterator;
  451. friend bool operator<(const path& lhs, const path& rhs);
  452. // see path::iterator::increment/decrement comment below
  453. static void m_path_iterator_increment(path::iterator & it);
  454. static void m_path_iterator_decrement(path::iterator & it);
  455. }; // class path
  456. namespace detail
  457. {
  458. BOOST_FILESYSTEM_DECL
  459. int lex_compare(path::iterator first1, path::iterator last1,
  460. path::iterator first2, path::iterator last2);
  461. }
  462. # ifndef BOOST_FILESYSTEM_NO_DEPRECATED
  463. typedef path wpath;
  464. # endif
  465. //------------------------------------------------------------------------------------//
  466. // class path::iterator //
  467. //------------------------------------------------------------------------------------//
  468. class path::iterator
  469. : public boost::iterator_facade<
  470. path::iterator,
  471. path const,
  472. boost::bidirectional_traversal_tag >
  473. {
  474. private:
  475. friend class boost::iterator_core_access;
  476. friend class boost::filesystem::path;
  477. friend void m_path_iterator_increment(path::iterator & it);
  478. friend void m_path_iterator_decrement(path::iterator & it);
  479. const path& dereference() const { return m_element; }
  480. bool equal(const iterator & rhs) const
  481. {
  482. return m_path_ptr == rhs.m_path_ptr && m_pos == rhs.m_pos;
  483. }
  484. // iterator_facade derived classes don't seem to like implementations in
  485. // separate translation unit dll's, so forward to class path static members
  486. void increment() { m_path_iterator_increment(*this); }
  487. void decrement() { m_path_iterator_decrement(*this); }
  488. path m_element; // current element
  489. const path* m_path_ptr; // path being iterated over
  490. string_type::size_type m_pos; // position of m_element in
  491. // m_path_ptr->m_pathname.
  492. // if m_element is implicit dot, m_pos is the
  493. // position of the last separator in the path.
  494. // end() iterator is indicated by
  495. // m_pos == m_path_ptr->m_pathname.size()
  496. }; // path::iterator
  497. //------------------------------------------------------------------------------------//
  498. // //
  499. // non-member functions //
  500. // //
  501. //------------------------------------------------------------------------------------//
  502. // std::lexicographical_compare would infinately recurse because path iterators
  503. // yield paths, so provide a path aware version
  504. inline bool lexicographical_compare(path::iterator first1, path::iterator last1,
  505. path::iterator first2, path::iterator last2)
  506. { return detail::lex_compare(first1, last1, first2, last2) < 0; }
  507. inline bool operator==(const path& lhs, const path& rhs) {return lhs.compare(rhs) == 0;}
  508. inline bool operator==(const path& lhs, const path::string_type& rhs) {return lhs.compare(rhs) == 0;}
  509. inline bool operator==(const path::string_type& lhs, const path& rhs) {return rhs.compare(lhs) == 0;}
  510. inline bool operator==(const path& lhs, const path::value_type* rhs) {return lhs.compare(rhs) == 0;}
  511. inline bool operator==(const path::value_type* lhs, const path& rhs) {return rhs.compare(lhs) == 0;}
  512. inline bool operator!=(const path& lhs, const path& rhs) {return lhs.compare(rhs) != 0;}
  513. inline bool operator!=(const path& lhs, const path::string_type& rhs) {return lhs.compare(rhs) != 0;}
  514. inline bool operator!=(const path::string_type& lhs, const path& rhs) {return rhs.compare(lhs) != 0;}
  515. inline bool operator!=(const path& lhs, const path::value_type* rhs) {return lhs.compare(rhs) != 0;}
  516. inline bool operator!=(const path::value_type* lhs, const path& rhs) {return rhs.compare(lhs) != 0;}
  517. // TODO: why do == and != have additional overloads, but the others don't?
  518. inline bool operator<(const path& lhs, const path& rhs) {return lhs.compare(rhs) < 0;}
  519. inline bool operator<=(const path& lhs, const path& rhs) {return !(rhs < lhs);}
  520. inline bool operator> (const path& lhs, const path& rhs) {return rhs < lhs;}
  521. inline bool operator>=(const path& lhs, const path& rhs) {return !(lhs < rhs);}
  522. inline std::size_t hash_value(const path& x)
  523. {
  524. # ifdef BOOST_WINDOWS_API
  525. std::size_t seed = 0;
  526. for(const path::value_type* it = x.c_str(); *it; ++it)
  527. hash_combine(seed, *it == '/' ? L'\\' : *it);
  528. return seed;
  529. # else // BOOST_POSIX_API
  530. return hash_range(x.native().begin(), x.native().end());
  531. # endif
  532. }
  533. inline void swap(path& lhs, path& rhs) { lhs.swap(rhs); }
  534. inline path operator/(const path& lhs, const path& rhs) { return path(lhs) /= rhs; }
  535. // inserters and extractors
  536. // use boost::io::quoted() to handle spaces in paths
  537. // use '&' as escape character to ease use for Windows paths
  538. template <class Char, class Traits>
  539. inline std::basic_ostream<Char, Traits>&
  540. operator<<(std::basic_ostream<Char, Traits>& os, const path& p)
  541. {
  542. return os
  543. << boost::io::quoted(p.template string<std::basic_string<Char> >(), static_cast<Char>('&'));
  544. }
  545. template <class Char, class Traits>
  546. inline std::basic_istream<Char, Traits>&
  547. operator>>(std::basic_istream<Char, Traits>& is, path& p)
  548. {
  549. std::basic_string<Char> str;
  550. is >> boost::io::quoted(str, static_cast<Char>('&'));
  551. p = str;
  552. return is;
  553. }
  554. // name_checks
  555. // These functions are holdovers from version 1. It isn't clear they have much
  556. // usefulness, or how to generalize them for later versions.
  557. BOOST_FILESYSTEM_DECL bool portable_posix_name(const std::string & name);
  558. BOOST_FILESYSTEM_DECL bool windows_name(const std::string & name);
  559. BOOST_FILESYSTEM_DECL bool portable_name(const std::string & name);
  560. BOOST_FILESYSTEM_DECL bool portable_directory_name(const std::string & name);
  561. BOOST_FILESYSTEM_DECL bool portable_file_name(const std::string & name);
  562. BOOST_FILESYSTEM_DECL bool native(const std::string & name);
  563. //--------------------------------------------------------------------------------------//
  564. // class path member template implementation //
  565. //--------------------------------------------------------------------------------------//
  566. template <class InputIterator>
  567. path& path::append(InputIterator begin, InputIterator end, const codecvt_type& cvt)
  568. {
  569. if (begin == end)
  570. return *this;
  571. string_type::size_type sep_pos(m_append_separator_if_needed());
  572. std::basic_string<typename std::iterator_traits<InputIterator>::value_type>
  573. s(begin, end);
  574. path_traits::convert(s.c_str(), s.c_str()+s.size(), m_pathname, cvt);
  575. if (sep_pos)
  576. m_erase_redundant_separator(sep_pos);
  577. return *this;
  578. }
  579. template <class Source>
  580. path& path::append(Source const& source, const codecvt_type& cvt)
  581. {
  582. if (path_traits::empty(source))
  583. return *this;
  584. string_type::size_type sep_pos(m_append_separator_if_needed());
  585. path_traits::dispatch(source, m_pathname, cvt);
  586. if (sep_pos)
  587. m_erase_redundant_separator(sep_pos);
  588. return *this;
  589. }
  590. //--------------------------------------------------------------------------------------//
  591. // class path member template specializations //
  592. //--------------------------------------------------------------------------------------//
  593. template <> inline
  594. std::string path::string<std::string>() const
  595. { return string(); }
  596. template <> inline
  597. std::wstring path::string<std::wstring>() const
  598. { return wstring(); }
  599. template <> inline
  600. std::string path::string<std::string>(const codecvt_type& cvt) const
  601. { return string(cvt); }
  602. template <> inline
  603. std::wstring path::string<std::wstring>(const codecvt_type& cvt) const
  604. { return wstring(cvt); }
  605. template <> inline
  606. std::string path::generic_string<std::string>() const
  607. { return generic_string(); }
  608. template <> inline
  609. std::wstring path::generic_string<std::wstring>() const
  610. { return generic_wstring(); }
  611. template <> inline
  612. std::string path::generic_string<std::string>(const codecvt_type& cvt) const
  613. { return generic_string(cvt); }
  614. template <> inline
  615. std::wstring path::generic_string<std::wstring>(const codecvt_type& cvt) const
  616. { return generic_wstring(cvt); }
  617. } // namespace filesystem
  618. } // namespace boost
  619. //----------------------------------------------------------------------------//
  620. #include <boost/config/abi_suffix.hpp> // pops abi_prefix.hpp pragmas
  621. #endif // BOOST_FILESYSTEM_PATH_HPP