path.h 34 KB

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