fs_path.h 40 KB

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