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