fs_path.h 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353
  1. // Class filesystem::path -*- C++ -*-
  2. // Copyright (C) 2014-2021 Free Software Foundation, Inc.
  3. //
  4. // This file is part of the GNU ISO C++ Library. This library is free
  5. // software; you can redistribute it and/or modify it under the
  6. // terms of the GNU General Public License as published by the
  7. // Free Software Foundation; either version 3, or (at your option)
  8. // any later version.
  9. // This library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. // Under Section 7 of GPL version 3, you are granted additional
  14. // permissions described in the GCC Runtime Library Exception, version
  15. // 3.1, as published by the Free Software Foundation.
  16. // You should have received a copy of the GNU General Public License and
  17. // a copy of the GCC Runtime Library Exception along with this program;
  18. // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
  19. // <http://www.gnu.org/licenses/>.
  20. /** @file include/bits/fs_path.h
  21. * This is an internal header file, included by other library headers.
  22. * Do not attempt to use it directly. @headername{filesystem}
  23. */
  24. #ifndef _GLIBCXX_FS_PATH_H
  25. #define _GLIBCXX_FS_PATH_H 1
  26. #if __cplusplus >= 201703L
  27. #include <utility>
  28. #include <type_traits>
  29. #include <locale>
  30. #include <iosfwd>
  31. #include <iomanip>
  32. #include <codecvt>
  33. #include <string_view>
  34. #include <system_error>
  35. #include <bits/stl_algobase.h>
  36. #include <bits/locale_conv.h>
  37. #include <ext/concurrence.h>
  38. #include <bits/shared_ptr.h>
  39. #include <bits/unique_ptr.h>
  40. #if __cplusplus > 201703L
  41. # include <compare>
  42. #endif
  43. #if defined(_WIN32) && !defined(__CYGWIN__)
  44. # define _GLIBCXX_FILESYSTEM_IS_WINDOWS 1
  45. # include <algorithm>
  46. #endif
  47. namespace std _GLIBCXX_VISIBILITY(default)
  48. {
  49. _GLIBCXX_BEGIN_NAMESPACE_VERSION
  50. namespace filesystem
  51. {
  52. _GLIBCXX_BEGIN_NAMESPACE_CXX11
  53. /** @addtogroup filesystem
  54. * @{
  55. */
  56. class path;
  57. /// @cond undocumented
  58. namespace __detail
  59. {
  60. template<typename _CharT>
  61. inline constexpr bool __is_encoded_char = false;
  62. template<>
  63. inline constexpr bool __is_encoded_char<char> = true;
  64. #ifdef _GLIBCXX_USE_CHAR8_T
  65. template<>
  66. inline constexpr bool __is_encoded_char<char8_t> = true;
  67. #endif
  68. #if _GLIBCXX_USE_WCHAR_T
  69. template<>
  70. inline constexpr bool __is_encoded_char<wchar_t> = true;
  71. #endif
  72. template<>
  73. inline constexpr bool __is_encoded_char<char16_t> = true;
  74. template<>
  75. inline constexpr bool __is_encoded_char<char32_t> = true;
  76. #if __cpp_concepts >= 201907L
  77. template<typename _Iter>
  78. using __safe_iterator_traits = std::iterator_traits<_Iter>;
  79. #else
  80. template<typename _Iter>
  81. struct __safe_iterator_traits : std::iterator_traits<_Iter>
  82. { };
  83. // Protect against ill-formed iterator_traits specializations in C++17
  84. template<> struct __safe_iterator_traits<void*> { };
  85. template<> struct __safe_iterator_traits<const void*> { };
  86. template<> struct __safe_iterator_traits<volatile void*> { };
  87. template<> struct __safe_iterator_traits<const volatile void*> { };
  88. #endif
  89. template<typename _Iter_traits, typename = void>
  90. struct __is_path_iter_src
  91. : false_type
  92. { };
  93. template<typename _Iter_traits>
  94. struct __is_path_iter_src<_Iter_traits,
  95. void_t<typename _Iter_traits::value_type>>
  96. : bool_constant<__is_encoded_char<typename _Iter_traits::value_type>>
  97. { };
  98. template<typename _Source>
  99. inline constexpr bool __is_path_src
  100. = __is_path_iter_src<iterator_traits<decay_t<_Source>>>::value;
  101. template<>
  102. inline constexpr bool __is_path_src<path> = false;
  103. template<>
  104. inline constexpr bool __is_path_src<volatile path> = false;
  105. template<>
  106. inline constexpr bool __is_path_src<void*> = false;
  107. template<>
  108. inline constexpr bool __is_path_src<const void*> = false;
  109. template<>
  110. inline constexpr bool __is_path_src<volatile void*> = false;
  111. template<>
  112. inline constexpr bool __is_path_src<const volatile void*> = false;
  113. template<typename _CharT, typename _Traits, typename _Alloc>
  114. inline constexpr bool
  115. __is_path_src<basic_string<_CharT, _Traits, _Alloc>>
  116. = __is_encoded_char<_CharT>;
  117. template<typename _CharT, typename _Traits>
  118. inline constexpr bool
  119. __is_path_src<basic_string_view<_CharT, _Traits>>
  120. = __is_encoded_char<_CharT>;
  121. // SFINAE constraint for Source parameters as required by [fs.path.req].
  122. template<typename _Tp>
  123. using _Path = enable_if_t<__is_path_src<_Tp>, path>;
  124. // SFINAE constraint for InputIterator parameters as required by [fs.req].
  125. template<typename _Iter, typename _Tr = __safe_iterator_traits<_Iter>>
  126. using _Path2 = enable_if_t<__is_path_iter_src<_Tr>::value, path>;
  127. // The __effective_range overloads convert a Source parameter into
  128. // either a basic_string_view or basic_string containing the
  129. // effective range of the Source, as defined in [fs.path.req].
  130. template<typename _CharT, typename _Traits, typename _Alloc>
  131. inline basic_string_view<_CharT, _Traits>
  132. __effective_range(const basic_string<_CharT, _Traits, _Alloc>& __source)
  133. { return __source; }
  134. template<typename _CharT, typename _Traits>
  135. inline const basic_string_view<_CharT, _Traits>&
  136. __effective_range(const basic_string_view<_CharT, _Traits>& __source)
  137. { return __source; }
  138. template<typename _Source>
  139. inline auto
  140. __effective_range(const _Source& __source)
  141. {
  142. if constexpr (is_pointer_v<decay_t<_Source>>)
  143. return basic_string_view{&*__source};
  144. else
  145. {
  146. // _Source is an input iterator that iterates over an NTCTS.
  147. // Create a basic_string by reading until the null character.
  148. using value_type
  149. = typename iterator_traits<_Source>::value_type;
  150. basic_string<value_type> __str;
  151. _Source __it = __source;
  152. for (value_type __ch = *__it; __ch != value_type(); __ch = *++__it)
  153. __str.push_back(__ch);
  154. return __str;
  155. }
  156. }
  157. // The value type of a Source parameter's effective range.
  158. template<typename _Tp>
  159. using __value_t = typename remove_reference_t<
  160. decltype(__detail::__effective_range(std::declval<_Tp>()))>::value_type;
  161. // SFINAE helper to check that an effective range has value_type char,
  162. // as required by path constructors taking a std::locale parameter.
  163. // The type _Tp must have already been checked by _Path<Tp> or _Path2<_Tp>.
  164. template<typename _Tp, typename _Val = __value_t<_Tp>>
  165. using __value_type_is_char
  166. = std::enable_if_t<std::is_same_v<_Val, char>, _Val>;
  167. // As above, but also allows char8_t, as required by u8path
  168. // C++20 [depr.fs.path.factory]
  169. template<typename _Tp, typename _Val = __value_t<_Tp>>
  170. using __value_type_is_char_or_char8_t
  171. = std::enable_if_t<std::is_same_v<_Val, char>
  172. #ifdef _GLIBCXX_USE_CHAR8_T
  173. || std::is_same_v<_Val, char8_t>
  174. #endif
  175. , _Val>;
  176. // Create a string or string view from an iterator range.
  177. template<typename _InputIterator>
  178. inline auto
  179. __string_from_range(_InputIterator __first, _InputIterator __last)
  180. {
  181. using _EcharT
  182. = typename std::iterator_traits<_InputIterator>::value_type;
  183. static_assert(__is_encoded_char<_EcharT>);
  184. #if __cpp_lib_concepts
  185. constexpr bool __contiguous = std::contiguous_iterator<_InputIterator>;
  186. #else
  187. constexpr bool __contiguous
  188. = is_pointer_v<decltype(std::__niter_base(__first))>;
  189. #endif
  190. if constexpr (__contiguous)
  191. {
  192. // For contiguous iterators we can just return a string view.
  193. const auto* __f = std::__to_address(std::__niter_base(__first));
  194. const auto* __l = std::__to_address(std::__niter_base(__last));
  195. return basic_string_view<_EcharT>(__f, __l - __f);
  196. }
  197. else
  198. // Conversion requires contiguous characters, so create a string.
  199. return basic_string<_EcharT>(__first, __last);
  200. }
  201. } // namespace __detail
  202. /// @endcond
  203. /// A filesystem path.
  204. class path
  205. {
  206. public:
  207. #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
  208. using value_type = wchar_t;
  209. static constexpr value_type preferred_separator = L'\\';
  210. #else
  211. # ifdef _GLIBCXX_DOXYGEN
  212. /// Windows uses wchar_t for path::value_type, POSIX uses char.
  213. using value_type = __os_dependent__;
  214. # else
  215. using value_type = char;
  216. # endif
  217. static constexpr value_type preferred_separator = '/';
  218. #endif
  219. using string_type = std::basic_string<value_type>;
  220. /// path::format is ignored in this implementation
  221. enum format : unsigned char { native_format, generic_format, auto_format };
  222. // constructors and destructor
  223. path() noexcept { }
  224. path(const path& __p) = default;
  225. path(path&& __p)
  226. #if _GLIBCXX_USE_CXX11_ABI || _GLIBCXX_FULLY_DYNAMIC_STRING == 0
  227. noexcept
  228. #endif
  229. : _M_pathname(std::move(__p._M_pathname)),
  230. _M_cmpts(std::move(__p._M_cmpts))
  231. { __p.clear(); }
  232. path(string_type&& __source, format = auto_format)
  233. : _M_pathname(std::move(__source))
  234. { _M_split_cmpts(); }
  235. template<typename _Source,
  236. typename _Require = __detail::_Path<_Source>>
  237. path(_Source const& __source, format = auto_format)
  238. : _M_pathname(_S_convert(__detail::__effective_range(__source)))
  239. { _M_split_cmpts(); }
  240. template<typename _InputIterator,
  241. typename _Require = __detail::_Path2<_InputIterator>>
  242. path(_InputIterator __first, _InputIterator __last, format = auto_format)
  243. : _M_pathname(_S_convert(__first, __last))
  244. { _M_split_cmpts(); }
  245. template<typename _Source,
  246. typename _Require = __detail::_Path<_Source>,
  247. typename _Require2 = __detail::__value_type_is_char<_Source>>
  248. path(_Source const& __src, const locale& __loc, format = auto_format)
  249. : _M_pathname(_S_convert_loc(__detail::__effective_range(__src), __loc))
  250. { _M_split_cmpts(); }
  251. template<typename _InputIterator,
  252. typename _Require = __detail::_Path2<_InputIterator>,
  253. typename _Req2 = __detail::__value_type_is_char<_InputIterator>>
  254. path(_InputIterator __first, _InputIterator __last, const locale& __loc,
  255. format = auto_format)
  256. : _M_pathname(_S_convert_loc(__first, __last, __loc))
  257. { _M_split_cmpts(); }
  258. ~path() = default;
  259. // assignments
  260. path& operator=(const path&);
  261. path& operator=(path&&) noexcept;
  262. path& operator=(string_type&& __source);
  263. path& assign(string_type&& __source);
  264. template<typename _Source>
  265. __detail::_Path<_Source>&
  266. operator=(_Source const& __source)
  267. { return *this = path(__source); }
  268. template<typename _Source>
  269. __detail::_Path<_Source>&
  270. assign(_Source const& __source)
  271. { return *this = path(__source); }
  272. template<typename _InputIterator>
  273. __detail::_Path2<_InputIterator>&
  274. assign(_InputIterator __first, _InputIterator __last)
  275. { return *this = path(__first, __last); }
  276. // appends
  277. path& operator/=(const path& __p);
  278. template<typename _Source>
  279. __detail::_Path<_Source>&
  280. operator/=(_Source const& __source)
  281. {
  282. _M_append(_S_convert(__detail::__effective_range(__source)));
  283. return *this;
  284. }
  285. template<typename _Source>
  286. __detail::_Path<_Source>&
  287. append(_Source const& __source)
  288. {
  289. _M_append(_S_convert(__detail::__effective_range(__source)));
  290. return *this;
  291. }
  292. template<typename _InputIterator>
  293. __detail::_Path2<_InputIterator>&
  294. append(_InputIterator __first, _InputIterator __last)
  295. {
  296. _M_append(_S_convert(__first, __last));
  297. return *this;
  298. }
  299. // concatenation
  300. path& operator+=(const path& __x);
  301. path& operator+=(const string_type& __x);
  302. path& operator+=(const value_type* __x);
  303. path& operator+=(value_type __x);
  304. path& operator+=(basic_string_view<value_type> __x);
  305. template<typename _Source>
  306. __detail::_Path<_Source>&
  307. operator+=(_Source const& __x) { return concat(__x); }
  308. template<typename _CharT>
  309. __detail::_Path2<_CharT*>&
  310. operator+=(_CharT __x);
  311. template<typename _Source>
  312. __detail::_Path<_Source>&
  313. concat(_Source const& __x)
  314. {
  315. _M_concat(_S_convert(__detail::__effective_range(__x)));
  316. return *this;
  317. }
  318. template<typename _InputIterator>
  319. __detail::_Path2<_InputIterator>&
  320. concat(_InputIterator __first, _InputIterator __last)
  321. {
  322. _M_concat(_S_convert(__first, __last));
  323. return *this;
  324. }
  325. // modifiers
  326. void clear() noexcept { _M_pathname.clear(); _M_split_cmpts(); }
  327. path& make_preferred();
  328. path& remove_filename();
  329. path& replace_filename(const path& __replacement);
  330. path& replace_extension(const path& __replacement = path());
  331. void swap(path& __rhs) noexcept;
  332. // native format observers
  333. const string_type& native() const noexcept { return _M_pathname; }
  334. const value_type* c_str() const noexcept { return _M_pathname.c_str(); }
  335. operator string_type() const { return _M_pathname; }
  336. template<typename _CharT, typename _Traits = std::char_traits<_CharT>,
  337. typename _Allocator = std::allocator<_CharT>>
  338. std::basic_string<_CharT, _Traits, _Allocator>
  339. string(const _Allocator& __a = _Allocator()) const;
  340. std::string string() const;
  341. #if _GLIBCXX_USE_WCHAR_T
  342. std::wstring wstring() const;
  343. #endif
  344. #ifdef _GLIBCXX_USE_CHAR8_T
  345. __attribute__((__abi_tag__("__u8")))
  346. std::u8string u8string() const;
  347. #else
  348. std::string u8string() const;
  349. #endif // _GLIBCXX_USE_CHAR8_T
  350. std::u16string u16string() const;
  351. std::u32string u32string() const;
  352. // generic format observers
  353. template<typename _CharT, typename _Traits = std::char_traits<_CharT>,
  354. typename _Allocator = std::allocator<_CharT>>
  355. std::basic_string<_CharT, _Traits, _Allocator>
  356. generic_string(const _Allocator& __a = _Allocator()) const;
  357. std::string generic_string() const;
  358. #if _GLIBCXX_USE_WCHAR_T
  359. std::wstring generic_wstring() const;
  360. #endif
  361. #ifdef _GLIBCXX_USE_CHAR8_T
  362. __attribute__((__abi_tag__("__u8")))
  363. std::u8string generic_u8string() const;
  364. #else
  365. std::string generic_u8string() const;
  366. #endif // _GLIBCXX_USE_CHAR8_T
  367. std::u16string generic_u16string() const;
  368. std::u32string generic_u32string() const;
  369. // compare
  370. int compare(const path& __p) const noexcept;
  371. int compare(const string_type& __s) const noexcept;
  372. int compare(const value_type* __s) const noexcept;
  373. int compare(basic_string_view<value_type> __s) const noexcept;
  374. // decomposition
  375. path root_name() const;
  376. path root_directory() const;
  377. path root_path() const;
  378. path relative_path() const;
  379. path parent_path() const;
  380. path filename() const;
  381. path stem() const;
  382. path extension() const;
  383. // query
  384. [[nodiscard]] bool empty() const noexcept { return _M_pathname.empty(); }
  385. bool has_root_name() const noexcept;
  386. bool has_root_directory() const noexcept;
  387. bool has_root_path() const noexcept;
  388. bool has_relative_path() const noexcept;
  389. bool has_parent_path() const noexcept;
  390. bool has_filename() const noexcept;
  391. bool has_stem() const noexcept;
  392. bool has_extension() const noexcept;
  393. bool is_absolute() const noexcept;
  394. bool is_relative() const noexcept { return !is_absolute(); }
  395. // generation
  396. path lexically_normal() const;
  397. path lexically_relative(const path& base) const;
  398. path lexically_proximate(const path& base) const;
  399. // iterators
  400. class iterator;
  401. using const_iterator = iterator;
  402. iterator begin() const;
  403. iterator end() const;
  404. /// Write a path to a stream
  405. template<typename _CharT, typename _Traits>
  406. friend std::basic_ostream<_CharT, _Traits>&
  407. operator<<(std::basic_ostream<_CharT, _Traits>& __os, const path& __p)
  408. {
  409. __os << std::quoted(__p.string<_CharT, _Traits>());
  410. return __os;
  411. }
  412. /// Read a path from a stream
  413. template<typename _CharT, typename _Traits>
  414. friend std::basic_istream<_CharT, _Traits>&
  415. operator>>(std::basic_istream<_CharT, _Traits>& __is, path& __p)
  416. {
  417. std::basic_string<_CharT, _Traits> __tmp;
  418. if (__is >> std::quoted(__tmp))
  419. __p = std::move(__tmp);
  420. return __is;
  421. }
  422. // non-member operators
  423. /// Compare paths
  424. friend bool operator==(const path& __lhs, const path& __rhs) noexcept
  425. { return __lhs.compare(__rhs) == 0; }
  426. #if __cpp_lib_three_way_comparison
  427. /// Compare paths
  428. friend strong_ordering
  429. operator<=>(const path& __lhs, const path& __rhs) noexcept
  430. { return __lhs.compare(__rhs) <=> 0; }
  431. #else
  432. /// Compare paths
  433. friend bool operator!=(const path& __lhs, const path& __rhs) noexcept
  434. { return !(__lhs == __rhs); }
  435. /// Compare paths
  436. friend bool operator<(const path& __lhs, const path& __rhs) noexcept
  437. { return __lhs.compare(__rhs) < 0; }
  438. /// Compare paths
  439. friend bool operator<=(const path& __lhs, const path& __rhs) noexcept
  440. { return !(__rhs < __lhs); }
  441. /// Compare paths
  442. friend bool operator>(const path& __lhs, const path& __rhs) noexcept
  443. { return __rhs < __lhs; }
  444. /// Compare paths
  445. friend bool operator>=(const path& __lhs, const path& __rhs) noexcept
  446. { return !(__lhs < __rhs); }
  447. #endif
  448. /// Append one path to another
  449. friend path operator/(const path& __lhs, const path& __rhs)
  450. {
  451. path __result(__lhs);
  452. __result /= __rhs;
  453. return __result;
  454. }
  455. private:
  456. enum class _Type : unsigned char {
  457. _Multi = 0, _Root_name, _Root_dir, _Filename
  458. };
  459. path(basic_string_view<value_type> __str, _Type __type)
  460. : _M_pathname(__str)
  461. {
  462. __glibcxx_assert(__type != _Type::_Multi);
  463. _M_cmpts.type(__type);
  464. }
  465. enum class _Split { _Stem, _Extension };
  466. void _M_append(basic_string_view<value_type>);
  467. void _M_concat(basic_string_view<value_type>);
  468. pair<const string_type*, size_t> _M_find_extension() const noexcept;
  469. // path::_S_convert creates a basic_string<value_type> or
  470. // basic_string_view<value_type> from a range (either the effective
  471. // range of a Source parameter, or a pair of InputIterator parameters),
  472. // performing the conversions required by [fs.path.type.cvt].
  473. // If the value_type of the range value type is path::value_type,
  474. // no encoding conversion is performed. If the range is contiguous
  475. // a string_view
  476. static string_type
  477. _S_convert(string_type __str)
  478. { return __str; }
  479. template<typename _Tp>
  480. static auto
  481. _S_convert(const _Tp& __str)
  482. {
  483. if constexpr (is_same_v<_Tp, string_type>)
  484. return __str;
  485. else if constexpr (is_same_v<_Tp, basic_string_view<value_type>>)
  486. return __str;
  487. else if constexpr (is_same_v<typename _Tp::value_type, value_type>)
  488. return basic_string_view<value_type>(__str.data(), __str.size());
  489. else
  490. return _S_convert(__str.data(), __str.data() + __str.size());
  491. }
  492. template<typename _EcharT>
  493. static auto
  494. _S_convert(const _EcharT* __first, const _EcharT* __last);
  495. template<typename _Iter>
  496. static auto
  497. _S_convert(_Iter __first, _Iter __last)
  498. { return _S_convert(__detail::__string_from_range(__first, __last)); }
  499. static string_type
  500. _S_convert_loc(const char* __first, const char* __last,
  501. const std::locale& __loc);
  502. template<typename _Iter>
  503. static string_type
  504. _S_convert_loc(_Iter __first, _Iter __last, const std::locale& __loc)
  505. {
  506. const auto __s = __detail::__string_from_range(__first, __last);
  507. return _S_convert_loc(__s.data(), __s.data() + __s.size(), __loc);
  508. }
  509. template<typename _Tp>
  510. static string_type
  511. _S_convert_loc(const _Tp& __s, const std::locale& __loc)
  512. {
  513. return _S_convert_loc(__s.data(), __s.data() + __s.size(), __loc);
  514. }
  515. template<typename _CharT, typename _Traits, typename _Allocator>
  516. static basic_string<_CharT, _Traits, _Allocator>
  517. _S_str_convert(basic_string_view<value_type>, const _Allocator&);
  518. void _M_split_cmpts();
  519. _Type _M_type() const noexcept { return _M_cmpts.type(); }
  520. string_type _M_pathname;
  521. struct _Cmpt;
  522. struct _List
  523. {
  524. using value_type = _Cmpt;
  525. using iterator = value_type*;
  526. using const_iterator = const value_type*;
  527. _List();
  528. _List(const _List&);
  529. _List(_List&&) = default;
  530. _List& operator=(const _List&);
  531. _List& operator=(_List&&) = default;
  532. ~_List() = default;
  533. _Type type() const noexcept
  534. { return _Type(reinterpret_cast<uintptr_t>(_M_impl.get()) & 0x3); }
  535. void type(_Type) noexcept;
  536. int size() const noexcept; // zero unless type() == _Type::_Multi
  537. bool empty() const noexcept; // true unless type() == _Type::_Multi
  538. void clear();
  539. void swap(_List& __l) noexcept { _M_impl.swap(__l._M_impl); }
  540. int capacity() const noexcept;
  541. void reserve(int, bool); ///< @pre type() == _Type::_Multi
  542. // All the member functions below here have a precondition !empty()
  543. // (and they should only be called from within the library).
  544. iterator begin() noexcept;
  545. iterator end() noexcept;
  546. const_iterator begin() const noexcept;
  547. const_iterator end() const noexcept;
  548. value_type& front() noexcept;
  549. value_type& back() noexcept;
  550. const value_type& front() const noexcept;
  551. const value_type& back() const noexcept;
  552. void pop_back();
  553. void _M_erase_from(const_iterator __pos); // erases [__pos,end())
  554. struct _Impl;
  555. struct _Impl_deleter
  556. {
  557. void operator()(_Impl*) const noexcept;
  558. };
  559. unique_ptr<_Impl, _Impl_deleter> _M_impl;
  560. };
  561. _List _M_cmpts;
  562. struct _Parser;
  563. };
  564. /// @relates std::filesystem::path @{
  565. inline void swap(path& __lhs, path& __rhs) noexcept { __lhs.swap(__rhs); }
  566. size_t hash_value(const path& __p) noexcept;
  567. /// @}
  568. /// Exception type thrown by the Filesystem library
  569. class filesystem_error : public std::system_error
  570. {
  571. public:
  572. filesystem_error(const string& __what_arg, error_code __ec);
  573. filesystem_error(const string& __what_arg, const path& __p1,
  574. error_code __ec);
  575. filesystem_error(const string& __what_arg, const path& __p1,
  576. const path& __p2, error_code __ec);
  577. filesystem_error(const filesystem_error&) = default;
  578. filesystem_error& operator=(const filesystem_error&) = default;
  579. // No move constructor or assignment operator.
  580. // Copy rvalues instead, so that _M_impl is not left empty.
  581. ~filesystem_error();
  582. const path& path1() const noexcept;
  583. const path& path2() const noexcept;
  584. const char* what() const noexcept;
  585. private:
  586. struct _Impl;
  587. std::__shared_ptr<const _Impl> _M_impl;
  588. };
  589. /// @cond undocumented
  590. namespace __detail
  591. {
  592. [[noreturn]] inline void
  593. __throw_conversion_error()
  594. {
  595. _GLIBCXX_THROW_OR_ABORT(filesystem_error(
  596. "Cannot convert character sequence",
  597. std::make_error_code(errc::illegal_byte_sequence)));
  598. }
  599. #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
  600. template<typename _Tp>
  601. inline std::wstring
  602. __wstr_from_utf8(const _Tp& __str)
  603. {
  604. static_assert(std::is_same_v<typename _Tp::value_type, char>);
  605. std::wstring __wstr;
  606. // XXX This assumes native wide encoding is UTF-16.
  607. std::codecvt_utf8_utf16<wchar_t> __wcvt;
  608. const auto __p = __str.data();
  609. if (!__str_codecvt_in_all(__p, __p + __str.size(), __wstr, __wcvt))
  610. __detail::__throw_conversion_error();
  611. return __wstr;
  612. }
  613. #endif
  614. } // namespace __detail
  615. /// @endcond
  616. /** Create a path from a UTF-8-encoded sequence of char
  617. *
  618. * @relates std::filesystem::path
  619. */
  620. template<typename _InputIterator,
  621. typename _Require = __detail::_Path2<_InputIterator>,
  622. typename _CharT
  623. = __detail::__value_type_is_char_or_char8_t<_InputIterator>>
  624. inline path
  625. u8path(_InputIterator __first, _InputIterator __last)
  626. {
  627. #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
  628. if constexpr (is_same_v<_CharT, char>)
  629. return path{ __detail::__wstr_from_utf8(
  630. __detail::__string_from_range(__first, __last)) };
  631. else
  632. return path{ __first, __last }; // constructor handles char8_t
  633. #else
  634. // This assumes native normal encoding is UTF-8.
  635. return path{ __first, __last };
  636. #endif
  637. }
  638. /** Create a path from a UTF-8-encoded sequence of char
  639. *
  640. * @relates std::filesystem::path
  641. */
  642. template<typename _Source,
  643. typename _Require = __detail::_Path<_Source>,
  644. typename _CharT = __detail::__value_type_is_char_or_char8_t<_Source>>
  645. inline path
  646. u8path(const _Source& __source)
  647. {
  648. #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
  649. if constexpr (is_same_v<_CharT, char>)
  650. return path{ __detail::__wstr_from_utf8(
  651. __detail::__effective_range(__source)) };
  652. else
  653. return path{ __source }; // constructor handles char8_t
  654. #else
  655. // This assumes native normal encoding is UTF-8.
  656. return path{ __source };
  657. #endif
  658. }
  659. /// @cond undocumented
  660. struct path::_Cmpt : path
  661. {
  662. _Cmpt(basic_string_view<value_type> __s, _Type __t, size_t __pos)
  663. : path(__s, __t), _M_pos(__pos) { }
  664. _Cmpt() : _M_pos(-1) { }
  665. size_t _M_pos;
  666. };
  667. template<typename _EcharT>
  668. auto
  669. path::_S_convert(const _EcharT* __f, const _EcharT* __l)
  670. {
  671. static_assert(__detail::__is_encoded_char<_EcharT>);
  672. if constexpr (is_same_v<_EcharT, value_type>)
  673. return basic_string_view<value_type>(__f, __l - __f);
  674. #if !defined _GLIBCXX_FILESYSTEM_IS_WINDOWS && defined _GLIBCXX_USE_CHAR8_T
  675. else if constexpr (is_same_v<_EcharT, char8_t>)
  676. // For POSIX converting from char8_t to char is also 'noconv'
  677. return string_view(reinterpret_cast<const char*>(__f), __l - __f);
  678. #endif
  679. else
  680. {
  681. #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
  682. std::wstring __wstr;
  683. if constexpr (is_same_v<_EcharT, char>)
  684. {
  685. struct _UCvt : std::codecvt<wchar_t, char, std::mbstate_t>
  686. { } __cvt;
  687. if (__str_codecvt_in_all(__f, __l, __wstr, __cvt))
  688. return __wstr;
  689. }
  690. #ifdef _GLIBCXX_USE_CHAR8_T
  691. else if constexpr (is_same_v<_EcharT, char8_t>)
  692. {
  693. const auto __f2 = reinterpret_cast<const char*>(__f);
  694. return __detail::__wstr_from_utf8(string_view(__f2, __l - __f));
  695. }
  696. #endif
  697. else // char16_t or char32_t
  698. {
  699. struct _UCvt : std::codecvt<_EcharT, char, std::mbstate_t>
  700. { } __cvt;
  701. std::string __str;
  702. if (__str_codecvt_out_all(__f, __l, __str, __cvt))
  703. return __detail::__wstr_from_utf8(__str);
  704. }
  705. #else // ! windows
  706. struct _UCvt : std::codecvt<_EcharT, char, std::mbstate_t>
  707. { } __cvt;
  708. std::string __str;
  709. if (__str_codecvt_out_all(__f, __l, __str, __cvt))
  710. return __str;
  711. #endif
  712. __detail::__throw_conversion_error();
  713. }
  714. }
  715. /// @endcond
  716. /// An iterator for the components of a path
  717. class path::iterator
  718. {
  719. public:
  720. using difference_type = std::ptrdiff_t;
  721. using value_type = path;
  722. using reference = const path&;
  723. using pointer = const path*;
  724. using iterator_category = std::bidirectional_iterator_tag;
  725. iterator() : _M_path(nullptr), _M_cur(), _M_at_end() { }
  726. iterator(const iterator&) = default;
  727. iterator& operator=(const iterator&) = default;
  728. reference operator*() const;
  729. pointer operator->() const { return std::__addressof(**this); }
  730. iterator& operator++();
  731. iterator operator++(int) { auto __tmp = *this; ++*this; return __tmp; }
  732. iterator& operator--();
  733. iterator operator--(int) { auto __tmp = *this; --*this; return __tmp; }
  734. friend bool operator==(const iterator& __lhs, const iterator& __rhs)
  735. { return __lhs._M_equals(__rhs); }
  736. friend bool operator!=(const iterator& __lhs, const iterator& __rhs)
  737. { return !__lhs._M_equals(__rhs); }
  738. private:
  739. friend class path;
  740. bool _M_is_multi() const { return _M_path->_M_type() == _Type::_Multi; }
  741. friend difference_type
  742. __path_iter_distance(const iterator& __first, const iterator& __last)
  743. {
  744. __glibcxx_assert(__first._M_path != nullptr);
  745. __glibcxx_assert(__first._M_path == __last._M_path);
  746. if (__first._M_is_multi())
  747. return std::distance(__first._M_cur, __last._M_cur);
  748. else if (__first._M_at_end == __last._M_at_end)
  749. return 0;
  750. else
  751. return __first._M_at_end ? -1 : 1;
  752. }
  753. friend void
  754. __path_iter_advance(iterator& __i, difference_type __n)
  755. {
  756. if (__n == 1)
  757. ++__i;
  758. else if (__n == -1)
  759. --__i;
  760. else if (__n != 0)
  761. {
  762. __glibcxx_assert(__i._M_path != nullptr);
  763. __glibcxx_assert(__i._M_is_multi());
  764. // __glibcxx_assert(__i._M_path->_M_cmpts.end() - __i._M_cur >= __n);
  765. __i._M_cur += __n;
  766. }
  767. }
  768. iterator(const path* __path, path::_List::const_iterator __iter)
  769. : _M_path(__path), _M_cur(__iter), _M_at_end()
  770. { }
  771. iterator(const path* __path, bool __at_end)
  772. : _M_path(__path), _M_cur(), _M_at_end(__at_end)
  773. { }
  774. bool _M_equals(iterator) const;
  775. const path* _M_path;
  776. path::_List::const_iterator _M_cur;
  777. bool _M_at_end; // only used when type != _Multi
  778. };
  779. inline path&
  780. path::operator=(path&& __p) noexcept
  781. {
  782. if (&__p == this) [[__unlikely__]]
  783. return *this;
  784. _M_pathname = std::move(__p._M_pathname);
  785. _M_cmpts = std::move(__p._M_cmpts);
  786. __p.clear();
  787. return *this;
  788. }
  789. inline path&
  790. path::operator=(string_type&& __source)
  791. { return *this = path(std::move(__source)); }
  792. inline path&
  793. path::assign(string_type&& __source)
  794. { return *this = path(std::move(__source)); }
  795. inline path&
  796. path::operator+=(const string_type& __x)
  797. {
  798. _M_concat(__x);
  799. return *this;
  800. }
  801. inline path&
  802. path::operator+=(const value_type* __x)
  803. {
  804. _M_concat(__x);
  805. return *this;
  806. }
  807. inline path&
  808. path::operator+=(value_type __x)
  809. {
  810. _M_concat(basic_string_view<value_type>(&__x, 1));
  811. return *this;
  812. }
  813. inline path&
  814. path::operator+=(basic_string_view<value_type> __x)
  815. {
  816. _M_concat(__x);
  817. return *this;
  818. }
  819. template<typename _CharT>
  820. inline __detail::_Path2<_CharT*>&
  821. path::operator+=(const _CharT __x)
  822. {
  823. _M_concat(_S_convert(&__x, &__x + 1));
  824. return *this;
  825. }
  826. inline path&
  827. path::make_preferred()
  828. {
  829. #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
  830. std::replace(_M_pathname.begin(), _M_pathname.end(), L'/',
  831. preferred_separator);
  832. #endif
  833. return *this;
  834. }
  835. inline void path::swap(path& __rhs) noexcept
  836. {
  837. _M_pathname.swap(__rhs._M_pathname);
  838. _M_cmpts.swap(__rhs._M_cmpts);
  839. }
  840. /// @cond undocumented
  841. template<typename _CharT, typename _Traits, typename _Allocator>
  842. std::basic_string<_CharT, _Traits, _Allocator>
  843. path::_S_str_convert(basic_string_view<value_type> __str,
  844. const _Allocator& __a)
  845. {
  846. static_assert(!is_same_v<_CharT, value_type>);
  847. using _WString = basic_string<_CharT, _Traits, _Allocator>;
  848. if (__str.size() == 0)
  849. return _WString(__a);
  850. #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
  851. // First convert native string from UTF-16 to to UTF-8.
  852. // XXX This assumes that the execution wide-character set is UTF-16.
  853. std::codecvt_utf8_utf16<value_type> __cvt;
  854. using _CharAlloc = __alloc_rebind<_Allocator, char>;
  855. using _String = basic_string<char, char_traits<char>, _CharAlloc>;
  856. _String __u8str{_CharAlloc{__a}};
  857. const value_type* __wfirst = __str.data();
  858. const value_type* __wlast = __wfirst + __str.size();
  859. if (__str_codecvt_out_all(__wfirst, __wlast, __u8str, __cvt)) {
  860. if constexpr (is_same_v<_CharT, char>)
  861. return __u8str; // XXX assumes native ordinary encoding is UTF-8.
  862. else {
  863. const char* __first = __u8str.data();
  864. const char* __last = __first + __u8str.size();
  865. #else
  866. const value_type* __first = __str.data();
  867. const value_type* __last = __first + __str.size();
  868. #endif
  869. // Convert UTF-8 string to requested format.
  870. #ifdef _GLIBCXX_USE_CHAR8_T
  871. if constexpr (is_same_v<_CharT, char8_t>)
  872. return _WString(__first, __last, __a);
  873. else
  874. #endif
  875. {
  876. // Convert UTF-8 to wide string.
  877. _WString __wstr(__a);
  878. struct _UCvt : std::codecvt<_CharT, char, std::mbstate_t> { } __cvt;
  879. if (__str_codecvt_in_all(__first, __last, __wstr, __cvt))
  880. return __wstr;
  881. }
  882. #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
  883. } }
  884. #endif
  885. __detail::__throw_conversion_error();
  886. }
  887. /// @endcond
  888. template<typename _CharT, typename _Traits, typename _Allocator>
  889. inline basic_string<_CharT, _Traits, _Allocator>
  890. path::string(const _Allocator& __a) const
  891. {
  892. if constexpr (is_same_v<_CharT, value_type>)
  893. return { _M_pathname.c_str(), _M_pathname.length(), __a };
  894. else
  895. return _S_str_convert<_CharT, _Traits>(_M_pathname, __a);
  896. }
  897. inline std::string
  898. path::string() const { return string<char>(); }
  899. #if _GLIBCXX_USE_WCHAR_T
  900. inline std::wstring
  901. path::wstring() const { return string<wchar_t>(); }
  902. #endif
  903. #ifdef _GLIBCXX_USE_CHAR8_T
  904. inline std::u8string
  905. path::u8string() const { return string<char8_t>(); }
  906. #else
  907. inline std::string
  908. path::u8string() const
  909. {
  910. #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
  911. std::string __str;
  912. // convert from native wide encoding (assumed to be UTF-16) to UTF-8
  913. std::codecvt_utf8_utf16<value_type> __cvt;
  914. const value_type* __first = _M_pathname.data();
  915. const value_type* __last = __first + _M_pathname.size();
  916. if (__str_codecvt_out_all(__first, __last, __str, __cvt))
  917. return __str;
  918. __detail::__throw_conversion_error();
  919. #else
  920. return _M_pathname;
  921. #endif
  922. }
  923. #endif // _GLIBCXX_USE_CHAR8_T
  924. inline std::u16string
  925. path::u16string() const { return string<char16_t>(); }
  926. inline std::u32string
  927. path::u32string() const { return string<char32_t>(); }
  928. template<typename _CharT, typename _Traits, typename _Allocator>
  929. inline std::basic_string<_CharT, _Traits, _Allocator>
  930. path::generic_string(const _Allocator& __a) const
  931. {
  932. #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
  933. const value_type __slash = L'/';
  934. #else
  935. const value_type __slash = '/';
  936. #endif
  937. using _Alloc2 = typename allocator_traits<_Allocator>::template
  938. rebind_alloc<value_type>;
  939. basic_string<value_type, char_traits<value_type>, _Alloc2> __str(__a);
  940. if (_M_type() == _Type::_Root_dir)
  941. __str.assign(1, __slash);
  942. else
  943. {
  944. __str.reserve(_M_pathname.size());
  945. bool __add_slash = false;
  946. for (auto& __elem : *this)
  947. {
  948. #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
  949. if (__elem._M_type() == _Type::_Root_dir)
  950. {
  951. __str += __slash;
  952. continue;
  953. }
  954. #endif
  955. if (__add_slash)
  956. __str += __slash;
  957. __str += basic_string_view<value_type>(__elem._M_pathname);
  958. __add_slash = __elem._M_type() == _Type::_Filename;
  959. }
  960. }
  961. if constexpr (is_same_v<_CharT, value_type>)
  962. return __str;
  963. else
  964. return _S_str_convert<_CharT, _Traits>(__str, __a);
  965. }
  966. inline std::string
  967. path::generic_string() const
  968. { return generic_string<char>(); }
  969. #if _GLIBCXX_USE_WCHAR_T
  970. inline std::wstring
  971. path::generic_wstring() const
  972. { return generic_string<wchar_t>(); }
  973. #endif
  974. #ifdef _GLIBCXX_USE_CHAR8_T
  975. inline std::u8string
  976. path::generic_u8string() const
  977. { return generic_string<char8_t>(); }
  978. #else
  979. inline std::string
  980. path::generic_u8string() const
  981. { return generic_string(); }
  982. #endif
  983. inline std::u16string
  984. path::generic_u16string() const
  985. { return generic_string<char16_t>(); }
  986. inline std::u32string
  987. path::generic_u32string() const
  988. { return generic_string<char32_t>(); }
  989. inline int
  990. path::compare(const string_type& __s) const noexcept
  991. { return compare(basic_string_view<value_type>(__s)); }
  992. inline int
  993. path::compare(const value_type* __s) const noexcept
  994. { return compare(basic_string_view<value_type>(__s)); }
  995. inline path
  996. path::filename() const
  997. {
  998. if (empty())
  999. return {};
  1000. else if (_M_type() == _Type::_Filename)
  1001. return *this;
  1002. else if (_M_type() == _Type::_Multi)
  1003. {
  1004. if (_M_pathname.back() == preferred_separator)
  1005. return {};
  1006. auto& __last = *--end();
  1007. if (__last._M_type() == _Type::_Filename)
  1008. return __last;
  1009. }
  1010. return {};
  1011. }
  1012. inline path
  1013. path::stem() const
  1014. {
  1015. auto ext = _M_find_extension();
  1016. if (ext.first && ext.second != 0)
  1017. return path{ext.first->substr(0, ext.second)};
  1018. return {};
  1019. }
  1020. inline path
  1021. path::extension() const
  1022. {
  1023. auto ext = _M_find_extension();
  1024. if (ext.first && ext.second != string_type::npos)
  1025. return path{ext.first->substr(ext.second)};
  1026. return {};
  1027. }
  1028. inline bool
  1029. path::has_stem() const noexcept
  1030. {
  1031. auto ext = _M_find_extension();
  1032. return ext.first && ext.second != 0;
  1033. }
  1034. inline bool
  1035. path::has_extension() const noexcept
  1036. {
  1037. auto ext = _M_find_extension();
  1038. return ext.first && ext.second != string_type::npos;
  1039. }
  1040. inline bool
  1041. path::is_absolute() const noexcept
  1042. {
  1043. #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
  1044. return has_root_name() && has_root_directory();
  1045. #else
  1046. return has_root_directory();
  1047. #endif
  1048. }
  1049. inline path::iterator
  1050. path::begin() const
  1051. {
  1052. if (_M_type() == _Type::_Multi)
  1053. return iterator(this, _M_cmpts.begin());
  1054. return iterator(this, empty());
  1055. }
  1056. inline path::iterator
  1057. path::end() const
  1058. {
  1059. if (_M_type() == _Type::_Multi)
  1060. return iterator(this, _M_cmpts.end());
  1061. return iterator(this, true);
  1062. }
  1063. inline path::iterator&
  1064. path::iterator::operator++()
  1065. {
  1066. __glibcxx_assert(_M_path != nullptr);
  1067. if (_M_path->_M_type() == _Type::_Multi)
  1068. {
  1069. __glibcxx_assert(_M_cur != _M_path->_M_cmpts.end());
  1070. ++_M_cur;
  1071. }
  1072. else
  1073. {
  1074. __glibcxx_assert(!_M_at_end);
  1075. _M_at_end = true;
  1076. }
  1077. return *this;
  1078. }
  1079. inline path::iterator&
  1080. path::iterator::operator--()
  1081. {
  1082. __glibcxx_assert(_M_path != nullptr);
  1083. if (_M_path->_M_type() == _Type::_Multi)
  1084. {
  1085. __glibcxx_assert(_M_cur != _M_path->_M_cmpts.begin());
  1086. --_M_cur;
  1087. }
  1088. else
  1089. {
  1090. __glibcxx_assert(_M_at_end);
  1091. _M_at_end = false;
  1092. }
  1093. return *this;
  1094. }
  1095. inline path::iterator::reference
  1096. path::iterator::operator*() const
  1097. {
  1098. __glibcxx_assert(_M_path != nullptr);
  1099. if (_M_path->_M_type() == _Type::_Multi)
  1100. {
  1101. __glibcxx_assert(_M_cur != _M_path->_M_cmpts.end());
  1102. return *_M_cur;
  1103. }
  1104. return *_M_path;
  1105. }
  1106. inline bool
  1107. path::iterator::_M_equals(iterator __rhs) const
  1108. {
  1109. if (_M_path != __rhs._M_path)
  1110. return false;
  1111. if (_M_path == nullptr)
  1112. return true;
  1113. if (_M_path->_M_type() == path::_Type::_Multi)
  1114. return _M_cur == __rhs._M_cur;
  1115. return _M_at_end == __rhs._M_at_end;
  1116. }
  1117. /// @} group filesystem
  1118. _GLIBCXX_END_NAMESPACE_CXX11
  1119. } // namespace filesystem
  1120. inline ptrdiff_t
  1121. distance(filesystem::path::iterator __first, filesystem::path::iterator __last)
  1122. { return __path_iter_distance(__first, __last); }
  1123. template<typename _InputIterator, typename _Distance>
  1124. void
  1125. advance(filesystem::path::iterator& __i, _Distance __n)
  1126. { __path_iter_advance(__i, static_cast<ptrdiff_t>(__n)); }
  1127. extern template class __shared_ptr<const filesystem::filesystem_error::_Impl>;
  1128. _GLIBCXX_END_NAMESPACE_VERSION
  1129. } // namespace std
  1130. #endif // C++17
  1131. #endif // _GLIBCXX_FS_PATH_H