30 #ifndef _GLIBCXX_EXPERIMENTAL_FS_PATH_H 31 #define _GLIBCXX_EXPERIMENTAL_FS_PATH_H 1 33 #if __cplusplus < 201103L 48 #if defined(_WIN32) && !defined(__CYGWIN__) 49 # define _GLIBCXX_FILESYSTEM_IS_WINDOWS 1 53 namespace std _GLIBCXX_VISIBILITY(default)
55 namespace experimental
61 _GLIBCXX_BEGIN_NAMESPACE_VERSION
62 _GLIBCXX_BEGIN_NAMESPACE_CXX11
72 template<
typename _CharT>
75 template<
typename _Iter,
76 typename _Iter_traits = std::iterator_traits<_Iter>>
77 using __is_path_iter_src
78 = __and_<__is_encoded_char<typename _Iter_traits::value_type>,
80 typename _Iter_traits::iterator_category>>;
82 template<
typename _Iter>
83 static __is_path_iter_src<_Iter>
84 __is_path_src(_Iter,
int);
86 template<
typename _CharT,
typename _Traits,
typename _Alloc>
87 static __is_encoded_char<_CharT>
90 template<
typename _Unknown>
92 __is_path_src(
const _Unknown&, ...);
94 template<
typename _Tp1,
typename _Tp2>
95 struct __constructible_from;
97 template<
typename _Iter>
98 struct __constructible_from<_Iter, _Iter>
99 : __is_path_iter_src<_Iter>
102 template<
typename _Source>
103 struct __constructible_from<_Source, void>
104 : decltype(__is_path_src(std::declval<_Source>(), 0))
107 template<
typename _Tp1,
typename _Tp2 =
void>
108 using _Path =
typename 109 std::enable_if<__and_<__not_<is_same<_Tp1, path>>,
110 __constructible_from<_Tp1, _Tp2>>::value,
113 template<
typename _Source>
115 _S_range_begin(_Source __begin) {
return __begin; }
117 struct __null_terminated { };
119 template<
typename _Source>
120 static __null_terminated
121 _S_range_end(_Source) {
return {}; }
123 template<
typename _CharT,
typename _Traits,
typename _Alloc>
126 {
return __str.
data(); }
128 template<
typename _CharT,
typename _Traits,
typename _Alloc>
131 {
return __str.
data() + __str.
size(); }
133 template<
typename _Tp,
134 typename _Iter = decltype(_S_range_begin(std::declval<_Tp>())),
135 typename _Val =
typename std::iterator_traits<_Iter>::value_type>
136 using __value_type_is_char
137 =
typename std::enable_if<std::is_same<_Val, char>::value>::type;
140 #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS 141 typedef wchar_t value_type;
142 static constexpr value_type preferred_separator = L
'\\';
144 typedef char value_type;
145 static constexpr value_type preferred_separator =
'/';
156 : _M_pathname(std::move(__p._M_pathname)), _M_type(__p._M_type)
162 template<
typename _Source,
163 typename _Require = _Path<_Source>>
164 path(_Source
const& __source)
165 : _M_pathname(_S_convert(_S_range_begin(__source),
166 _S_range_end(__source)))
167 { _M_split_cmpts(); }
169 template<
typename _InputIterator,
170 typename _Require = _Path<_InputIterator, _InputIterator>>
171 path(_InputIterator __first, _InputIterator __last)
172 : _M_pathname(_S_convert(__first, __last))
173 { _M_split_cmpts(); }
175 template<
typename _Source,
176 typename _Require = _Path<_Source>,
177 typename _Require2 = __value_type_is_char<_Source>>
178 path(_Source
const& __source,
const locale& __loc)
179 : _M_pathname(_S_convert_loc(_S_range_begin(__source),
180 _S_range_end(__source), __loc))
181 { _M_split_cmpts(); }
183 template<
typename _InputIterator,
184 typename _Require = _Path<_InputIterator, _InputIterator>,
185 typename _Require2 = __value_type_is_char<_InputIterator>>
186 path(_InputIterator __first, _InputIterator __last,
const locale& __loc)
187 : _M_pathname(_S_convert_loc(__first, __last, __loc))
188 { _M_split_cmpts(); }
194 path& operator=(
const path& __p) =
default;
195 path& operator=(path&& __p) noexcept;
197 template<
typename _Source>
199 operator=(_Source
const& __source)
200 {
return *
this = path(__source); }
202 template<
typename _Source>
204 assign(_Source
const& __source)
205 {
return *
this = path(__source); }
207 template<
typename _InputIterator>
208 _Path<_InputIterator, _InputIterator>&
209 assign(_InputIterator __first, _InputIterator __last)
210 {
return *
this = path(__first, __last); }
214 path& operator/=(
const path& __p) {
return _M_append(__p._M_pathname); }
216 template <
class _Source>
218 operator/=(_Source
const& __source)
219 {
return append(__source); }
221 template<
typename _Source>
223 append(_Source
const& __source)
225 return _M_append(_S_convert(_S_range_begin(__source),
226 _S_range_end(__source)));
229 template<
typename _InputIterator>
230 _Path<_InputIterator, _InputIterator>&
231 append(_InputIterator __first, _InputIterator __last)
232 {
return _M_append(_S_convert(__first, __last)); }
236 path& operator+=(
const path& __x);
237 path& operator+=(
const string_type& __x);
238 path& operator+=(
const value_type* __x);
239 path& operator+=(value_type __x);
241 template<
typename _Source>
243 operator+=(_Source
const& __x) {
return concat(__x); }
245 template<
typename _CharT>
246 _Path<_CharT*, _CharT*>&
247 operator+=(_CharT __x);
249 template<
typename _Source>
251 concat(_Source
const& __x)
252 {
return *
this += _S_convert(_S_range_begin(__x), _S_range_end(__x)); }
254 template<
typename _InputIterator>
255 _Path<_InputIterator, _InputIterator>&
256 concat(_InputIterator __first, _InputIterator __last)
257 {
return *
this += _S_convert(__first, __last); }
261 void clear() noexcept { _M_pathname.clear(); _M_split_cmpts(); }
263 path& make_preferred();
264 path& remove_filename();
265 path& replace_filename(
const path& __replacement);
266 path& replace_extension(
const path& __replacement = path());
268 void swap(path& __rhs) noexcept;
272 const string_type& native()
const noexcept {
return _M_pathname; }
273 const value_type* c_str()
const noexcept {
return _M_pathname.c_str(); }
274 operator string_type()
const {
return _M_pathname; }
276 template<
typename _CharT,
typename _Traits = std::
char_traits<_CharT>,
277 typename _Allocator = std::allocator<_CharT>>
279 string(
const _Allocator& __a = _Allocator())
const;
282 #if _GLIBCXX_USE_WCHAR_T 290 template<
typename _CharT,
typename _Traits = std::
char_traits<_CharT>,
291 typename _Allocator = std::allocator<_CharT>>
293 generic_string(
const _Allocator& __a = _Allocator())
const;
296 #if _GLIBCXX_USE_WCHAR_T 305 int compare(
const path& __p)
const noexcept;
306 int compare(
const string_type& __s)
const;
307 int compare(
const value_type* __s)
const;
311 path root_name()
const;
312 path root_directory()
const;
313 path root_path()
const;
314 path relative_path()
const;
315 path parent_path()
const;
316 path filename()
const;
318 path extension()
const;
322 bool empty()
const noexcept {
return _M_pathname.empty(); }
323 bool has_root_name()
const;
324 bool has_root_directory()
const;
325 bool has_root_path()
const;
326 bool has_relative_path()
const;
327 bool has_parent_path()
const;
328 bool has_filename()
const;
329 bool has_stem()
const;
330 bool has_extension()
const;
331 bool is_absolute()
const;
332 bool is_relative()
const {
return !is_absolute(); }
342 enum class _Type : unsigned char {
343 _Multi, _Root_name, _Root_dir, _Filename
346 path(string_type __str, _Type __type) : _M_pathname(__str), _M_type(__type)
348 _GLIBCXX_DEBUG_ASSERT(!empty());
349 _GLIBCXX_DEBUG_ASSERT(_M_type != _Type::_Multi);
352 enum class _Split { _Stem, _Extension };
354 path& _M_append(
const string_type& __str)
356 if (!_M_pathname.empty() && !_S_is_dir_sep(_M_pathname.back())
357 && !__str.
empty() && !_S_is_dir_sep(__str.
front()))
358 _M_pathname += preferred_separator;
359 _M_pathname += __str;
366 template<
typename _CharT>
370 _S_convert(value_type* __src, __null_terminated)
371 {
return string_type(__src); }
374 _S_convert(
const value_type* __src, __null_terminated)
375 {
return string_type(__src); }
377 template<
typename _Iter>
379 _S_convert(_Iter __first, _Iter __last)
381 using __value_type =
typename std::iterator_traits<_Iter>::value_type;
382 return _Cvt<__value_type>::_S_convert(__first, __last);
385 template<
typename _InputIterator>
387 _S_convert(_InputIterator __src, __null_terminated)
389 using _Tp =
typename std::iterator_traits<_InputIterator>::value_type;
391 while (*__src != _Tp{})
393 return _S_convert(__tmp.
data(), __tmp.
data() + __tmp.
size());
397 _S_convert_loc(
const char* __first,
const char* __last,
400 template<
typename _Iter>
402 _S_convert_loc(_Iter __first, _Iter __last,
const std::locale& __loc)
405 return _S_convert_loc(__str.
data(), __str.
data()+__str.
size(), __loc);
408 template<
typename _InputIterator>
410 _S_convert_loc(_InputIterator __src, __null_terminated,
414 while (*__src !=
'\0')
416 return _S_convert_loc(__tmp.
data(), __tmp.
data()+__tmp.
size(), __loc);
419 bool _S_is_dir_sep(value_type __ch)
421 #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS 422 return __ch == L
'/' || __ch == preferred_separator;
428 void _M_split_cmpts();
430 void _M_add_root_name(
size_t __n);
431 void _M_add_root_dir(
size_t __pos);
432 void _M_add_filename(
size_t __pos,
size_t __n);
434 string_type _M_pathname;
437 using _List = _GLIBCXX_STD_C::vector<_Cmpt>;
439 _Type _M_type = _Type::_Multi;
442 inline void swap(
path& __lhs,
path& __rhs) noexcept { __lhs.swap(__rhs); }
447 inline bool operator<(
const path& __lhs,
const path& __rhs) noexcept
448 {
return __lhs.compare(__rhs) < 0; }
451 inline bool operator<=(
const path& __lhs,
const path& __rhs) noexcept
452 {
return !(__rhs < __lhs); }
455 inline bool operator>(
const path& __lhs,
const path& __rhs) noexcept
456 {
return __rhs < __lhs; }
459 inline bool operator>=(
const path& __lhs,
const path& __rhs) noexcept
460 {
return !(__lhs < __rhs); }
463 inline bool operator==(
const path& __lhs,
const path& __rhs) noexcept
464 {
return __lhs.compare(__rhs) == 0; }
467 inline bool operator!=(
const path& __lhs,
const path& __rhs) noexcept
468 {
return !(__lhs == __rhs); }
472 {
return path(__lhs) /= __rhs; }
475 template<
typename _CharT,
typename _Traits>
477 operator<<(basic_ostream<_CharT, _Traits>& __os,
const path& __p)
479 auto __tmp = __p.string<_CharT, _Traits>();
480 using __quoted_string
482 __os << __quoted_string{__tmp,
'"',
'\\'};
487 template<
typename _CharT,
typename _Traits>
492 using __quoted_string
494 if (__is >> __quoted_string{ __tmp,
'"',
'\\' })
495 __p = std::move(__tmp);
500 template<
typename _Source>
504 #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS 507 return path{ __source };
512 template<
typename _InputIterator>
514 u8path(_InputIterator __first, _InputIterator __last)
516 #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS 519 return path{ __first, __last };
526 filesystem_error(
const string& __what_arg,
error_code __ec)
529 filesystem_error(
const string& __what_arg,
const path& __p1,
533 filesystem_error(
const string& __what_arg,
const path& __p1,
535 :
system_error(__ec, __what_arg), _M_path1(__p1), _M_path2(__p2)
540 const path& path1()
const noexcept {
return _M_path1; }
541 const path& path2()
const noexcept {
return _M_path2; }
542 const char* what()
const noexcept {
return _M_what.c_str(); }
554 {
using value_type = char; };
558 {
using value_type = wchar_t; };
562 {
using value_type = char16_t; };
566 {
using value_type = char32_t; };
568 struct path::_Cmpt :
path 570 _Cmpt(string_type __s, _Type __t,
size_t __pos)
571 :
path(std::move(__s), __t), _M_pos(__pos) { }
573 _Cmpt() : _M_pos(-1) { }
580 struct path::_Cvt<path::value_type>
582 template<
typename _Iter>
584 _S_convert(_Iter __first, _Iter __last)
585 {
return string_type{__first, __last}; }
588 template<
typename _CharT>
591 #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS 593 _S_wconvert(
const char* __f,
const char* __l,
true_type)
596 const auto& __cvt = std::use_facet<_Cvt>(
std::locale{});
598 if (__str_codecvt_in(__f, __l, __wstr, __cvt))
600 _GLIBCXX_THROW_OR_ABORT(filesystem_error(
601 "Cannot convert character sequence",
602 std::make_error_code(errc::illegal_byte_sequence)));
606 _S_wconvert(
const _CharT* __f,
const _CharT* __l,
false_type)
608 std::codecvt_utf8<_CharT> __cvt;
610 if (__str_codecvt_out(__f, __l, __str, __cvt))
612 const char* __f2 = __str.
data();
613 const char* __l2 = __f2 + __str.
size();
614 std::codecvt_utf8<wchar_t> __wcvt;
616 if (__str_codecvt_in(__f2, __l2, __wstr, __wcvt))
619 _GLIBCXX_THROW_OR_ABORT(filesystem_error(
620 "Cannot convert character sequence",
621 std::make_error_code(errc::illegal_byte_sequence)));
625 _S_convert(
const _CharT* __f,
const _CharT* __l)
627 return _S_wconvert(__f, __l, is_same<_CharT, char>{});
631 _S_convert(
const _CharT* __f,
const _CharT* __l)
633 std::codecvt_utf8<_CharT> __cvt;
635 if (__str_codecvt_out(__f, __l, __str, __cvt))
637 _GLIBCXX_THROW_OR_ABORT(filesystem_error(
638 "Cannot convert character sequence",
639 std::make_error_code(errc::illegal_byte_sequence)));
644 _S_convert(_CharT* __f, _CharT* __l)
646 return _S_convert(const_cast<const _CharT*>(__f),
647 const_cast<const _CharT*>(__l));
650 template<
typename _Iter>
652 _S_convert(_Iter __first, _Iter __last)
655 return _S_convert(__str.
data(), __str.
data() + __str.
size());
658 template<
typename _Iter,
typename _Cont>
660 _S_convert(__gnu_cxx::__normal_iterator<_Iter, _Cont> __first,
661 __gnu_cxx::__normal_iterator<_Iter, _Cont> __last)
662 {
return _S_convert(__first.base(), __last.base()); }
669 using difference_type = std::ptrdiff_t;
675 iterator() : _M_path(
nullptr), _M_cur(), _M_at_end() { }
684 iterator operator++(
int) {
auto __tmp = *
this; ++_M_cur;
return __tmp; }
687 iterator operator--(
int) {
auto __tmp = *
this; --_M_cur;
return __tmp; }
690 {
return __lhs._M_equals(__rhs); }
693 {
return !__lhs._M_equals(__rhs); }
698 iterator(
const path* __path, path::_List::const_iterator __iter)
699 : _M_path(__path), _M_cur(__iter), _M_at_end()
702 iterator(
const path* __path,
bool __at_end)
703 : _M_path(__path), _M_cur(), _M_at_end(__at_end)
709 path::_List::const_iterator _M_cur;
715 path::operator=(path&& __p) noexcept
717 _M_pathname = std::move(__p._M_pathname);
718 _M_cmpts = std::move(__p._M_cmpts);
719 _M_type = __p._M_type;
725 path::operator+=(
const path& __p)
727 return operator+=(__p.native());
754 template<
typename _CharT>
755 inline path::_Path<_CharT*, _CharT*>&
756 path::operator+=(_CharT __x)
759 return concat(__addr, __addr + 1);
763 path::make_preferred()
765 #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS 766 std::replace(_M_pathname.begin(), _M_pathname.end(), L
'/',
767 preferred_separator);
772 inline void path::swap(path& __rhs) noexcept
774 _M_pathname.swap(__rhs._M_pathname);
775 _M_cmpts.swap(__rhs._M_cmpts);
776 std::swap(_M_type, __rhs._M_type);
779 template<
typename _CharT,
typename _Traits,
typename _Allocator>
783 if (is_same<_CharT, value_type>::value)
784 return { _M_pathname.
begin(), _M_pathname.end(), __a };
786 const value_type* __first = _M_pathname.data();
787 const value_type* __last = __first + _M_pathname.size();
789 #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS 790 using _CharAlloc = __alloc_rebind<_Allocator, char>;
795 codecvt_utf8<value_type> __cvt;
796 _String __u8str{_CharAlloc{__a}};
797 if (__str_codecvt_out(__first, __last, __u8str, __cvt))
802 operator()(
const _String& __from, _String&,
true_type)
806 operator()(
const _String& __from, _WString& __to,
false_type)
809 codecvt_utf8<_CharT> __cvt;
810 const char* __f = __from.data();
811 const char* __l = __f + __from.size();
812 if (__str_codecvt_in(__f, __l, __to, __cvt))
818 if (
auto* __p = __dispatch(__u8str, __wstr, is_same<_CharT, char>{}))
822 codecvt_utf8<_CharT> __cvt;
824 if (__str_codecvt_in(__first, __last, __wstr, __cvt))
827 _GLIBCXX_THROW_OR_ABORT(filesystem_error(
828 "Cannot convert character sequence",
829 std::make_error_code(errc::illegal_byte_sequence)));
835 #if _GLIBCXX_USE_WCHAR_T 841 path::u8string()
const 843 #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS 846 codecvt_utf8<value_type> __cvt;
847 const value_type* __first = _M_pathname.data();
848 const value_type* __last = __first + _M_pathname.size();
849 if (__str_codecvt_out(__first, __last, __str, __cvt))
851 _GLIBCXX_THROW_OR_ABORT(filesystem_error(
852 "Cannot convert character sequence",
853 std::make_error_code(errc::illegal_byte_sequence)));
865 #ifndef _GLIBCXX_FILESYSTEM_IS_WINDOWS 866 template<
typename _CharT,
typename _Traits,
typename _Allocator>
868 path::generic_string(
const _Allocator& __a)
const 872 path::generic_string()
const {
return string(); }
874 #if _GLIBCXX_USE_WCHAR_T 876 path::generic_wstring()
const {
return wstring(); }
880 path::generic_u8string()
const {
return u8string(); }
883 path::generic_u16string()
const {
return u16string(); }
886 path::generic_u32string()
const {
return u32string(); }
890 path::compare(
const string_type& __s)
const {
return compare(path(__s)); }
893 path::compare(
const value_type* __s)
const {
return compare(path(__s)); }
896 path::filename()
const {
return empty() ? path() : *--
end(); }
901 auto ext = _M_find_extension();
902 if (ext.first && ext.second != 0)
903 return path{ext.first->substr(0, ext.second)};
908 path::extension()
const 910 auto ext = _M_find_extension();
912 return path{ext.first->substr(ext.second)};
917 path::has_stem()
const 919 auto ext = _M_find_extension();
920 return ext.first && ext.second != 0;
924 path::has_extension()
const 926 auto ext = _M_find_extension();
931 path::is_absolute()
const 933 #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS 934 return has_root_name();
936 return has_root_directory();
943 if (_M_type == _Type::_Multi)
944 return iterator(
this, _M_cmpts.begin());
951 if (_M_type == _Type::_Multi)
952 return iterator(
this, _M_cmpts.end());
957 path::iterator::operator++()
959 _GLIBCXX_DEBUG_ASSERT(_M_path !=
nullptr);
960 if (_M_path->_M_type == _Type::_Multi)
962 _GLIBCXX_DEBUG_ASSERT(_M_cur != _M_path->_M_cmpts.end());
967 _GLIBCXX_DEBUG_ASSERT(!_M_at_end);
974 path::iterator::operator--()
976 _GLIBCXX_DEBUG_ASSERT(_M_path !=
nullptr);
977 if (_M_path->_M_type == _Type::_Multi)
979 _GLIBCXX_DEBUG_ASSERT(_M_cur != _M_path->_M_cmpts.begin());
984 _GLIBCXX_DEBUG_ASSERT(_M_at_end);
991 path::iterator::operator*()
const 993 _GLIBCXX_DEBUG_ASSERT(_M_path !=
nullptr);
994 if (_M_path->_M_type == _Type::_Multi)
996 _GLIBCXX_DEBUG_ASSERT(_M_cur != _M_path->_M_cmpts.end());
1003 path::iterator::_M_equals(
iterator __rhs)
const 1005 if (_M_path != __rhs._M_path)
1007 if (_M_path ==
nullptr)
1009 if (_M_path->_M_type == path::_Type::_Multi)
1010 return _M_cur == __rhs._M_cur;
1011 return _M_at_end == __rhs._M_at_end;
1015 _GLIBCXX_END_NAMESPACE_CXX11
1016 _GLIBCXX_END_NAMESPACE_VERSION
1024 #endif // _GLIBCXX_EXPERIMENTAL_FS_PATH_H
std::basic_istream< _CharT, _Traits > & operator>>(std::basic_istream< _CharT, _Traits > &__is, bitset< _Nb > &__x)
Global I/O operators for bitsets.
_Tp * __addressof(_Tp &__r) noexcept
Same as C++11 std::addressof.
basic_string< char16_t > u16string
A string of char16_t.
basic_string< wchar_t > wstring
A string of wchar_t.
size_t hash_value(const path &__p) noexcept
Compare paths.
complex< _Tp > operator*(const complex< _Tp > &__x, const complex< _Tp > &__y)
Return new complex value x times y.
Struct for delimited strings.
Thrown to indicate error code of underlying system.
Managing sequences of characters and character-like objects.
basic_string< char > string
A string of char.
Template class basic_ostream.
constexpr const _Tp * begin(initializer_list< _Tp > __ils) noexcept
Return an iterator pointing to the first element of the initializer_list.
Bidirectional iterators support a superset of forward iterator operations.
const _CharT * data() const noexcept
Return const pointer to contents.
complex< _Tp > operator/(const complex< _Tp > &__x, const complex< _Tp > &__y)
Return new complex value x divided by y.
An iterator for the components of a path.
void replace(_ForwardIterator __first, _ForwardIterator __last, const _Tp &__old_value, const _Tp &__new_value)
Replace each occurrence of one value in a sequence with another value.
path u8path(const _Source &__source)
Compare paths.
size_type size() const noexcept
Returns the number of characters in the string, not including any null-termination.
Class codecvt<wchar_t, char, mbstate_t> specialization.
Template class basic_istream.
void push_back(_CharT __c)
Append a single character.
static const size_type npos
Value returned by various member functions when they fail.
bool empty() const noexcept
Struct holding two objects of arbitrary type.
Container class for localization functionality.The locale class is first a class wrapper for C librar...
basic_string< char32_t > u32string
A string of char32_t.
ISO C++ entities toplevel namespace is std.
constexpr const _Tp * end(initializer_list< _Tp > __ils) noexcept
Return an iterator pointing to one past the last element of the initializer_list. ...