Path: blob/main/contrib/llvm-project/libcxx/include/__filesystem/path.h
35262 views
// -*- C++ -*-1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//89#ifndef _LIBCPP___FILESYSTEM_PATH_H10#define _LIBCPP___FILESYSTEM_PATH_H1112#include <__algorithm/replace.h>13#include <__algorithm/replace_copy.h>14#include <__config>15#include <__functional/unary_function.h>16#include <__fwd/functional.h>17#include <__iterator/back_insert_iterator.h>18#include <__iterator/iterator_traits.h>19#include <__type_traits/decay.h>20#include <__type_traits/is_pointer.h>21#include <__type_traits/remove_const.h>22#include <__type_traits/remove_pointer.h>23#include <cstddef>24#include <string>25#include <string_view>2627#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)28# include <iomanip> // for quoted29# include <locale>30#endif3132#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)33# pragma GCC system_header34#endif3536_LIBCPP_PUSH_MACROS37#include <__undef_macros>3839#if _LIBCPP_STD_VER >= 174041_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM4243_LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_PUSH4445template <class _Tp>46struct __can_convert_char {47static 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> {53static const bool value = true;54using __char_type = char;55};56template <>57struct __can_convert_char<wchar_t> {58static const bool value = true;59using __char_type = wchar_t;60};61# ifndef _LIBCPP_HAS_NO_CHAR8_T62template <>63struct __can_convert_char<char8_t> {64static const bool value = true;65using __char_type = char8_t;66};67# endif68template <>69struct __can_convert_char<char16_t> {70static const bool value = true;71using __char_type = char16_t;72};73template <>74struct __can_convert_char<char32_t> {75static const bool value = true;76using __char_type = char32_t;77};7879template <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)82return __e == _ECharT('/') || __e == _ECharT('\\');83# else84return __e == _ECharT('/');85# endif86}8788# ifndef _LIBCPP_HAS_NO_CHAR8_T89typedef u8string __u8_string;90# else91typedef string __u8_string;92# endif9394struct _NullSentinel {};9596template <class _Tp>97using _Void = void;9899template <class _Tp, class = void>100struct __is_pathable_string : public false_type {};101102template <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> {106using _Str = basic_string<_ECharT, _Traits, _Alloc>;107108_LIBCPP_HIDE_FROM_ABI static _ECharT const* __range_begin(_Str const& __s) { return __s.data(); }109110_LIBCPP_HIDE_FROM_ABI static _ECharT const* __range_end(_Str const& __s) { return __s.data() + __s.length(); }111112_LIBCPP_HIDE_FROM_ABI static _ECharT __first_or_null(_Str const& __s) { return __s.empty() ? _ECharT{} : __s[0]; }113};114115template <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> {119using _Str = basic_string_view<_ECharT, _Traits>;120121_LIBCPP_HIDE_FROM_ABI static _ECharT const* __range_begin(_Str const& __s) { return __s.data(); }122123_LIBCPP_HIDE_FROM_ABI static _ECharT const* __range_end(_Str const& __s) { return __s.data() + __s.length(); }124125_LIBCPP_HIDE_FROM_ABI static _ECharT __first_or_null(_Str const& __s) { return __s.empty() ? _ECharT{} : __s[0]; }126};127128template <class _Source,129class _DS = __decay_t<_Source>,130class _UnqualPtrType = __remove_const_t<__remove_pointer_t<_DS> >,131bool _IsCharPtr = is_pointer<_DS>::value && __can_convert_char<_UnqualPtrType>::value>132struct __is_pathable_char_array : false_type {};133134template <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; }137138_LIBCPP_HIDE_FROM_ABI static _ECharT const* __range_end(const _ECharT* __b) {139using _Iter = const _ECharT*;140const _ECharT __sentinel = _ECharT{};141_Iter __e = __b;142for (; *__e != __sentinel; ++__e)143;144return __e;145}146147_LIBCPP_HIDE_FROM_ABI static _ECharT __first_or_null(const _ECharT* __b) { return *__b; }148};149150template <class _Iter, bool _IsIt = __has_input_iterator_category<_Iter>::value, class = void>151struct __is_pathable_iter : false_type {};152153template <class _Iter>154struct __is_pathable_iter<155_Iter,156true,157_Void<typename __can_convert_char< typename iterator_traits<_Iter>::value_type>::__char_type> >158: __can_convert_char<typename iterator_traits<_Iter>::value_type> {159using _ECharT = typename iterator_traits<_Iter>::value_type;160161_LIBCPP_HIDE_FROM_ABI static _Iter __range_begin(_Iter __b) { return __b; }162163_LIBCPP_HIDE_FROM_ABI static _NullSentinel __range_end(_Iter) { return _NullSentinel{}; }164165_LIBCPP_HIDE_FROM_ABI static _ECharT __first_or_null(_Iter __b) { return *__b; }166};167168template <class _Tp,169bool _IsStringT = __is_pathable_string<_Tp>::value,170bool _IsCharIterT = __is_pathable_char_array<_Tp>::value,171bool _IsIterT = !_IsCharIterT && __is_pathable_iter<_Tp>::value>172struct __is_pathable : false_type {173static_assert(!_IsStringT && !_IsCharIterT && !_IsIterT, "Must all be false");174};175176template <class _Tp>177struct __is_pathable<_Tp, true, false, false> : __is_pathable_string<_Tp> {};178179template <class _Tp>180struct __is_pathable<_Tp, false, true, false> : __is_pathable_char_array<_Tp> {};181182template <class _Tp>183struct __is_pathable<_Tp, false, false, true> : __is_pathable_iter<_Tp> {};184185# if defined(_LIBCPP_WIN32API)186typedef wstring __path_string;187typedef wchar_t __path_value;188# else189typedef string __path_string;190typedef char __path_value;191# endif192193# 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# endif197198template <class _ECharT>199struct _PathCVT;200201# if !defined(_LIBCPP_HAS_NO_LOCALIZATION)202template <class _ECharT>203struct _PathCVT {204static_assert(__can_convert_char<_ECharT>::value, "Char type not convertible");205206typedef __narrow_to_utf8<sizeof(_ECharT) * __CHAR_BIT__> _Narrower;207# if defined(_LIBCPP_WIN32API)208typedef __widen_from_utf8<sizeof(wchar_t) * __CHAR_BIT__> _Widener;209# endif210211_LIBCPP_HIDE_FROM_ABI static void __append_range(__path_string& __dest, _ECharT const* __b, _ECharT const* __e) {212# if defined(_LIBCPP_WIN32API)213string __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}220221template <class _Iter>222_LIBCPP_HIDE_FROM_ABI static void __append_range(__path_string& __dest, _Iter __b, _Iter __e) {223static_assert(!is_same<_Iter, _ECharT*>::value, "Call const overload");224if (__b == __e)225return;226basic_string<_ECharT> __tmp(__b, __e);227# if defined(_LIBCPP_WIN32API)228string __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}235236template <class _Iter>237_LIBCPP_HIDE_FROM_ABI static void __append_range(__path_string& __dest, _Iter __b, _NullSentinel) {238static_assert(!is_same<_Iter, _ECharT*>::value, "Call const overload");239const _ECharT __sentinel = _ECharT{};240if (*__b == __sentinel)241return;242basic_string<_ECharT> __tmp;243for (; *__b != __sentinel; ++__b)244__tmp.push_back(*__b);245# if defined(_LIBCPP_WIN32API)246string __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}253254template <class _Source>255_LIBCPP_HIDE_FROM_ABI static void __append_source(__path_string& __dest, _Source const& __s) {256using _Traits = __is_pathable<_Source>;257__append_range(__dest, _Traits::__range_begin(__s), _Traits::__range_end(__s));258}259};260# endif // !_LIBCPP_HAS_NO_LOCALIZATION261262template <>263struct _PathCVT<__path_value> {264template <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) {266for (; __b != __e; ++__b)267__dest.push_back(*__b);268}269270template <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}274275template <class _Iter>276_LIBCPP_HIDE_FROM_ABI static void __append_range(__path_string& __dest, _Iter __b, _NullSentinel) {277const char __sentinel = char{};278for (; *__b != __sentinel; ++__b)279__dest.push_back(*__b);280}281282template <class _Source>283_LIBCPP_HIDE_FROM_ABI static void __append_source(__path_string& __dest, _Source const& __s) {284using _Traits = __is_pathable<_Source>;285__append_range(__dest, _Traits::__range_begin(__s), _Traits::__range_end(__s));286}287};288289# 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) {293size_t __size = __char_to_wide(__str, nullptr, 0);294size_t __pos = __dest.size();295__dest.resize(__pos + __size);296__char_to_wide(__str, const_cast<__path_value*>(__dest.data()) + __pos, __size);297}298299template <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) {301basic_string<char> __tmp(__b, __e);302__append_string(__dest, __tmp);303}304305template <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) {307basic_string<char> __tmp(__b, __e);308__append_string(__dest, __tmp);309}310311template <class _Iter>312_LIBCPP_HIDE_FROM_ABI static void __append_range(__path_string& __dest, _Iter __b, _NullSentinel) {313const char __sentinel = char{};314basic_string<char> __tmp;315for (; *__b != __sentinel; ++__b)316__tmp.push_back(*__b);317__append_string(__dest, __tmp);318}319320template <class _Source>321_LIBCPP_HIDE_FROM_ABI static void __append_source(__path_string& __dest, _Source const& __s) {322using _Traits = __is_pathable<_Source>;323__append_range(__dest, _Traits::__range_begin(__s), _Traits::__range_end(__s));324}325};326327template <class _ECharT>328struct _PathExport {329typedef __narrow_to_utf8<sizeof(wchar_t) * __CHAR_BIT__> _Narrower;330typedef __widen_from_utf8<sizeof(_ECharT) * __CHAR_BIT__> _Widener;331332template <class _Str>333_LIBCPP_HIDE_FROM_ABI static void __append(_Str& __dest, const __path_string& __src) {334string __utf8;335_Narrower()(back_inserter(__utf8), __src.data(), __src.data() + __src.size());336_Widener()(back_inserter(__dest), __utf8.data(), __utf8.data() + __utf8.size());337}338};339340template <>341struct _PathExport<char> {342template <class _Str>343_LIBCPP_HIDE_FROM_ABI static void __append(_Str& __dest, const __path_string& __src) {344size_t __size = __wide_to_char(__src, nullptr, 0);345size_t __pos = __dest.size();346__dest.resize(__size);347__wide_to_char(__src, const_cast<char*>(__dest.data()) + __pos, __size);348}349};350351template <>352struct _PathExport<wchar_t> {353template <class _Str>354_LIBCPP_HIDE_FROM_ABI static void __append(_Str& __dest, const __path_string& __src) {355__dest.append(__src.begin(), __src.end());356}357};358359template <>360struct _PathExport<char16_t> {361template <class _Str>362_LIBCPP_HIDE_FROM_ABI static void __append(_Str& __dest, const __path_string& __src) {363__dest.append(__src.begin(), __src.end());364}365};366367# ifndef _LIBCPP_HAS_NO_CHAR8_T368template <>369struct _PathExport<char8_t> {370typedef __narrow_to_utf8<sizeof(wchar_t) * __CHAR_BIT__> _Narrower;371372template <class _Str>373_LIBCPP_HIDE_FROM_ABI static void __append(_Str& __dest, const __path_string& __src) {374_Narrower()(back_inserter(__dest), __src.data(), __src.data() + __src.size());375}376};377# endif /* !_LIBCPP_HAS_NO_CHAR8_T */378# endif /* _LIBCPP_WIN32API */379380class _LIBCPP_EXPORTED_FROM_ABI path {381template <class _SourceOrIter, class _Tp = path&>382using _EnableIfPathable = __enable_if_t<__is_pathable<_SourceOrIter>::value, _Tp>;383384template <class _Tp>385using _SourceChar = typename __is_pathable<_Tp>::__char_type;386387template <class _Tp>388using _SourceCVT = _PathCVT<_SourceChar<_Tp> >;389390public:391# if defined(_LIBCPP_WIN32API)392typedef wchar_t value_type;393static constexpr value_type preferred_separator = L'\\';394# else395typedef char value_type;396static constexpr value_type preferred_separator = '/';397# endif398typedef basic_string<value_type> string_type;399typedef basic_string_view<value_type> __string_view;400401enum format : unsigned char { auto_format, native_format, generic_format };402403// constructors and destructor404_LIBCPP_HIDE_FROM_ABI path() noexcept {}405_LIBCPP_HIDE_FROM_ABI path(const path& __p) : __pn_(__p.__pn_) {}406_LIBCPP_HIDE_FROM_ABI path(path&& __p) noexcept : __pn_(std::move(__p.__pn_)) {}407408_LIBCPP_HIDE_FROM_ABI path(string_type&& __s, format = format::auto_format) noexcept : __pn_(std::move(__s)) {}409410template <class _Source, class = _EnableIfPathable<_Source, void> >411_LIBCPP_HIDE_FROM_ABI path(const _Source& __src, format = format::auto_format) {412_SourceCVT<_Source>::__append_source(__pn_, __src);413}414415template <class _InputIt>416_LIBCPP_HIDE_FROM_ABI path(_InputIt __first, _InputIt __last, format = format::auto_format) {417typedef typename iterator_traits<_InputIt>::value_type _ItVal;418_PathCVT<_ItVal>::__append_range(__pn_, __first, __last);419}420421/*422#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)423// TODO Implement locale conversions.424template <class _Source, class = _EnableIfPathable<_Source, void> >425path(const _Source& __src, const locale& __loc, format = format::auto_format);426template <class _InputIt>427path(_InputIt __first, _InputIt _last, const locale& __loc,428format = format::auto_format);429#endif430*/431432_LIBCPP_HIDE_FROM_ABI ~path() = default;433434// assignments435_LIBCPP_HIDE_FROM_ABI path& operator=(const path& __p) {436__pn_ = __p.__pn_;437return *this;438}439440_LIBCPP_HIDE_FROM_ABI path& operator=(path&& __p) noexcept {441__pn_ = std::move(__p.__pn_);442return *this;443}444445_LIBCPP_HIDE_FROM_ABI path& operator=(string_type&& __s) noexcept {446__pn_ = std::move(__s);447return *this;448}449450_LIBCPP_HIDE_FROM_ABI path& assign(string_type&& __s) noexcept {451__pn_ = std::move(__s);452return *this;453}454455template <class _Source>456_LIBCPP_HIDE_FROM_ABI _EnableIfPathable<_Source> operator=(const _Source& __src) {457return this->assign(__src);458}459460template <class _Source>461_LIBCPP_HIDE_FROM_ABI _EnableIfPathable<_Source> assign(const _Source& __src) {462__pn_.clear();463_SourceCVT<_Source>::__append_source(__pn_, __src);464return *this;465}466467template <class _InputIt>468_LIBCPP_HIDE_FROM_ABI path& assign(_InputIt __first, _InputIt __last) {469typedef typename iterator_traits<_InputIt>::value_type _ItVal;470__pn_.clear();471_PathCVT<_ItVal>::__append_range(__pn_, __first, __last);472return *this;473}474475public:476// appends477# if defined(_LIBCPP_WIN32API)478_LIBCPP_HIDE_FROM_ABI path& operator/=(const path& __p) {479auto __p_root_name = __p.__root_name();480auto __p_root_name_size = __p_root_name.size();481if (__p.is_absolute() || (!__p_root_name.empty() && __p_root_name != __string_view(root_name().__pn_))) {482__pn_ = __p.__pn_;483return *this;484}485if (__p.has_root_directory()) {486path __root_name_str = root_name();487__pn_ = __root_name_str.native();488__pn_ += __string_view(__p.__pn_).substr(__p_root_name_size);489return *this;490}491if (has_filename() || (!has_root_directory() && is_absolute()))492__pn_ += preferred_separator;493__pn_ += __string_view(__p.__pn_).substr(__p_root_name_size);494return *this;495}496template <class _Source>497_LIBCPP_HIDE_FROM_ABI _EnableIfPathable<_Source> operator/=(const _Source& __src) {498return operator/=(path(__src));499}500501template <class _Source>502_LIBCPP_HIDE_FROM_ABI _EnableIfPathable<_Source> append(const _Source& __src) {503return operator/=(path(__src));504}505506template <class _InputIt>507_LIBCPP_HIDE_FROM_ABI path& append(_InputIt __first, _InputIt __last) {508return operator/=(path(__first, __last));509}510# else511_LIBCPP_HIDE_FROM_ABI path& operator/=(const path& __p) {512if (__p.is_absolute()) {513__pn_ = __p.__pn_;514return *this;515}516if (has_filename())517__pn_ += preferred_separator;518__pn_ += __p.native();519return *this;520}521522// FIXME: Use _LIBCPP_DIAGNOSE_WARNING to produce a diagnostic when __src523// is known at compile time to be "/' since the user almost certainly intended524// to append a separator instead of overwriting the path with "/"525template <class _Source>526_LIBCPP_HIDE_FROM_ABI _EnableIfPathable<_Source> operator/=(const _Source& __src) {527return this->append(__src);528}529530template <class _Source>531_LIBCPP_HIDE_FROM_ABI _EnableIfPathable<_Source> append(const _Source& __src) {532using _Traits = __is_pathable<_Source>;533using _CVT = _PathCVT<_SourceChar<_Source> >;534bool __source_is_absolute = filesystem::__is_separator(_Traits::__first_or_null(__src));535if (__source_is_absolute)536__pn_.clear();537else if (has_filename())538__pn_ += preferred_separator;539_CVT::__append_source(__pn_, __src);540return *this;541}542543template <class _InputIt>544_LIBCPP_HIDE_FROM_ABI path& append(_InputIt __first, _InputIt __last) {545typedef typename iterator_traits<_InputIt>::value_type _ItVal;546static_assert(__can_convert_char<_ItVal>::value, "Must convertible");547using _CVT = _PathCVT<_ItVal>;548if (__first != __last && filesystem::__is_separator(*__first))549__pn_.clear();550else if (has_filename())551__pn_ += preferred_separator;552_CVT::__append_range(__pn_, __first, __last);553return *this;554}555# endif556557// concatenation558_LIBCPP_HIDE_FROM_ABI path& operator+=(const path& __x) {559__pn_ += __x.__pn_;560return *this;561}562563_LIBCPP_HIDE_FROM_ABI path& operator+=(const string_type& __x) {564__pn_ += __x;565return *this;566}567568_LIBCPP_HIDE_FROM_ABI path& operator+=(__string_view __x) {569__pn_ += __x;570return *this;571}572573_LIBCPP_HIDE_FROM_ABI path& operator+=(const value_type* __x) {574__pn_ += __x;575return *this;576}577578_LIBCPP_HIDE_FROM_ABI path& operator+=(value_type __x) {579__pn_ += __x;580return *this;581}582583template <class _ECharT, __enable_if_t<__can_convert_char<_ECharT>::value, int> = 0>584_LIBCPP_HIDE_FROM_ABI path& operator+=(_ECharT __x) {585_PathCVT<_ECharT>::__append_source(__pn_, basic_string_view<_ECharT>(&__x, 1));586return *this;587}588589template <class _Source>590_LIBCPP_HIDE_FROM_ABI _EnableIfPathable<_Source> operator+=(const _Source& __x) {591return this->concat(__x);592}593594template <class _Source>595_LIBCPP_HIDE_FROM_ABI _EnableIfPathable<_Source> concat(const _Source& __x) {596_SourceCVT<_Source>::__append_source(__pn_, __x);597return *this;598}599600template <class _InputIt>601_LIBCPP_HIDE_FROM_ABI path& concat(_InputIt __first, _InputIt __last) {602typedef typename iterator_traits<_InputIt>::value_type _ItVal;603_PathCVT<_ItVal>::__append_range(__pn_, __first, __last);604return *this;605}606607// modifiers608_LIBCPP_HIDE_FROM_ABI void clear() noexcept { __pn_.clear(); }609610_LIBCPP_HIDE_FROM_ABI path& make_preferred() {611# if defined(_LIBCPP_WIN32API)612std::replace(__pn_.begin(), __pn_.end(), L'/', L'\\');613# endif614return *this;615}616617_LIBCPP_HIDE_FROM_ABI path& remove_filename() {618auto __fname = __filename();619if (!__fname.empty())620__pn_.erase(__fname.data() - __pn_.data());621return *this;622}623624_LIBCPP_HIDE_FROM_ABI path& replace_filename(const path& __replacement) {625remove_filename();626return (*this /= __replacement);627}628629path& replace_extension(const path& __replacement = path());630631friend _LIBCPP_HIDE_FROM_ABI bool operator==(const path& __lhs, const path& __rhs) noexcept {632return __lhs.__compare(__rhs.__pn_) == 0;633}634# if _LIBCPP_STD_VER <= 17635friend _LIBCPP_HIDE_FROM_ABI bool operator!=(const path& __lhs, const path& __rhs) noexcept {636return __lhs.__compare(__rhs.__pn_) != 0;637}638friend _LIBCPP_HIDE_FROM_ABI bool operator<(const path& __lhs, const path& __rhs) noexcept {639return __lhs.__compare(__rhs.__pn_) < 0;640}641friend _LIBCPP_HIDE_FROM_ABI bool operator<=(const path& __lhs, const path& __rhs) noexcept {642return __lhs.__compare(__rhs.__pn_) <= 0;643}644friend _LIBCPP_HIDE_FROM_ABI bool operator>(const path& __lhs, const path& __rhs) noexcept {645return __lhs.__compare(__rhs.__pn_) > 0;646}647friend _LIBCPP_HIDE_FROM_ABI bool operator>=(const path& __lhs, const path& __rhs) noexcept {648return __lhs.__compare(__rhs.__pn_) >= 0;649}650# else // _LIBCPP_STD_VER <= 17651friend _LIBCPP_HIDE_FROM_ABI strong_ordering operator<=>(const path& __lhs, const path& __rhs) noexcept {652return __lhs.__compare(__rhs.__pn_) <=> 0;653}654# endif // _LIBCPP_STD_VER <= 17655656friend _LIBCPP_HIDE_FROM_ABI path operator/(const path& __lhs, const path& __rhs) {657path __result(__lhs);658__result /= __rhs;659return __result;660}661662_LIBCPP_HIDE_FROM_ABI void swap(path& __rhs) noexcept { __pn_.swap(__rhs.__pn_); }663664// private helper to allow reserving memory in the path665_LIBCPP_HIDE_FROM_ABI void __reserve(size_t __s) { __pn_.reserve(__s); }666667// native format observers668_LIBCPP_HIDE_FROM_ABI const string_type& native() const noexcept { return __pn_; }669670_LIBCPP_HIDE_FROM_ABI const value_type* c_str() const noexcept { return __pn_.c_str(); }671672_LIBCPP_HIDE_FROM_ABI operator string_type() const { return __pn_; }673674# if defined(_LIBCPP_WIN32API)675_LIBCPP_HIDE_FROM_ABI std::wstring wstring() const { return __pn_; }676677_LIBCPP_HIDE_FROM_ABI std::wstring generic_wstring() const {678std::wstring __s;679__s.resize(__pn_.size());680std::replace_copy(__pn_.begin(), __pn_.end(), __s.begin(), '\\', '/');681return __s;682}683684# if !defined(_LIBCPP_HAS_NO_LOCALIZATION)685template <class _ECharT, class _Traits = char_traits<_ECharT>, class _Allocator = allocator<_ECharT> >686_LIBCPP_HIDE_FROM_ABI basic_string<_ECharT, _Traits, _Allocator> string(const _Allocator& __a = _Allocator()) const {687using _Str = basic_string<_ECharT, _Traits, _Allocator>;688_Str __s(__a);689__s.reserve(__pn_.size());690_PathExport<_ECharT>::__append(__s, __pn_);691return __s;692}693694_LIBCPP_HIDE_FROM_ABI std::string string() const { return string<char>(); }695_LIBCPP_HIDE_FROM_ABI __u8_string u8string() const {696using _CVT = __narrow_to_utf8<sizeof(wchar_t) * __CHAR_BIT__>;697__u8_string __s;698__s.reserve(__pn_.size());699_CVT()(back_inserter(__s), __pn_.data(), __pn_.data() + __pn_.size());700return __s;701}702703_LIBCPP_HIDE_FROM_ABI std::u16string u16string() const { return string<char16_t>(); }704_LIBCPP_HIDE_FROM_ABI std::u32string u32string() const { return string<char32_t>(); }705706// generic format observers707template <class _ECharT, class _Traits = char_traits<_ECharT>, class _Allocator = allocator<_ECharT> >708_LIBCPP_HIDE_FROM_ABI basic_string<_ECharT, _Traits, _Allocator>709generic_string(const _Allocator& __a = _Allocator()) const {710using _Str = basic_string<_ECharT, _Traits, _Allocator>;711_Str __s = string<_ECharT, _Traits, _Allocator>(__a);712// Note: This (and generic_u8string below) is slightly suboptimal as713// it iterates twice over the string; once to convert it to the right714// character type, and once to replace path delimiters.715std::replace(__s.begin(), __s.end(), static_cast<_ECharT>('\\'), static_cast<_ECharT>('/'));716return __s;717}718719_LIBCPP_HIDE_FROM_ABI std::string generic_string() const { return generic_string<char>(); }720_LIBCPP_HIDE_FROM_ABI std::u16string generic_u16string() const { return generic_string<char16_t>(); }721_LIBCPP_HIDE_FROM_ABI std::u32string generic_u32string() const { return generic_string<char32_t>(); }722_LIBCPP_HIDE_FROM_ABI __u8_string generic_u8string() const {723__u8_string __s = u8string();724std::replace(__s.begin(), __s.end(), '\\', '/');725return __s;726}727# endif /* !_LIBCPP_HAS_NO_LOCALIZATION */728# else /* _LIBCPP_WIN32API */729730_LIBCPP_HIDE_FROM_ABI std::string string() const { return __pn_; }731# ifndef _LIBCPP_HAS_NO_CHAR8_T732_LIBCPP_HIDE_FROM_ABI std::u8string u8string() const { return std::u8string(__pn_.begin(), __pn_.end()); }733# else734_LIBCPP_HIDE_FROM_ABI std::string u8string() const { return __pn_; }735# endif736737# if !defined(_LIBCPP_HAS_NO_LOCALIZATION)738template <class _ECharT, class _Traits = char_traits<_ECharT>, class _Allocator = allocator<_ECharT> >739_LIBCPP_HIDE_FROM_ABI basic_string<_ECharT, _Traits, _Allocator> string(const _Allocator& __a = _Allocator()) const {740using _CVT = __widen_from_utf8<sizeof(_ECharT) * __CHAR_BIT__>;741using _Str = basic_string<_ECharT, _Traits, _Allocator>;742_Str __s(__a);743__s.reserve(__pn_.size());744_CVT()(std::back_inserter(__s), __pn_.data(), __pn_.data() + __pn_.size());745return __s;746}747748# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS749_LIBCPP_HIDE_FROM_ABI std::wstring wstring() const { return string<wchar_t>(); }750# endif751_LIBCPP_HIDE_FROM_ABI std::u16string u16string() const { return string<char16_t>(); }752_LIBCPP_HIDE_FROM_ABI std::u32string u32string() const { return string<char32_t>(); }753# endif /* !_LIBCPP_HAS_NO_LOCALIZATION */754755// generic format observers756_LIBCPP_HIDE_FROM_ABI std::string generic_string() const { return __pn_; }757# ifndef _LIBCPP_HAS_NO_CHAR8_T758_LIBCPP_HIDE_FROM_ABI std::u8string generic_u8string() const { return std::u8string(__pn_.begin(), __pn_.end()); }759# else760_LIBCPP_HIDE_FROM_ABI std::string generic_u8string() const { return __pn_; }761# endif762763# if !defined(_LIBCPP_HAS_NO_LOCALIZATION)764template <class _ECharT, class _Traits = char_traits<_ECharT>, class _Allocator = allocator<_ECharT> >765_LIBCPP_HIDE_FROM_ABI basic_string<_ECharT, _Traits, _Allocator>766generic_string(const _Allocator& __a = _Allocator()) const {767return string<_ECharT, _Traits, _Allocator>(__a);768}769770# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS771_LIBCPP_HIDE_FROM_ABI std::wstring generic_wstring() const { return string<wchar_t>(); }772# endif773_LIBCPP_HIDE_FROM_ABI std::u16string generic_u16string() const { return string<char16_t>(); }774_LIBCPP_HIDE_FROM_ABI std::u32string generic_u32string() const { return string<char32_t>(); }775# endif /* !_LIBCPP_HAS_NO_LOCALIZATION */776# endif /* !_LIBCPP_WIN32API */777778private:779int __compare(__string_view) const;780__string_view __root_name() const;781__string_view __root_directory() const;782__string_view __root_path_raw() const;783__string_view __relative_path() const;784__string_view __parent_path() const;785__string_view __filename() const;786__string_view __stem() const;787__string_view __extension() const;788789public:790// compare791_LIBCPP_HIDE_FROM_ABI int compare(const path& __p) const noexcept { return __compare(__p.__pn_); }792_LIBCPP_HIDE_FROM_ABI int compare(const string_type& __s) const { return __compare(__s); }793_LIBCPP_HIDE_FROM_ABI int compare(__string_view __s) const { return __compare(__s); }794_LIBCPP_HIDE_FROM_ABI int compare(const value_type* __s) const { return __compare(__s); }795796// decomposition797_LIBCPP_HIDE_FROM_ABI path root_name() const { return string_type(__root_name()); }798_LIBCPP_HIDE_FROM_ABI path root_directory() const { return string_type(__root_directory()); }799_LIBCPP_HIDE_FROM_ABI path root_path() const {800# if defined(_LIBCPP_WIN32API)801return string_type(__root_path_raw());802# else803return root_name().append(string_type(__root_directory()));804# endif805}806_LIBCPP_HIDE_FROM_ABI path relative_path() const { return string_type(__relative_path()); }807_LIBCPP_HIDE_FROM_ABI path parent_path() const { return string_type(__parent_path()); }808_LIBCPP_HIDE_FROM_ABI path filename() const { return string_type(__filename()); }809_LIBCPP_HIDE_FROM_ABI path stem() const { return string_type(__stem()); }810_LIBCPP_HIDE_FROM_ABI path extension() const { return string_type(__extension()); }811812// query813_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI bool empty() const noexcept { return __pn_.empty(); }814815_LIBCPP_HIDE_FROM_ABI bool has_root_name() const { return !__root_name().empty(); }816_LIBCPP_HIDE_FROM_ABI bool has_root_directory() const { return !__root_directory().empty(); }817_LIBCPP_HIDE_FROM_ABI bool has_root_path() const { return !__root_path_raw().empty(); }818_LIBCPP_HIDE_FROM_ABI bool has_relative_path() const { return !__relative_path().empty(); }819_LIBCPP_HIDE_FROM_ABI bool has_parent_path() const { return !__parent_path().empty(); }820_LIBCPP_HIDE_FROM_ABI bool has_filename() const { return !__filename().empty(); }821_LIBCPP_HIDE_FROM_ABI bool has_stem() const { return !__stem().empty(); }822_LIBCPP_HIDE_FROM_ABI bool has_extension() const { return !__extension().empty(); }823824_LIBCPP_HIDE_FROM_ABI bool is_absolute() const {825# if defined(_LIBCPP_WIN32API)826__string_view __root_name_str = __root_name();827__string_view __root_dir = __root_directory();828if (__root_name_str.size() == 2 && __root_name_str[1] == ':') {829// A drive letter with no root directory is relative, e.g. x:example.830return !__root_dir.empty();831}832// If no root name, it's relative, e.g. \example is relative to the current drive833if (__root_name_str.empty())834return false;835if (__root_name_str.size() < 3)836return false;837// A server root name, like \\server, is always absolute838if (__root_name_str[0] != '/' && __root_name_str[0] != '\\')839return false;840if (__root_name_str[1] != '/' && __root_name_str[1] != '\\')841return false;842// Seems to be a server root name843return true;844# else845return has_root_directory();846# endif847}848_LIBCPP_HIDE_FROM_ABI bool is_relative() const { return !is_absolute(); }849850// relative paths851path lexically_normal() const;852path lexically_relative(const path& __base) const;853854_LIBCPP_HIDE_FROM_ABI path lexically_proximate(const path& __base) const {855path __result = this->lexically_relative(__base);856if (__result.native().empty())857return *this;858return __result;859}860861// iterators862class _LIBCPP_EXPORTED_FROM_ABI iterator;863typedef iterator const_iterator;864865iterator begin() const;866iterator end() const;867868# if !defined(_LIBCPP_HAS_NO_LOCALIZATION)869template <870class _CharT,871class _Traits,872__enable_if_t<is_same<_CharT, value_type>::value && is_same<_Traits, char_traits<value_type> >::value, int> = 0>873_LIBCPP_HIDE_FROM_ABI friend basic_ostream<_CharT, _Traits>&874operator<<(basic_ostream<_CharT, _Traits>& __os, const path& __p) {875__os << std::__quoted(__p.native());876return __os;877}878879template <880class _CharT,881class _Traits,882__enable_if_t<!is_same<_CharT, value_type>::value || !is_same<_Traits, char_traits<value_type> >::value, int> = 0>883_LIBCPP_HIDE_FROM_ABI friend basic_ostream<_CharT, _Traits>&884operator<<(basic_ostream<_CharT, _Traits>& __os, const path& __p) {885__os << std::__quoted(__p.string<_CharT, _Traits>());886return __os;887}888889template <class _CharT, class _Traits>890_LIBCPP_HIDE_FROM_ABI friend basic_istream<_CharT, _Traits>&891operator>>(basic_istream<_CharT, _Traits>& __is, path& __p) {892basic_string<_CharT, _Traits> __tmp;893__is >> std::__quoted(__tmp);894__p = __tmp;895return __is;896}897# endif // !_LIBCPP_HAS_NO_LOCALIZATION898899private:900inline _LIBCPP_HIDE_FROM_ABI path& __assign_view(__string_view const& __s) {901__pn_ = string_type(__s);902return *this;903}904string_type __pn_;905};906907inline _LIBCPP_HIDE_FROM_ABI void swap(path& __lhs, path& __rhs) noexcept { __lhs.swap(__rhs); }908909_LIBCPP_EXPORTED_FROM_ABI size_t hash_value(const path& __p) noexcept;910911_LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_POP912913_LIBCPP_END_NAMESPACE_FILESYSTEM914915_LIBCPP_BEGIN_NAMESPACE_STD916917template <>918struct _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY hash<filesystem::path> : __unary_function<filesystem::path, size_t> {919_LIBCPP_HIDE_FROM_ABI size_t operator()(filesystem::path const& __p) const noexcept {920return filesystem::hash_value(__p);921}922};923924_LIBCPP_END_NAMESPACE_STD925926#endif // _LIBCPP_STD_VER >= 17927928_LIBCPP_POP_MACROS929930#endif // _LIBCPP___FILESYSTEM_PATH_H931932933