path.h 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932
  1. // -*- C++ -*-
  2. //===----------------------------------------------------------------------===//
  3. //
  4. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  5. // See https://llvm.org/LICENSE.txt for license information.
  6. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  7. //
  8. //===----------------------------------------------------------------------===//
  9. #ifndef _LIBCPP___FILESYSTEM_PATH_H
  10. #define _LIBCPP___FILESYSTEM_PATH_H
  11. #include <__algorithm/replace.h>
  12. #include <__algorithm/replace_copy.h>
  13. #include <__availability>
  14. #include <__config>
  15. #include <__functional/unary_function.h>
  16. #include <__fwd/functional.h>
  17. #include <__iterator/back_insert_iterator.h>
  18. #include <__iterator/iterator_traits.h>
  19. #include <__type_traits/decay.h>
  20. #include <__type_traits/is_pointer.h>
  21. #include <__type_traits/remove_const.h>
  22. #include <__type_traits/remove_pointer.h>
  23. #include <cstddef>
  24. #include <string>
  25. #include <string_view>
  26. #if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
  27. # include <iomanip> // for quoted
  28. # include <locale>
  29. #endif
  30. #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
  31. # pragma GCC system_header
  32. #endif
  33. _LIBCPP_PUSH_MACROS
  34. #include <__undef_macros>
  35. #if _LIBCPP_STD_VER >= 17
  36. _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM
  37. _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_PUSH
  38. template <class _Tp>
  39. struct __can_convert_char {
  40. static const bool value = false;
  41. };
  42. template <class _Tp>
  43. struct __can_convert_char<const _Tp> : public __can_convert_char<_Tp> {};
  44. template <>
  45. struct __can_convert_char<char> {
  46. static const bool value = true;
  47. using __char_type = char;
  48. };
  49. template <>
  50. struct __can_convert_char<wchar_t> {
  51. static const bool value = true;
  52. using __char_type = wchar_t;
  53. };
  54. # ifndef _LIBCPP_HAS_NO_CHAR8_T
  55. template <>
  56. struct __can_convert_char<char8_t> {
  57. static const bool value = true;
  58. using __char_type = char8_t;
  59. };
  60. # endif
  61. template <>
  62. struct __can_convert_char<char16_t> {
  63. static const bool value = true;
  64. using __char_type = char16_t;
  65. };
  66. template <>
  67. struct __can_convert_char<char32_t> {
  68. static const bool value = true;
  69. using __char_type = char32_t;
  70. };
  71. template <class _ECharT, __enable_if_t<__can_convert_char<_ECharT>::value, int> = 0>
  72. _LIBCPP_HIDE_FROM_ABI bool __is_separator(_ECharT __e) {
  73. # if defined(_LIBCPP_WIN32API)
  74. return __e == _ECharT('/') || __e == _ECharT('\\');
  75. # else
  76. return __e == _ECharT('/');
  77. # endif
  78. }
  79. # ifndef _LIBCPP_HAS_NO_CHAR8_T
  80. typedef u8string __u8_string;
  81. # else
  82. typedef string __u8_string;
  83. # endif
  84. struct _NullSentinel {};
  85. template <class _Tp>
  86. using _Void = void;
  87. template <class _Tp, class = void>
  88. struct __is_pathable_string : public false_type {};
  89. template <class _ECharT, class _Traits, class _Alloc>
  90. struct __is_pathable_string< basic_string<_ECharT, _Traits, _Alloc>,
  91. _Void<typename __can_convert_char<_ECharT>::__char_type> >
  92. : public __can_convert_char<_ECharT> {
  93. using _Str = basic_string<_ECharT, _Traits, _Alloc>;
  94. _LIBCPP_HIDE_FROM_ABI static _ECharT const* __range_begin(_Str const& __s) { return __s.data(); }
  95. _LIBCPP_HIDE_FROM_ABI static _ECharT const* __range_end(_Str const& __s) { return __s.data() + __s.length(); }
  96. _LIBCPP_HIDE_FROM_ABI static _ECharT __first_or_null(_Str const& __s) { return __s.empty() ? _ECharT{} : __s[0]; }
  97. };
  98. template <class _ECharT, class _Traits>
  99. struct __is_pathable_string< basic_string_view<_ECharT, _Traits>,
  100. _Void<typename __can_convert_char<_ECharT>::__char_type> >
  101. : public __can_convert_char<_ECharT> {
  102. using _Str = basic_string_view<_ECharT, _Traits>;
  103. _LIBCPP_HIDE_FROM_ABI static _ECharT const* __range_begin(_Str const& __s) { return __s.data(); }
  104. _LIBCPP_HIDE_FROM_ABI static _ECharT const* __range_end(_Str const& __s) { return __s.data() + __s.length(); }
  105. _LIBCPP_HIDE_FROM_ABI static _ECharT __first_or_null(_Str const& __s) { return __s.empty() ? _ECharT{} : __s[0]; }
  106. };
  107. template <class _Source,
  108. class _DS = __decay_t<_Source>,
  109. class _UnqualPtrType = __remove_const_t<__remove_pointer_t<_DS> >,
  110. bool _IsCharPtr = is_pointer<_DS>::value && __can_convert_char<_UnqualPtrType>::value>
  111. struct __is_pathable_char_array : false_type {};
  112. template <class _Source, class _ECharT, class _UPtr>
  113. struct __is_pathable_char_array<_Source, _ECharT*, _UPtr, true> : __can_convert_char<__remove_const_t<_ECharT> > {
  114. _LIBCPP_HIDE_FROM_ABI static _ECharT const* __range_begin(const _ECharT* __b) { return __b; }
  115. _LIBCPP_HIDE_FROM_ABI static _ECharT const* __range_end(const _ECharT* __b) {
  116. using _Iter = const _ECharT*;
  117. const _ECharT __sentinel = _ECharT{};
  118. _Iter __e = __b;
  119. for (; *__e != __sentinel; ++__e)
  120. ;
  121. return __e;
  122. }
  123. _LIBCPP_HIDE_FROM_ABI static _ECharT __first_or_null(const _ECharT* __b) { return *__b; }
  124. };
  125. template <class _Iter, bool _IsIt = __has_input_iterator_category<_Iter>::value, class = void>
  126. struct __is_pathable_iter : false_type {};
  127. template <class _Iter>
  128. struct __is_pathable_iter<
  129. _Iter,
  130. true,
  131. _Void<typename __can_convert_char< typename iterator_traits<_Iter>::value_type>::__char_type> >
  132. : __can_convert_char<typename iterator_traits<_Iter>::value_type> {
  133. using _ECharT = typename iterator_traits<_Iter>::value_type;
  134. _LIBCPP_HIDE_FROM_ABI static _Iter __range_begin(_Iter __b) { return __b; }
  135. _LIBCPP_HIDE_FROM_ABI static _NullSentinel __range_end(_Iter) { return _NullSentinel{}; }
  136. _LIBCPP_HIDE_FROM_ABI static _ECharT __first_or_null(_Iter __b) { return *__b; }
  137. };
  138. template <class _Tp,
  139. bool _IsStringT = __is_pathable_string<_Tp>::value,
  140. bool _IsCharIterT = __is_pathable_char_array<_Tp>::value,
  141. bool _IsIterT = !_IsCharIterT && __is_pathable_iter<_Tp>::value>
  142. struct __is_pathable : false_type {
  143. static_assert(!_IsStringT && !_IsCharIterT && !_IsIterT, "Must all be false");
  144. };
  145. template <class _Tp>
  146. struct __is_pathable<_Tp, true, false, false> : __is_pathable_string<_Tp> {};
  147. template <class _Tp>
  148. struct __is_pathable<_Tp, false, true, false> : __is_pathable_char_array<_Tp> {};
  149. template <class _Tp>
  150. struct __is_pathable<_Tp, false, false, true> : __is_pathable_iter<_Tp> {};
  151. # if defined(_LIBCPP_WIN32API)
  152. typedef wstring __path_string;
  153. typedef wchar_t __path_value;
  154. # else
  155. typedef string __path_string;
  156. typedef char __path_value;
  157. # endif
  158. # if defined(_LIBCPP_WIN32API)
  159. _LIBCPP_EXPORTED_FROM_ABI size_t __wide_to_char(const wstring&, char*, size_t);
  160. _LIBCPP_EXPORTED_FROM_ABI size_t __char_to_wide(const string&, wchar_t*, size_t);
  161. # endif
  162. template <class _ECharT>
  163. struct _PathCVT;
  164. # if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
  165. template <class _ECharT>
  166. struct _PathCVT {
  167. static_assert(__can_convert_char<_ECharT>::value, "Char type not convertible");
  168. typedef __narrow_to_utf8<sizeof(_ECharT) * __CHAR_BIT__> _Narrower;
  169. # if defined(_LIBCPP_WIN32API)
  170. typedef __widen_from_utf8<sizeof(wchar_t) * __CHAR_BIT__> _Widener;
  171. # endif
  172. _LIBCPP_HIDE_FROM_ABI static void __append_range(__path_string& __dest, _ECharT const* __b, _ECharT const* __e) {
  173. # if defined(_LIBCPP_WIN32API)
  174. string __utf8;
  175. _Narrower()(back_inserter(__utf8), __b, __e);
  176. _Widener()(back_inserter(__dest), __utf8.data(), __utf8.data() + __utf8.size());
  177. # else
  178. _Narrower()(back_inserter(__dest), __b, __e);
  179. # endif
  180. }
  181. template <class _Iter>
  182. _LIBCPP_HIDE_FROM_ABI static void __append_range(__path_string& __dest, _Iter __b, _Iter __e) {
  183. static_assert(!is_same<_Iter, _ECharT*>::value, "Call const overload");
  184. if (__b == __e)
  185. return;
  186. basic_string<_ECharT> __tmp(__b, __e);
  187. # if defined(_LIBCPP_WIN32API)
  188. string __utf8;
  189. _Narrower()(back_inserter(__utf8), __tmp.data(), __tmp.data() + __tmp.length());
  190. _Widener()(back_inserter(__dest), __utf8.data(), __utf8.data() + __utf8.size());
  191. # else
  192. _Narrower()(back_inserter(__dest), __tmp.data(), __tmp.data() + __tmp.length());
  193. # endif
  194. }
  195. template <class _Iter>
  196. _LIBCPP_HIDE_FROM_ABI static void __append_range(__path_string& __dest, _Iter __b, _NullSentinel) {
  197. static_assert(!is_same<_Iter, _ECharT*>::value, "Call const overload");
  198. const _ECharT __sentinel = _ECharT{};
  199. if (*__b == __sentinel)
  200. return;
  201. basic_string<_ECharT> __tmp;
  202. for (; *__b != __sentinel; ++__b)
  203. __tmp.push_back(*__b);
  204. # if defined(_LIBCPP_WIN32API)
  205. string __utf8;
  206. _Narrower()(back_inserter(__utf8), __tmp.data(), __tmp.data() + __tmp.length());
  207. _Widener()(back_inserter(__dest), __utf8.data(), __utf8.data() + __utf8.size());
  208. # else
  209. _Narrower()(back_inserter(__dest), __tmp.data(), __tmp.data() + __tmp.length());
  210. # endif
  211. }
  212. template <class _Source>
  213. _LIBCPP_HIDE_FROM_ABI static void __append_source(__path_string& __dest, _Source const& __s) {
  214. using _Traits = __is_pathable<_Source>;
  215. __append_range(__dest, _Traits::__range_begin(__s), _Traits::__range_end(__s));
  216. }
  217. };
  218. # endif // !_LIBCPP_HAS_NO_LOCALIZATION
  219. template <>
  220. struct _PathCVT<__path_value> {
  221. template <class _Iter, __enable_if_t<__has_exactly_input_iterator_category<_Iter>::value, int> = 0>
  222. _LIBCPP_HIDE_FROM_ABI static void __append_range(__path_string& __dest, _Iter __b, _Iter __e) {
  223. for (; __b != __e; ++__b)
  224. __dest.push_back(*__b);
  225. }
  226. template <class _Iter, __enable_if_t<__has_forward_iterator_category<_Iter>::value, int> = 0>
  227. _LIBCPP_HIDE_FROM_ABI static void __append_range(__path_string& __dest, _Iter __b, _Iter __e) {
  228. __dest.append(__b, __e);
  229. }
  230. template <class _Iter>
  231. _LIBCPP_HIDE_FROM_ABI static void __append_range(__path_string& __dest, _Iter __b, _NullSentinel) {
  232. const char __sentinel = char{};
  233. for (; *__b != __sentinel; ++__b)
  234. __dest.push_back(*__b);
  235. }
  236. template <class _Source>
  237. _LIBCPP_HIDE_FROM_ABI static void __append_source(__path_string& __dest, _Source const& __s) {
  238. using _Traits = __is_pathable<_Source>;
  239. __append_range(__dest, _Traits::__range_begin(__s), _Traits::__range_end(__s));
  240. }
  241. };
  242. # if defined(_LIBCPP_WIN32API)
  243. template <>
  244. struct _PathCVT<char> {
  245. _LIBCPP_HIDE_FROM_ABI static void __append_string(__path_string& __dest, const basic_string<char>& __str) {
  246. size_t __size = __char_to_wide(__str, nullptr, 0);
  247. size_t __pos = __dest.size();
  248. __dest.resize(__pos + __size);
  249. __char_to_wide(__str, const_cast<__path_value*>(__dest.data()) + __pos, __size);
  250. }
  251. template <class _Iter, __enable_if_t<__has_exactly_input_iterator_category<_Iter>::value, int> = 0>
  252. _LIBCPP_HIDE_FROM_ABI static void __append_range(__path_string& __dest, _Iter __b, _Iter __e) {
  253. basic_string<char> __tmp(__b, __e);
  254. __append_string(__dest, __tmp);
  255. }
  256. template <class _Iter, __enable_if_t<__has_forward_iterator_category<_Iter>::value, int> = 0>
  257. _LIBCPP_HIDE_FROM_ABI static void __append_range(__path_string& __dest, _Iter __b, _Iter __e) {
  258. basic_string<char> __tmp(__b, __e);
  259. __append_string(__dest, __tmp);
  260. }
  261. template <class _Iter>
  262. _LIBCPP_HIDE_FROM_ABI static void __append_range(__path_string& __dest, _Iter __b, _NullSentinel) {
  263. const char __sentinel = char{};
  264. basic_string<char> __tmp;
  265. for (; *__b != __sentinel; ++__b)
  266. __tmp.push_back(*__b);
  267. __append_string(__dest, __tmp);
  268. }
  269. template <class _Source>
  270. _LIBCPP_HIDE_FROM_ABI static void __append_source(__path_string& __dest, _Source const& __s) {
  271. using _Traits = __is_pathable<_Source>;
  272. __append_range(__dest, _Traits::__range_begin(__s), _Traits::__range_end(__s));
  273. }
  274. };
  275. template <class _ECharT>
  276. struct _PathExport {
  277. typedef __narrow_to_utf8<sizeof(wchar_t) * __CHAR_BIT__> _Narrower;
  278. typedef __widen_from_utf8<sizeof(_ECharT) * __CHAR_BIT__> _Widener;
  279. template <class _Str>
  280. _LIBCPP_HIDE_FROM_ABI static void __append(_Str& __dest, const __path_string& __src) {
  281. string __utf8;
  282. _Narrower()(back_inserter(__utf8), __src.data(), __src.data() + __src.size());
  283. _Widener()(back_inserter(__dest), __utf8.data(), __utf8.data() + __utf8.size());
  284. }
  285. };
  286. template <>
  287. struct _PathExport<char> {
  288. template <class _Str>
  289. _LIBCPP_HIDE_FROM_ABI static void __append(_Str& __dest, const __path_string& __src) {
  290. size_t __size = __wide_to_char(__src, nullptr, 0);
  291. size_t __pos = __dest.size();
  292. __dest.resize(__size);
  293. __wide_to_char(__src, const_cast<char*>(__dest.data()) + __pos, __size);
  294. }
  295. };
  296. template <>
  297. struct _PathExport<wchar_t> {
  298. template <class _Str>
  299. _LIBCPP_HIDE_FROM_ABI static void __append(_Str& __dest, const __path_string& __src) {
  300. __dest.append(__src.begin(), __src.end());
  301. }
  302. };
  303. template <>
  304. struct _PathExport<char16_t> {
  305. template <class _Str>
  306. _LIBCPP_HIDE_FROM_ABI static void __append(_Str& __dest, const __path_string& __src) {
  307. __dest.append(__src.begin(), __src.end());
  308. }
  309. };
  310. # ifndef _LIBCPP_HAS_NO_CHAR8_T
  311. template <>
  312. struct _PathExport<char8_t> {
  313. typedef __narrow_to_utf8<sizeof(wchar_t) * __CHAR_BIT__> _Narrower;
  314. template <class _Str>
  315. _LIBCPP_HIDE_FROM_ABI static void __append(_Str& __dest, const __path_string& __src) {
  316. _Narrower()(back_inserter(__dest), __src.data(), __src.data() + __src.size());
  317. }
  318. };
  319. # endif /* !_LIBCPP_HAS_NO_CHAR8_T */
  320. # endif /* _LIBCPP_WIN32API */
  321. class _LIBCPP_EXPORTED_FROM_ABI path {
  322. template <class _SourceOrIter, class _Tp = path&>
  323. using _EnableIfPathable = __enable_if_t<__is_pathable<_SourceOrIter>::value, _Tp>;
  324. template <class _Tp>
  325. using _SourceChar = typename __is_pathable<_Tp>::__char_type;
  326. template <class _Tp>
  327. using _SourceCVT = _PathCVT<_SourceChar<_Tp> >;
  328. public:
  329. # if defined(_LIBCPP_WIN32API)
  330. typedef wchar_t value_type;
  331. static constexpr value_type preferred_separator = L'\\';
  332. # else
  333. typedef char value_type;
  334. static constexpr value_type preferred_separator = '/';
  335. # endif
  336. typedef basic_string<value_type> string_type;
  337. typedef basic_string_view<value_type> __string_view;
  338. enum format : unsigned char { auto_format, native_format, generic_format };
  339. // constructors and destructor
  340. _LIBCPP_HIDE_FROM_ABI path() noexcept {}
  341. _LIBCPP_HIDE_FROM_ABI path(const path& __p) : __pn_(__p.__pn_) {}
  342. _LIBCPP_HIDE_FROM_ABI path(path&& __p) noexcept : __pn_(std::move(__p.__pn_)) {}
  343. _LIBCPP_HIDE_FROM_ABI path(string_type&& __s, format = format::auto_format) noexcept : __pn_(std::move(__s)) {}
  344. template <class _Source, class = _EnableIfPathable<_Source, void> >
  345. _LIBCPP_HIDE_FROM_ABI path(const _Source& __src, format = format::auto_format) {
  346. _SourceCVT<_Source>::__append_source(__pn_, __src);
  347. }
  348. template <class _InputIt>
  349. _LIBCPP_HIDE_FROM_ABI path(_InputIt __first, _InputIt __last, format = format::auto_format) {
  350. typedef typename iterator_traits<_InputIt>::value_type _ItVal;
  351. _PathCVT<_ItVal>::__append_range(__pn_, __first, __last);
  352. }
  353. /*
  354. #if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
  355. // TODO Implement locale conversions.
  356. template <class _Source, class = _EnableIfPathable<_Source, void> >
  357. path(const _Source& __src, const locale& __loc, format = format::auto_format);
  358. template <class _InputIt>
  359. path(_InputIt __first, _InputIt _last, const locale& __loc,
  360. format = format::auto_format);
  361. #endif
  362. */
  363. _LIBCPP_HIDE_FROM_ABI ~path() = default;
  364. // assignments
  365. _LIBCPP_HIDE_FROM_ABI path& operator=(const path& __p) {
  366. __pn_ = __p.__pn_;
  367. return *this;
  368. }
  369. _LIBCPP_HIDE_FROM_ABI path& operator=(path&& __p) noexcept {
  370. __pn_ = std::move(__p.__pn_);
  371. return *this;
  372. }
  373. _LIBCPP_HIDE_FROM_ABI path& operator=(string_type&& __s) noexcept {
  374. __pn_ = std::move(__s);
  375. return *this;
  376. }
  377. _LIBCPP_HIDE_FROM_ABI path& assign(string_type&& __s) noexcept {
  378. __pn_ = std::move(__s);
  379. return *this;
  380. }
  381. template <class _Source>
  382. _LIBCPP_HIDE_FROM_ABI _EnableIfPathable<_Source> operator=(const _Source& __src) {
  383. return this->assign(__src);
  384. }
  385. template <class _Source>
  386. _LIBCPP_HIDE_FROM_ABI _EnableIfPathable<_Source> assign(const _Source& __src) {
  387. __pn_.clear();
  388. _SourceCVT<_Source>::__append_source(__pn_, __src);
  389. return *this;
  390. }
  391. template <class _InputIt>
  392. _LIBCPP_HIDE_FROM_ABI path& assign(_InputIt __first, _InputIt __last) {
  393. typedef typename iterator_traits<_InputIt>::value_type _ItVal;
  394. __pn_.clear();
  395. _PathCVT<_ItVal>::__append_range(__pn_, __first, __last);
  396. return *this;
  397. }
  398. public:
  399. // appends
  400. # if defined(_LIBCPP_WIN32API)
  401. _LIBCPP_HIDE_FROM_ABI path& operator/=(const path& __p) {
  402. auto __p_root_name = __p.__root_name();
  403. auto __p_root_name_size = __p_root_name.size();
  404. if (__p.is_absolute() || (!__p_root_name.empty() && __p_root_name != __string_view(root_name().__pn_))) {
  405. __pn_ = __p.__pn_;
  406. return *this;
  407. }
  408. if (__p.has_root_directory()) {
  409. path __root_name_str = root_name();
  410. __pn_ = __root_name_str.native();
  411. __pn_ += __string_view(__p.__pn_).substr(__p_root_name_size);
  412. return *this;
  413. }
  414. if (has_filename() || (!has_root_directory() && is_absolute()))
  415. __pn_ += preferred_separator;
  416. __pn_ += __string_view(__p.__pn_).substr(__p_root_name_size);
  417. return *this;
  418. }
  419. template <class _Source>
  420. _LIBCPP_HIDE_FROM_ABI _EnableIfPathable<_Source> operator/=(const _Source& __src) {
  421. return operator/=(path(__src));
  422. }
  423. template <class _Source>
  424. _LIBCPP_HIDE_FROM_ABI _EnableIfPathable<_Source> append(const _Source& __src) {
  425. return operator/=(path(__src));
  426. }
  427. template <class _InputIt>
  428. _LIBCPP_HIDE_FROM_ABI path& append(_InputIt __first, _InputIt __last) {
  429. return operator/=(path(__first, __last));
  430. }
  431. # else
  432. _LIBCPP_HIDE_FROM_ABI path& operator/=(const path& __p) {
  433. if (__p.is_absolute()) {
  434. __pn_ = __p.__pn_;
  435. return *this;
  436. }
  437. if (has_filename())
  438. __pn_ += preferred_separator;
  439. __pn_ += __p.native();
  440. return *this;
  441. }
  442. // FIXME: Use _LIBCPP_DIAGNOSE_WARNING to produce a diagnostic when __src
  443. // is known at compile time to be "/' since the user almost certainly intended
  444. // to append a separator instead of overwriting the path with "/"
  445. template <class _Source>
  446. _LIBCPP_HIDE_FROM_ABI _EnableIfPathable<_Source> operator/=(const _Source& __src) {
  447. return this->append(__src);
  448. }
  449. template <class _Source>
  450. _LIBCPP_HIDE_FROM_ABI _EnableIfPathable<_Source> append(const _Source& __src) {
  451. using _Traits = __is_pathable<_Source>;
  452. using _CVT = _PathCVT<_SourceChar<_Source> >;
  453. bool __source_is_absolute = filesystem::__is_separator(_Traits::__first_or_null(__src));
  454. if (__source_is_absolute)
  455. __pn_.clear();
  456. else if (has_filename())
  457. __pn_ += preferred_separator;
  458. _CVT::__append_source(__pn_, __src);
  459. return *this;
  460. }
  461. template <class _InputIt>
  462. _LIBCPP_HIDE_FROM_ABI path& append(_InputIt __first, _InputIt __last) {
  463. typedef typename iterator_traits<_InputIt>::value_type _ItVal;
  464. static_assert(__can_convert_char<_ItVal>::value, "Must convertible");
  465. using _CVT = _PathCVT<_ItVal>;
  466. if (__first != __last && filesystem::__is_separator(*__first))
  467. __pn_.clear();
  468. else if (has_filename())
  469. __pn_ += preferred_separator;
  470. _CVT::__append_range(__pn_, __first, __last);
  471. return *this;
  472. }
  473. # endif
  474. // concatenation
  475. _LIBCPP_HIDE_FROM_ABI path& operator+=(const path& __x) {
  476. __pn_ += __x.__pn_;
  477. return *this;
  478. }
  479. _LIBCPP_HIDE_FROM_ABI path& operator+=(const string_type& __x) {
  480. __pn_ += __x;
  481. return *this;
  482. }
  483. _LIBCPP_HIDE_FROM_ABI path& operator+=(__string_view __x) {
  484. __pn_ += __x;
  485. return *this;
  486. }
  487. _LIBCPP_HIDE_FROM_ABI path& operator+=(const value_type* __x) {
  488. __pn_ += __x;
  489. return *this;
  490. }
  491. _LIBCPP_HIDE_FROM_ABI path& operator+=(value_type __x) {
  492. __pn_ += __x;
  493. return *this;
  494. }
  495. template <class _ECharT, __enable_if_t<__can_convert_char<_ECharT>::value, int> = 0>
  496. _LIBCPP_HIDE_FROM_ABI path& operator+=(_ECharT __x) {
  497. _PathCVT<_ECharT>::__append_source(__pn_, basic_string_view<_ECharT>(&__x, 1));
  498. return *this;
  499. }
  500. template <class _Source>
  501. _LIBCPP_HIDE_FROM_ABI _EnableIfPathable<_Source> operator+=(const _Source& __x) {
  502. return this->concat(__x);
  503. }
  504. template <class _Source>
  505. _LIBCPP_HIDE_FROM_ABI _EnableIfPathable<_Source> concat(const _Source& __x) {
  506. _SourceCVT<_Source>::__append_source(__pn_, __x);
  507. return *this;
  508. }
  509. template <class _InputIt>
  510. _LIBCPP_HIDE_FROM_ABI path& concat(_InputIt __first, _InputIt __last) {
  511. typedef typename iterator_traits<_InputIt>::value_type _ItVal;
  512. _PathCVT<_ItVal>::__append_range(__pn_, __first, __last);
  513. return *this;
  514. }
  515. // modifiers
  516. _LIBCPP_HIDE_FROM_ABI void clear() noexcept { __pn_.clear(); }
  517. _LIBCPP_HIDE_FROM_ABI path& make_preferred() {
  518. # if defined(_LIBCPP_WIN32API)
  519. std::replace(__pn_.begin(), __pn_.end(), L'/', L'\\');
  520. # endif
  521. return *this;
  522. }
  523. _LIBCPP_HIDE_FROM_ABI path& remove_filename() {
  524. auto __fname = __filename();
  525. if (!__fname.empty())
  526. __pn_.erase(__fname.data() - __pn_.data());
  527. return *this;
  528. }
  529. _LIBCPP_HIDE_FROM_ABI path& replace_filename(const path& __replacement) {
  530. remove_filename();
  531. return (*this /= __replacement);
  532. }
  533. path& replace_extension(const path& __replacement = path());
  534. friend _LIBCPP_HIDE_FROM_ABI bool operator==(const path& __lhs, const path& __rhs) noexcept {
  535. return __lhs.__compare(__rhs.__pn_) == 0;
  536. }
  537. # if _LIBCPP_STD_VER <= 17
  538. friend _LIBCPP_HIDE_FROM_ABI bool operator!=(const path& __lhs, const path& __rhs) noexcept {
  539. return __lhs.__compare(__rhs.__pn_) != 0;
  540. }
  541. friend _LIBCPP_HIDE_FROM_ABI bool operator<(const path& __lhs, const path& __rhs) noexcept {
  542. return __lhs.__compare(__rhs.__pn_) < 0;
  543. }
  544. friend _LIBCPP_HIDE_FROM_ABI bool operator<=(const path& __lhs, const path& __rhs) noexcept {
  545. return __lhs.__compare(__rhs.__pn_) <= 0;
  546. }
  547. friend _LIBCPP_HIDE_FROM_ABI bool operator>(const path& __lhs, const path& __rhs) noexcept {
  548. return __lhs.__compare(__rhs.__pn_) > 0;
  549. }
  550. friend _LIBCPP_HIDE_FROM_ABI bool operator>=(const path& __lhs, const path& __rhs) noexcept {
  551. return __lhs.__compare(__rhs.__pn_) >= 0;
  552. }
  553. # else // _LIBCPP_STD_VER <= 17
  554. friend _LIBCPP_HIDE_FROM_ABI strong_ordering operator<=>(const path& __lhs, const path& __rhs) noexcept {
  555. return __lhs.__compare(__rhs.__pn_) <=> 0;
  556. }
  557. # endif // _LIBCPP_STD_VER <= 17
  558. friend _LIBCPP_HIDE_FROM_ABI path operator/(const path& __lhs, const path& __rhs) {
  559. path __result(__lhs);
  560. __result /= __rhs;
  561. return __result;
  562. }
  563. _LIBCPP_HIDE_FROM_ABI void swap(path& __rhs) noexcept { __pn_.swap(__rhs.__pn_); }
  564. // private helper to allow reserving memory in the path
  565. _LIBCPP_HIDE_FROM_ABI void __reserve(size_t __s) { __pn_.reserve(__s); }
  566. // native format observers
  567. _LIBCPP_HIDE_FROM_ABI const string_type& native() const noexcept { return __pn_; }
  568. _LIBCPP_HIDE_FROM_ABI const value_type* c_str() const noexcept { return __pn_.c_str(); }
  569. _LIBCPP_HIDE_FROM_ABI operator string_type() const { return __pn_; }
  570. # if defined(_LIBCPP_WIN32API)
  571. _LIBCPP_HIDE_FROM_ABI std::wstring wstring() const { return __pn_; }
  572. _LIBCPP_HIDE_FROM_ABI std::wstring generic_wstring() const {
  573. std::wstring __s;
  574. __s.resize(__pn_.size());
  575. std::replace_copy(__pn_.begin(), __pn_.end(), __s.begin(), '\\', '/');
  576. return __s;
  577. }
  578. # if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
  579. template <class _ECharT, class _Traits = char_traits<_ECharT>, class _Allocator = allocator<_ECharT> >
  580. _LIBCPP_HIDE_FROM_ABI basic_string<_ECharT, _Traits, _Allocator> string(const _Allocator& __a = _Allocator()) const {
  581. using _Str = basic_string<_ECharT, _Traits, _Allocator>;
  582. _Str __s(__a);
  583. __s.reserve(__pn_.size());
  584. _PathExport<_ECharT>::__append(__s, __pn_);
  585. return __s;
  586. }
  587. _LIBCPP_HIDE_FROM_ABI std::string string() const { return string<char>(); }
  588. _LIBCPP_HIDE_FROM_ABI __u8_string u8string() const {
  589. using _CVT = __narrow_to_utf8<sizeof(wchar_t) * __CHAR_BIT__>;
  590. __u8_string __s;
  591. __s.reserve(__pn_.size());
  592. _CVT()(back_inserter(__s), __pn_.data(), __pn_.data() + __pn_.size());
  593. return __s;
  594. }
  595. _LIBCPP_HIDE_FROM_ABI std::u16string u16string() const { return string<char16_t>(); }
  596. _LIBCPP_HIDE_FROM_ABI std::u32string u32string() const { return string<char32_t>(); }
  597. // generic format observers
  598. template <class _ECharT, class _Traits = char_traits<_ECharT>, class _Allocator = allocator<_ECharT> >
  599. _LIBCPP_HIDE_FROM_ABI basic_string<_ECharT, _Traits, _Allocator>
  600. generic_string(const _Allocator& __a = _Allocator()) const {
  601. using _Str = basic_string<_ECharT, _Traits, _Allocator>;
  602. _Str __s = string<_ECharT, _Traits, _Allocator>(__a);
  603. // Note: This (and generic_u8string below) is slightly suboptimal as
  604. // it iterates twice over the string; once to convert it to the right
  605. // character type, and once to replace path delimiters.
  606. std::replace(__s.begin(), __s.end(), static_cast<_ECharT>('\\'), static_cast<_ECharT>('/'));
  607. return __s;
  608. }
  609. _LIBCPP_HIDE_FROM_ABI std::string generic_string() const { return generic_string<char>(); }
  610. _LIBCPP_HIDE_FROM_ABI std::u16string generic_u16string() const { return generic_string<char16_t>(); }
  611. _LIBCPP_HIDE_FROM_ABI std::u32string generic_u32string() const { return generic_string<char32_t>(); }
  612. _LIBCPP_HIDE_FROM_ABI __u8_string generic_u8string() const {
  613. __u8_string __s = u8string();
  614. std::replace(__s.begin(), __s.end(), '\\', '/');
  615. return __s;
  616. }
  617. # endif /* !_LIBCPP_HAS_NO_LOCALIZATION */
  618. # else /* _LIBCPP_WIN32API */
  619. _LIBCPP_HIDE_FROM_ABI std::string string() const { return __pn_; }
  620. # ifndef _LIBCPP_HAS_NO_CHAR8_T
  621. _LIBCPP_HIDE_FROM_ABI std::u8string u8string() const { return std::u8string(__pn_.begin(), __pn_.end()); }
  622. # else
  623. _LIBCPP_HIDE_FROM_ABI std::string u8string() const { return __pn_; }
  624. # endif
  625. # if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
  626. template <class _ECharT, class _Traits = char_traits<_ECharT>, class _Allocator = allocator<_ECharT> >
  627. _LIBCPP_HIDE_FROM_ABI basic_string<_ECharT, _Traits, _Allocator> string(const _Allocator& __a = _Allocator()) const {
  628. using _CVT = __widen_from_utf8<sizeof(_ECharT) * __CHAR_BIT__>;
  629. using _Str = basic_string<_ECharT, _Traits, _Allocator>;
  630. _Str __s(__a);
  631. __s.reserve(__pn_.size());
  632. _CVT()(std::back_inserter(__s), __pn_.data(), __pn_.data() + __pn_.size());
  633. return __s;
  634. }
  635. # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
  636. _LIBCPP_HIDE_FROM_ABI std::wstring wstring() const { return string<wchar_t>(); }
  637. # endif
  638. _LIBCPP_HIDE_FROM_ABI std::u16string u16string() const { return string<char16_t>(); }
  639. _LIBCPP_HIDE_FROM_ABI std::u32string u32string() const { return string<char32_t>(); }
  640. # endif /* !_LIBCPP_HAS_NO_LOCALIZATION */
  641. // generic format observers
  642. _LIBCPP_HIDE_FROM_ABI std::string generic_string() const { return __pn_; }
  643. # ifndef _LIBCPP_HAS_NO_CHAR8_T
  644. _LIBCPP_HIDE_FROM_ABI std::u8string generic_u8string() const { return std::u8string(__pn_.begin(), __pn_.end()); }
  645. # else
  646. _LIBCPP_HIDE_FROM_ABI std::string generic_u8string() const { return __pn_; }
  647. # endif
  648. # if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
  649. template <class _ECharT, class _Traits = char_traits<_ECharT>, class _Allocator = allocator<_ECharT> >
  650. _LIBCPP_HIDE_FROM_ABI basic_string<_ECharT, _Traits, _Allocator>
  651. generic_string(const _Allocator& __a = _Allocator()) const {
  652. return string<_ECharT, _Traits, _Allocator>(__a);
  653. }
  654. # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
  655. _LIBCPP_HIDE_FROM_ABI std::wstring generic_wstring() const { return string<wchar_t>(); }
  656. # endif
  657. _LIBCPP_HIDE_FROM_ABI std::u16string generic_u16string() const { return string<char16_t>(); }
  658. _LIBCPP_HIDE_FROM_ABI std::u32string generic_u32string() const { return string<char32_t>(); }
  659. # endif /* !_LIBCPP_HAS_NO_LOCALIZATION */
  660. # endif /* !_LIBCPP_WIN32API */
  661. private:
  662. int __compare(__string_view) const;
  663. __string_view __root_name() const;
  664. __string_view __root_directory() const;
  665. __string_view __root_path_raw() const;
  666. __string_view __relative_path() const;
  667. __string_view __parent_path() const;
  668. __string_view __filename() const;
  669. __string_view __stem() const;
  670. __string_view __extension() const;
  671. public:
  672. // compare
  673. _LIBCPP_HIDE_FROM_ABI int compare(const path& __p) const noexcept { return __compare(__p.__pn_); }
  674. _LIBCPP_HIDE_FROM_ABI int compare(const string_type& __s) const { return __compare(__s); }
  675. _LIBCPP_HIDE_FROM_ABI int compare(__string_view __s) const { return __compare(__s); }
  676. _LIBCPP_HIDE_FROM_ABI int compare(const value_type* __s) const { return __compare(__s); }
  677. // decomposition
  678. _LIBCPP_HIDE_FROM_ABI path root_name() const { return string_type(__root_name()); }
  679. _LIBCPP_HIDE_FROM_ABI path root_directory() const { return string_type(__root_directory()); }
  680. _LIBCPP_HIDE_FROM_ABI path root_path() const {
  681. # if defined(_LIBCPP_WIN32API)
  682. return string_type(__root_path_raw());
  683. # else
  684. return root_name().append(string_type(__root_directory()));
  685. # endif
  686. }
  687. _LIBCPP_HIDE_FROM_ABI path relative_path() const { return string_type(__relative_path()); }
  688. _LIBCPP_HIDE_FROM_ABI path parent_path() const { return string_type(__parent_path()); }
  689. _LIBCPP_HIDE_FROM_ABI path filename() const { return string_type(__filename()); }
  690. _LIBCPP_HIDE_FROM_ABI path stem() const { return string_type(__stem()); }
  691. _LIBCPP_HIDE_FROM_ABI path extension() const { return string_type(__extension()); }
  692. // query
  693. _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI bool empty() const noexcept { return __pn_.empty(); }
  694. _LIBCPP_HIDE_FROM_ABI bool has_root_name() const { return !__root_name().empty(); }
  695. _LIBCPP_HIDE_FROM_ABI bool has_root_directory() const { return !__root_directory().empty(); }
  696. _LIBCPP_HIDE_FROM_ABI bool has_root_path() const { return !__root_path_raw().empty(); }
  697. _LIBCPP_HIDE_FROM_ABI bool has_relative_path() const { return !__relative_path().empty(); }
  698. _LIBCPP_HIDE_FROM_ABI bool has_parent_path() const { return !__parent_path().empty(); }
  699. _LIBCPP_HIDE_FROM_ABI bool has_filename() const { return !__filename().empty(); }
  700. _LIBCPP_HIDE_FROM_ABI bool has_stem() const { return !__stem().empty(); }
  701. _LIBCPP_HIDE_FROM_ABI bool has_extension() const { return !__extension().empty(); }
  702. _LIBCPP_HIDE_FROM_ABI bool is_absolute() const {
  703. # if defined(_LIBCPP_WIN32API)
  704. __string_view __root_name_str = __root_name();
  705. __string_view __root_dir = __root_directory();
  706. if (__root_name_str.size() == 2 && __root_name_str[1] == ':') {
  707. // A drive letter with no root directory is relative, e.g. x:example.
  708. return !__root_dir.empty();
  709. }
  710. // If no root name, it's relative, e.g. \example is relative to the current drive
  711. if (__root_name_str.empty())
  712. return false;
  713. if (__root_name_str.size() < 3)
  714. return false;
  715. // A server root name, like \\server, is always absolute
  716. if (__root_name_str[0] != '/' && __root_name_str[0] != '\\')
  717. return false;
  718. if (__root_name_str[1] != '/' && __root_name_str[1] != '\\')
  719. return false;
  720. // Seems to be a server root name
  721. return true;
  722. # else
  723. return has_root_directory();
  724. # endif
  725. }
  726. _LIBCPP_HIDE_FROM_ABI bool is_relative() const { return !is_absolute(); }
  727. // relative paths
  728. path lexically_normal() const;
  729. path lexically_relative(const path& __base) const;
  730. _LIBCPP_HIDE_FROM_ABI path lexically_proximate(const path& __base) const {
  731. path __result = this->lexically_relative(__base);
  732. if (__result.native().empty())
  733. return *this;
  734. return __result;
  735. }
  736. // iterators
  737. class _LIBCPP_EXPORTED_FROM_ABI iterator;
  738. typedef iterator const_iterator;
  739. iterator begin() const;
  740. iterator end() const;
  741. # if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
  742. template <
  743. class _CharT,
  744. class _Traits,
  745. __enable_if_t<is_same<_CharT, value_type>::value && is_same<_Traits, char_traits<value_type> >::value, int> = 0>
  746. _LIBCPP_HIDE_FROM_ABI friend basic_ostream<_CharT, _Traits>&
  747. operator<<(basic_ostream<_CharT, _Traits>& __os, const path& __p) {
  748. __os << std::__quoted(__p.native());
  749. return __os;
  750. }
  751. template <
  752. class _CharT,
  753. class _Traits,
  754. __enable_if_t<!is_same<_CharT, value_type>::value || !is_same<_Traits, char_traits<value_type> >::value, int> = 0>
  755. _LIBCPP_HIDE_FROM_ABI friend basic_ostream<_CharT, _Traits>&
  756. operator<<(basic_ostream<_CharT, _Traits>& __os, const path& __p) {
  757. __os << std::__quoted(__p.string<_CharT, _Traits>());
  758. return __os;
  759. }
  760. template <class _CharT, class _Traits>
  761. _LIBCPP_HIDE_FROM_ABI friend basic_istream<_CharT, _Traits>&
  762. operator>>(basic_istream<_CharT, _Traits>& __is, path& __p) {
  763. basic_string<_CharT, _Traits> __tmp;
  764. __is >> std::__quoted(__tmp);
  765. __p = __tmp;
  766. return __is;
  767. }
  768. # endif // !_LIBCPP_HAS_NO_LOCALIZATION
  769. private:
  770. inline _LIBCPP_HIDE_FROM_ABI path& __assign_view(__string_view const& __s) {
  771. __pn_ = string_type(__s);
  772. return *this;
  773. }
  774. string_type __pn_;
  775. };
  776. inline _LIBCPP_HIDE_FROM_ABI void swap(path& __lhs, path& __rhs) noexcept { __lhs.swap(__rhs); }
  777. _LIBCPP_EXPORTED_FROM_ABI size_t hash_value(const path& __p) noexcept;
  778. _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_POP
  779. _LIBCPP_END_NAMESPACE_FILESYSTEM
  780. _LIBCPP_BEGIN_NAMESPACE_STD
  781. template <>
  782. struct _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY hash<filesystem::path> : __unary_function<filesystem::path, size_t> {
  783. _LIBCPP_HIDE_FROM_ABI size_t operator()(filesystem::path const& __p) const noexcept {
  784. return filesystem::hash_value(__p);
  785. }
  786. };
  787. _LIBCPP_END_NAMESPACE_STD
  788. #endif // _LIBCPP_STD_VER >= 17
  789. _LIBCPP_POP_MACROS
  790. #endif // _LIBCPP___FILESYSTEM_PATH_H