brintos

brintos / llvm-project-archived public Read only

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