path.h 32 KB

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