libstdc++: fs_path.h Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30#ifndef _GLIBCXX_FS_PATH_H

31#define _GLIBCXX_FS_PATH_H 1

32

33#if __cplusplus >= 201703L

34

46#include <bits/shared_ptr.h>

48

49#if __cplusplus > 201703L

51#endif

52

53#if defined(_WIN32) && !defined(__CYGWIN__)

54# define _GLIBCXX_FILESYSTEM_IS_WINDOWS 1

55#endif

56

57namespace std _GLIBCXX_VISIBILITY(default)

58{

59_GLIBCXX_BEGIN_NAMESPACE_VERSION

60

61namespace filesystem

62{

63_GLIBCXX_BEGIN_NAMESPACE_CXX11

64

65 class path;

66

67

68namespace __detail

69{

70

71

72 template<typename _CharT>

73 inline constexpr bool __is_encoded_char = false;

74 template<>

75 inline constexpr bool __is_encoded_char = true;

76#ifdef _GLIBCXX_USE_CHAR8_T

77 template<>

78 inline constexpr bool __is_encoded_char<char8_t> = true;

79#endif

80#if _GLIBCXX_USE_WCHAR_T

81 template<>

82 inline constexpr bool __is_encoded_char<wchar_t> = true;

83#endif

84 template<>

85 inline constexpr bool __is_encoded_char<char16_t> = true;

86 template<>

87 inline constexpr bool __is_encoded_char<char32_t> = true;

88

89#if __cpp_concepts >= 201907L

90 template<typename _Iter>

92#else

93 template<typename _Iter>

95 { };

96

97

98 template<> struct __safe_iterator_traits<void*> { };

99 template<> struct __safe_iterator_traits<const void*> { };

100 template<> struct __safe_iterator_traits<volatile void*> { };

101 template<> struct __safe_iterator_traits<const volatile void*> { };

102#endif

103

104 template<typename _Iter_traits, typename = void>

105 inline constexpr bool __is_path_iter_src = false;

106

107 template<typename _Iter_traits>

108 inline constexpr bool

109 __is_path_iter_src<_Iter_traits, void_t<typename _Iter_traits::value_type>>

110 = __is_encoded_char<typename _Iter_traits::value_type>;

111

112 template<typename _Source>

113 inline constexpr bool __is_path_src

114 = __is_path_iter_src<iterator_traits<decay_t<_Source>>>;

115

116 template<>

117 inline constexpr bool __is_path_src = false;

118

119 template<>

120 inline constexpr bool __is_path_src = false;

121

122 template<>

123 inline constexpr bool __is_path_src<void*> = false;

124

125 template<>

126 inline constexpr bool __is_path_src<const void*> = false;

127

128 template<>

129 inline constexpr bool __is_path_src<volatile void*> = false;

130

131 template<>

132 inline constexpr bool __is_path_src<const volatile void*> = false;

133

134 template<typename _CharT, typename _Traits, typename _Alloc>

135 inline constexpr bool

136 __is_path_src<basic_string<_CharT, _Traits, _Alloc>>

137 = __is_encoded_char<_CharT>;

138

139 template<typename _CharT, typename _Traits>

140 inline constexpr bool

141 __is_path_src<basic_string_view<_CharT, _Traits>>

142 = __is_encoded_char<_CharT>;

143

144

145 template<typename _Tp>

146 using _Path = enable_if_t<__is_path_src<_Tp>, path>;

147

148

149 template<typename _Iter, typename _Tr = __safe_iterator_traits<_Iter>>

150 using _Path2 = enable_if_t<__is_path_iter_src<_Tr>, path>;

151

152#if __cpp_lib_concepts

153 template<typename _Iter>

154 constexpr bool __is_contiguous = std::contiguous_iterator<_Iter>;

155#else

156 template<typename _Iter>

157 constexpr bool __is_contiguous = false;

158#endif

159

160 template<typename _Tp>

161 constexpr bool __is_contiguous<_Tp*> = true;

162

163 template<typename _Tp, typename _Seq>

164 constexpr bool

165 __is_contiguous<__gnu_cxx::__normal_iterator<_Tp*, _Seq>> = true;

166

167#if !defined _GLIBCXX_FILESYSTEM_IS_WINDOWS && defined _GLIBCXX_USE_CHAR8_T

168

169 template<typename _EcharT>

170 using __unified_u8_t

171 = __conditional_t<is_same_v<_EcharT, char8_t>, char, _EcharT>;

172#else

173 template<typename _EcharT>

174 using __unified_u8_t = _EcharT;

175#endif

176

177

178

179

180

181 template<typename _CharT, typename _Traits, typename _Alloc>

182 inline basic_string_view<_CharT>

183 __effective_range(const basic_string<_CharT, _Traits, _Alloc>& __source)

184 noexcept

185 { return __source; }

186

187 template<typename _CharT, typename _Traits>

188 inline basic_string_view<_CharT>

189 __effective_range(const basic_string_view<_CharT, _Traits>& __source)

190 noexcept

191 { return __source; }

192

193

194 template<typename _Source>

195 auto

196 __effective_range(const _Source& __source)

197 {

198

199 using _Iter = decltype(std::__niter_base(__source));

200 using value_type = typename iterator_traits<_Iter>::value_type;

201

202 if constexpr (__is_contiguous<_Iter>)

203 return basic_string_view<value_type>{&*__source};

204 else

205 {

206

207

208 basic_string<__unified_u8_t<value_type>> __str;

209 _Source __it = __source;

210 for (value_type __ch = *__it; __ch != value_type(); __ch = *++__it)

211 __str.push_back(__ch);

212 return __str;

213 }

214 }

215

216

217 template<typename _Source>

218 struct __source_value_type_impl

219 {

220 using type

221 = typename __safe_iterator_traits<decay_t<_Source>>::value_type;

222 };

223

224 template<typename _CharT, typename _Traits, typename _Alloc>

225 struct __source_value_type_impl<basic_string<_CharT, _Traits, _Alloc>>

226 {

227 using type = _CharT;

228 };

229

230 template<typename _CharT, typename _Traits>

231 struct __source_value_type_impl<basic_string_view<_CharT, _Traits>>

232 {

233 using type = _CharT;

234 };

235

236

237 template<typename _Source>

238 using __source_value_t = typename __source_value_type_impl<_Source>::type;

239

240

241

242

243 template<typename _Tp, typename _Val = __source_value_t<_Tp>>

244 using __value_type_is_char

246

247

248

249 template<typename _Tp, typename _Val = __source_value_t<_Tp>>

250 using __value_type_is_char_or_char8_t

252#ifdef _GLIBCXX_USE_CHAR8_T

253 || std::is_same_v<_Val, char8_t>

254#endif

255 , _Val>;

256

257

258 template<typename _InputIterator>

259 inline auto

260 __string_from_range(_InputIterator __first, _InputIterator __last)

261 {

262 using _EcharT

264 static_assert(__is_encoded_char<_EcharT>);

265

266 if constexpr (__is_contiguous<_InputIterator>)

267 {

268

269 if (auto __len = __last - __first) [[__likely__]]

270 return basic_string_view<_EcharT>(&*__first, __len);

271 return basic_string_view<_EcharT>();

272 }

273 else

274 {

275

276 return basic_string<__unified_u8_t<_EcharT>>(__first, __last);

277 }

278 }

279

280

281}

282

283

284

285

286

287

288

289

290

291

292

294 {

295 public:

296#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS

297 using value_type = wchar_t;

298 static constexpr value_type preferred_separator = L'\\';

299#else

300# ifdef _GLIBCXX_DOXYGEN

301

302 using value_type = __os_dependent__;

303# else

304 using value_type = char;

305# endif

306 static constexpr value_type preferred_separator = '/';

307#endif

309

310

311 enum format : unsigned char { native_format, generic_format, auto_format };

312

313

314

315 path() noexcept { }

316

317 path(const path& __p) = default;

318

319 path(path&& __p) noexcept

320 : _M_pathname(std::move(__p._M_pathname)),

321 _M_cmpts(std::move(__p._M_cmpts))

322 { __p.clear(); }

323

324 path(string_type&& __source, format = auto_format)

325 : _M_pathname(std::move(__source))

326 { _M_split_cmpts(); }

327

328 template<typename _Source,

329 typename _Require = __detail::_Path<_Source>>

330 path(_Source const& __source, format = auto_format)

331 : _M_pathname(_S_convert(__detail::__effective_range(__source)))

332 { _M_split_cmpts(); }

333

334 template<typename _InputIterator,

335 typename _Require = __detail::_Path2<_InputIterator>>

336 path(_InputIterator __first, _InputIterator __last, format = auto_format)

337 : _M_pathname(_S_convert(__detail::__string_from_range(__first, __last)))

338 { _M_split_cmpts(); }

339

340 template<typename _Source,

341 typename _Require = __detail::_Path<_Source>,

342 typename _Require2 = __detail::__value_type_is_char<_Source>>

343 path(_Source const& __src, const locale& __loc, format = auto_format)

344 : _M_pathname(_S_convert_loc(__detail::__effective_range(__src), __loc))

345 { _M_split_cmpts(); }

346

347 template<typename _InputIterator,

348 typename _Require = __detail::_Path2<_InputIterator>,

349 typename _Req2 = __detail::__value_type_is_char<_InputIterator>>

350 path(_InputIterator __first, _InputIterator __last, const locale& __loc,

351 format = auto_format)

352 : _M_pathname(_S_convert_loc(__first, __last, __loc))

353 { _M_split_cmpts(); }

354

355 ~path() = default;

356

357

358

359 path& operator=(const path&);

360 path& operator=(path&&) noexcept;

361 path& operator=(string_type&& __source);

362 path& assign(string_type&& __source);

363

364 template<typename _Source>

365 __detail::_Path<_Source>&

366 operator=(_Source const& __source)

367 { return *this = path(__source); }

368

369 template<typename _Source>

370 __detail::_Path<_Source>&

371 assign(_Source const& __source)

372 { return *this = path(__source); }

373

374 template<typename _InputIterator>

375 __detail::_Path2<_InputIterator>&

376 assign(_InputIterator __first, _InputIterator __last)

377 { return *this = path(__first, __last); }

378

379

380

381 path& operator/=(const path& __p);

382

383 template<typename _Source>

384 __detail::_Path<_Source>&

385 operator/=(_Source const& __source)

386 {

387 _M_append(_S_convert(__detail::__effective_range(__source)));

388 return *this;

389 }

390

391 template<typename _Source>

392 __detail::_Path<_Source>&

393 append(_Source const& __source)

394 {

395 _M_append(_S_convert(__detail::__effective_range(__source)));

396 return *this;

397 }

398

399 template<typename _InputIterator>

400 __detail::_Path2<_InputIterator>&

401 append(_InputIterator __first, _InputIterator __last)

402 {

403 _M_append(_S_convert(__detail::__string_from_range(__first, __last)));

404 return *this;

405 }

406

407

408

409 path& operator+=(const path& __x);

410 path& operator+=(const string_type& __x);

411 path& operator+=(const value_type* __x);

412 path& operator+=(value_type __x);

413 path& operator+=(basic_string_view<value_type> __x);

414

415 template<typename _Source>

416 __detail::_Path<_Source>&

417 operator+=(_Source const& __x) { return concat(__x); }

418

419 template<typename _CharT>

420 __detail::_Path2<_CharT*>&

421 operator+=(_CharT __x);

422

423 template<typename _Source>

424 __detail::_Path<_Source>&

425 concat(_Source const& __x)

426 {

427 _M_concat(_S_convert(__detail::__effective_range(__x)));

428 return *this;

429 }

430

431 template<typename _InputIterator>

432 __detail::_Path2<_InputIterator>&

433 concat(_InputIterator __first, _InputIterator __last)

434 {

435 _M_concat(_S_convert(__detail::__string_from_range(__first, __last)));

436 return *this;

437 }

438

439

440

441 void clear() noexcept { _M_pathname.clear(); _M_split_cmpts(); }

442

443 path& make_preferred();

444 path& remove_filename();

445 path& replace_filename(const path& __replacement);

446 path& replace_extension(const path& __replacement = path());

447

448 void swap(path& __rhs) noexcept;

449

450

451

452 const string_type& native() const noexcept { return _M_pathname; }

453 const value_type* c_str() const noexcept { return _M_pathname.c_str(); }

454 operator string_type() const { return _M_pathname; }

455

456 template<typename _CharT, typename _Traits = std::char_traits<_CharT>,

457 typename _Allocator = std::allocator<_CharT>>

459 string(const _Allocator& __a = _Allocator()) const;

460

462#if _GLIBCXX_USE_WCHAR_T

464#endif

465#ifdef _GLIBCXX_USE_CHAR8_T

466 __attribute__((__abi_tag__("__u8")))

467 std::u8string u8string() const;

468#else

470#endif

473

474

475 template<typename _CharT, typename _Traits = std::char_traits<_CharT>,

476 typename _Allocator = std::allocator<_CharT>>

478 generic_string(const _Allocator& __a = _Allocator()) const;

479

481#if _GLIBCXX_USE_WCHAR_T

483#endif

484#ifdef _GLIBCXX_USE_CHAR8_T

485 __attribute__((__abi_tag__("__u8")))

486 std::u8string generic_u8string() const;

487#else

489#endif

492

493

494

495 int compare(const path& __p) const noexcept;

496 int compare(const string_type& __s) const noexcept;

497 int compare(const value_type* __s) const noexcept;

498 int compare(basic_string_view<value_type> __s) const noexcept;

499

500

501

502 path root_name() const;

503 path root_directory() const;

504 path root_path() const;

505 path relative_path() const;

506 path parent_path() const;

507 path filename() const;

508 path stem() const;

509 path extension() const;

510

511

512

513 [[nodiscard]] bool empty() const noexcept { return _M_pathname.empty(); }

514 bool has_root_name() const noexcept;

515 bool has_root_directory() const noexcept;

516 bool has_root_path() const noexcept;

517 bool has_relative_path() const noexcept;

518 bool has_parent_path() const noexcept;

519 bool has_filename() const noexcept;

520 bool has_stem() const noexcept;

521 bool has_extension() const noexcept;

522 bool is_absolute() const noexcept;

523 bool is_relative() const noexcept { return !is_absolute(); }

524

525

526 path lexically_normal() const;

527 path lexically_relative(const path& base) const;

528 path lexically_proximate(const path& base) const;

529

530

531 class iterator;

532 using const_iterator = iterator;

533

534 iterator begin() const noexcept;

535 iterator end() const noexcept;

536

537

538 template<typename _CharT, typename _Traits>

541 {

542 __os << std::quoted(__p.string<_CharT, _Traits>());

543 return __os;

544 }

545

546

547 template<typename _CharT, typename _Traits>

550 {

552 if (__is >> std::quoted(__tmp))

554 return __is;

555 }

556

557

558

559

561 { return path::_S_compare(__lhs, __rhs) == 0; }

562

563#if __cpp_lib_three_way_comparison

564

565 friend strong_ordering

567 { return path::_S_compare(__lhs, __rhs) <=> 0; }

568#else

569

570 friend bool operator!=(const path& __lhs, const path& __rhs) noexcept

571 { return !(__lhs == __rhs); }

572

573

574 friend bool operator<(const path& __lhs, const path& __rhs) noexcept

575 { return __lhs.compare(__rhs) < 0; }

576

577

578 friend bool operator<=(const path& __lhs, const path& __rhs) noexcept

579 { return !(__rhs < __lhs); }

580

581

582 friend bool operator>(const path& __lhs, const path& __rhs) noexcept

583 { return __rhs < __lhs; }

584

585

586 friend bool operator>=(const path& __lhs, const path& __rhs) noexcept

587 { return !(__lhs < __rhs); }

588#endif

589

590

592 {

593 path __result(__lhs);

594 __result /= __rhs;

595 return __result;

596 }

597

598 private:

599 enum class _Type : unsigned char {

600 _Multi = 0, _Root_name, _Root_dir, _Filename

601 };

602

604

605 enum class _Split { _Stem, _Extension };

606

607 void _M_append(basic_string_view<value_type>);

608 void _M_concat(basic_string_view<value_type>);

609

610 pair<const string_type*, size_t> _M_find_extension() const noexcept;

611

612

613

614

615

616 template<typename _Tp>

617 static auto

618 _S_convert(_Tp __str)

619 noexcept(is_same_v<typename _Tp::value_type, value_type>)

620 {

621 if constexpr (is_same_v<typename _Tp::value_type, value_type>)

622 return __str;

623#if !defined _GLIBCXX_FILESYSTEM_IS_WINDOWS && defined _GLIBCXX_USE_CHAR8_T

624 else if constexpr (is_same_v<_Tp, std::u8string>)

625

626

627

628 return string_type(_S_convert(__str.data(),

629 __str.data() + __str.size()));

630#endif

631 else

632 return _S_convert(__str.data(), __str.data() + __str.size());

633 }

634

635 template<typename _EcharT>

636 static auto

637 _S_convert(const _EcharT* __first, const _EcharT* __last);

638

639

640

641

642 static string_type

643 _S_convert_loc(const char* __first, const char* __last,

645

646 template<typename _Iter>

647 static string_type

648 _S_convert_loc(_Iter __first, _Iter __last, const std::locale& __loc)

649 {

650 const auto __s = __detail::__string_from_range(__first, __last);

651 return _S_convert_loc(__s.data(), __s.data() + __s.size(), __loc);

652 }

653

654 template<typename _Tp>

655 static string_type

656 _S_convert_loc(const _Tp& __s, const std::locale& __loc)

657 {

658 return _S_convert_loc(__s.data(), __s.data() + __s.size(), __loc);

659 }

660

661 template<typename _CharT, typename _Traits, typename _Allocator>

662 static basic_string<_CharT, _Traits, _Allocator>

663 _S_str_convert(basic_string_view<value_type>, const _Allocator&);

664

665

666 __attribute__((__always_inline__))

667 static int

668 _S_compare(const path& __lhs, const path& __rhs) noexcept;

669

670 void _M_split_cmpts();

671

672 _Type _M_type() const noexcept { return _M_cmpts.type(); }

673

674 string_type _M_pathname;

675

676 struct _Cmpt;

677

678 struct _List

679 {

680 using value_type = _Cmpt;

681 using iterator = value_type*;

682 using const_iterator = const value_type*;

683

684 _List();

685 _List(const _List&);

686 _List(_List&&) = default;

687 _List& operator=(const _List&);

688 _List& operator=(_List&&) = default;

689 ~_List() = default;

690

691 _Type type() const noexcept

692 { return _Type(reinterpret_cast<__UINTPTR_TYPE__>(_M_impl.get()) & 0x3); }

693

694 void type(_Type) noexcept;

695

696 int size() const noexcept;

697 bool empty() const noexcept;

698 void clear();

699 void swap(_List& __l) noexcept { _M_impl.swap(__l._M_impl); }

700 int capacity() const noexcept;

701 void reserve(int, bool);

702

703

704

705

706 iterator begin() noexcept;

707 iterator end() noexcept;

708 const_iterator begin() const noexcept;

709 const_iterator end() const noexcept;

710

711 value_type& front() noexcept;

712 value_type& back() noexcept;

713 const value_type& front() const noexcept;

714 const value_type& back() const noexcept;

715

716 void pop_back();

717 void _M_erase_from(const_iterator __pos);

718

719 struct _Impl;

720 struct _Impl_deleter

721 {

722 void operator()(_Impl*) const noexcept;

723 };

724 unique_ptr<_Impl, _Impl_deleter> _M_impl;

725 };

726 _List _M_cmpts;

727

728 struct _Parser;

729

730 template<typename _EcharT> struct _Codecvt;

731 };

732

733

734

735

736 inline void swap(path& __lhs, path& __rhs) noexcept { __lhs.swap(__rhs); }

737

738 size_t hash_value(const path& __p) noexcept;

739

740

741

742

743

744

745

746

748 {

749 public:

751

754

757

760

761

762

763

765

766 const path& path1() const noexcept;

767 const path& path2() const noexcept;

768 const char* what() const noexcept;

769

770 private:

771 struct _Impl;

772 std::__shared_ptr<const _Impl> _M_impl;

773 };

774

775

776namespace __detail

777{

778 [[noreturn]] inline void

779 __throw_conversion_error()

780 {

782 "Cannot convert character sequence",

784 }

785

786#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS

787 template<typename _Tp>

789 __wstr_from_utf8(const _Tp& __str)

790 {

791 static_assert(std::is_same_v<typename _Tp::value_type, char>);

793

794 std::codecvt_utf8_utf16<wchar_t> __wcvt;

795 const auto __p = __str.data();

796 if (!__str_codecvt_in_all(__p, __p + __str.size(), __wstr, __wcvt))

797 __detail::__throw_conversion_error();

798 return __wstr;

799 }

800#endif

801

802}

803

804

805

806

807

808

809

810

811

812 template<typename _InputIterator,

813 typename _Require = __detail::_Path2<_InputIterator>,

814 typename _CharT

815 = __detail::__value_type_is_char_or_char8_t<_InputIterator>>

816 _GLIBCXX20_DEPRECATED_SUGGEST("path(u8string(first, last))")

818 u8path(_InputIterator __first, _InputIterator __last)

819 {

820#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS

821 if constexpr (is_same_v<_CharT, char>)

822 return path{ __detail::__wstr_from_utf8(

823 __detail::__string_from_range(__first, __last)) };

824 else

825 return path{ __first, __last };

826#else

827

828 return path{ __first, __last };

829#endif

830 }

831

832

833

834

835

836

837

838 template<typename _Source,

839 typename _Require = __detail::_Path<_Source>,

840 typename _CharT = __detail::__value_type_is_char_or_char8_t<_Source>>

841 _GLIBCXX20_DEPRECATED_SUGGEST("path((const char8_t*)&*source)")

843 u8path(const _Source& __source)

844 {

845#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS

846 if constexpr (is_same_v<_CharT, char>)

847 return path{ __detail::__wstr_from_utf8(

848 __detail::__effective_range(__source)) };

849 else

850 return path{ __source };

851#else

852

853 return path{ __source };

854#endif

855 }

856

857

858

859 struct path::_Cmpt : path

860 {

862

863 _Cmpt() : _M_pos(-1) { }

864

865 size_t _M_pos;

866 };

867

868

869

870

871

872

873

874 template<typename _EcharT>

875 struct path::_Codecvt

876

878 { };

879

880

881

882

883

884

885

886

887 template<>

888 struct path::_Codecvt<wchar_t>

889 : __conditional_t<sizeof(wchar_t) == sizeof(char32_t),

890 std::codecvt_utf8<wchar_t>,

891 std::codecvt_utf8_utf16<wchar_t>>

892 { };

893

894 template<typename _EcharT>

895 auto

896 path::_S_convert(const _EcharT* __f, const _EcharT* __l)

897 {

898 static_assert(__detail::__is_encoded_char<_EcharT>);

899

900#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS

901# define _GLIBCXX_CONV_FROM_UTF8(S) __detail::__wstr_from_utf8(S)

902#else

903# define _GLIBCXX_CONV_FROM_UTF8(S) S

904#endif

905

906 if constexpr (is_same_v<_EcharT, value_type>)

907 return basic_string_view<value_type>(__f, __l - __f);

908#ifdef _GLIBCXX_USE_CHAR8_T

909 else if constexpr (is_same_v<_EcharT, char8_t>)

910 {

911 string_view __str(reinterpret_cast<const char*>(__f), __l - __f);

912 return _GLIBCXX_CONV_FROM_UTF8(__str);

913 }

914#endif

915#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS

916 else if constexpr (is_same_v<_EcharT, char>)

917 {

919 path::_Codecvt<wchar_t> __cvt;

920 if (__str_codecvt_in_all(__f, __l, __wstr, __cvt))

921 return __wstr;

922 }

923#endif

924 else

925 {

926 path::_Codecvt<_EcharT> __cvt;

928 if (__str_codecvt_out_all(__f, __l, __str, __cvt))

929 return _GLIBCXX_CONV_FROM_UTF8(__str);

930 }

931 __detail::__throw_conversion_error();

932 }

933#undef _GLIBCXX_CONV_FROM_UTF8

934

935

936

937

938

939

940

941

943 {

944 public:

945 using difference_type = std::ptrdiff_t;

950

951 iterator() noexcept : _M_path(nullptr), _M_cur(), _M_at_end() { }

952

955

958

959 iterator& operator++() noexcept;

960

961 iterator operator++(int) noexcept

962 { auto __tmp = *this; ++*this; return __tmp; }

963

964 iterator& operator--() noexcept;

965

966 iterator operator--(int) noexcept

967 { auto __tmp = *this; --*this; return __tmp; }

968

969 friend bool

970 operator==(const iterator& __lhs, const iterator& __rhs) noexcept

971 { return __lhs._M_equals(__rhs); }

972

973 friend bool

974 operator!=(const iterator& __lhs, const iterator& __rhs) noexcept

975 { return !__lhs._M_equals(__rhs); }

976

977 private:

978 friend class path;

979

980 bool

981 _M_is_multi() const noexcept

982 { return _M_path->_M_type() == _Type::_Multi; }

983

984 friend difference_type

985 __path_iter_distance(const iterator& __first, const iterator& __last)

986 noexcept

987 {

988 __glibcxx_assert(__first._M_path != nullptr);

989 __glibcxx_assert(__first._M_path == __last._M_path);

990 if (__first._M_is_multi())

991 return std::distance(__first._M_cur, __last._M_cur);

992 else if (__first._M_at_end == __last._M_at_end)

993 return 0;

994 else

995 return __first._M_at_end ? -1 : 1;

996 }

997

998 friend void

999 __path_iter_advance(iterator& __i, difference_type __n) noexcept

1000 {

1001 if (__n == 1)

1002 ++__i;

1003 else if (__n == -1)

1004 --__i;

1005 else if (__n != 0)

1006 {

1007 __glibcxx_assert(__i._M_path != nullptr);

1008 __glibcxx_assert(__i._M_is_multi());

1009

1010 __i._M_cur += __n;

1011 }

1012 }

1013

1014 iterator(const path* __path, path::_List::const_iterator __iter) noexcept

1015 : _M_path(__path), _M_cur(__iter), _M_at_end()

1016 { }

1017

1018 iterator(const path* __path, bool __at_end) noexcept

1019 : _M_path(__path), _M_cur(), _M_at_end(__at_end)

1020 { }

1021

1022 bool _M_equals(iterator) const noexcept;

1023

1024 const path* _M_path;

1025 path::_List::const_iterator _M_cur;

1026 bool _M_at_end;

1027 };

1028

1029

1030 inline path&

1031 path::operator=(path&& __p) noexcept

1032 {

1033 if (&__p == this) [[__unlikely__]]

1034 return *this;

1035

1036 _M_pathname = std::move(__p._M_pathname);

1037 _M_cmpts = std::move(__p._M_cmpts);

1038 __p.clear();

1039 return *this;

1040 }

1041

1042 inline path&

1043 path::operator=(string_type&& __source)

1045

1046 inline path&

1047 path::assign(string_type&& __source)

1048 { return *this = path(std::move(__source)); }

1049

1050 inline path&

1051 path::operator+=(const string_type& __x)

1052 {

1053 _M_concat(__x);

1054 return *this;

1055 }

1056

1057 inline path&

1058 path::operator+=(const value_type* __x)

1059 {

1060 _M_concat(__x);

1061 return *this;

1062 }

1063

1064 inline path&

1065 path::operator+=(value_type __x)

1066 {

1067 _M_concat(basic_string_view<value_type>(&__x, 1));

1068 return *this;

1069 }

1070

1071 inline path&

1072 path::operator+=(basic_string_view<value_type> __x)

1073 {

1074 _M_concat(__x);

1075 return *this;

1076 }

1077

1078 template<typename _CharT>

1079 inline __detail::_Path2<_CharT*>&

1080 path::operator+=(const _CharT __x)

1081 {

1082 _M_concat(_S_convert(&__x, &__x + 1));

1083 return *this;

1084 }

1085

1086 inline path&

1087 path::make_preferred()

1088 {

1089#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS

1090 auto __pos = _M_pathname.find(L'/');

1091 while (__pos != _M_pathname.npos)

1092 {

1093 _M_pathname[__pos] = preferred_separator;

1094 __pos = _M_pathname.find(L'/', __pos);

1095 }

1096#endif

1097 return *this;

1098 }

1099

1100 inline void path::swap(path& __rhs) noexcept

1101 {

1102 _M_pathname.swap(__rhs._M_pathname);

1103 _M_cmpts.swap(__rhs._M_cmpts);

1104 }

1105

1106

1107 template<typename _CharT, typename _Traits, typename _Allocator>

1109 path::_S_str_convert(basic_string_view<value_type> __str,

1110 const _Allocator& __a)

1111 {

1112 static_assert(!is_same_v<_CharT, value_type>);

1113

1114 using _WString = basic_string<_CharT, _Traits, _Allocator>;

1115

1116 if (__str.size() == 0)

1117 return _WString(__a);

1118

1119#ifndef _GLIBCXX_FILESYSTEM_IS_WINDOWS

1120 string_view __u8str = __str;

1121#else

1122

1123

1124 std::codecvt_utf8_utf16<value_type> __cvt;

1125

1126 using _CharAlloc = __alloc_rebind<_Allocator, char>;

1127 using _String = basic_string<char, char_traits, _CharAlloc>;

1128 _String __u8str{_CharAlloc{__a}};

1129 const value_type* __wfirst = __str.data();

1130 const value_type* __wlast = __wfirst + __str.size();

1131 if (!__str_codecvt_out_all(__wfirst, __wlast, __u8str, __cvt))

1132 __detail::__throw_conversion_error();

1133 if constexpr (is_same_v<_CharT, char>)

1134 return __u8str;

1135 else

1136#endif

1137 {

1138 const char* __first = __u8str.data();

1139 const char* __last = __first + __u8str.size();

1140

1141

1142#ifdef _GLIBCXX_USE_CHAR8_T

1143 if constexpr (is_same_v<_CharT, char8_t>)

1144 return _WString(__first, __last, __a);

1145 else

1146#endif

1147 {

1148

1149 _WString __wstr(__a);

1150 path::_Codecvt<_CharT> __cvt;

1151 if (__str_codecvt_in_all(__first, __last, __wstr, __cvt))

1152 return __wstr;

1153 }

1154 }

1155 __detail::__throw_conversion_error();

1156 }

1157

1158

1159 template<typename _CharT, typename _Traits, typename _Allocator>

1160 inline basic_string<_CharT, _Traits, _Allocator>

1161 path::string(const _Allocator& __a) const

1162 {

1163 if constexpr (is_same_v<_CharT, value_type>)

1164 return { _M_pathname.c_str(), _M_pathname.length(), __a };

1165 else

1166 return _S_str_convert<_CharT, _Traits>(_M_pathname, __a);

1167 }

1168

1170 path::string() const { return string(); }

1171

1172#if _GLIBCXX_USE_WCHAR_T

1174 path::wstring() const { return string<wchar_t>(); }

1175#endif

1176

1177#ifdef _GLIBCXX_USE_CHAR8_T

1178 inline std::u8string

1179 path::u8string() const { return string<char8_t>(); }

1180#else

1182 path::u8string() const

1183 {

1184#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS

1186

1187 std::codecvt_utf8_utf16<value_type> __cvt;

1188 const value_type* __first = _M_pathname.data();

1189 const value_type* __last = __first + _M_pathname.size();

1190 if (__str_codecvt_out_all(__first, __last, __str, __cvt))

1191 return __str;

1192 __detail::__throw_conversion_error();

1193#else

1194 return _M_pathname;

1195#endif

1196 }

1197#endif

1198

1200 path::u16string() const { return string<char16_t>(); }

1201

1203 path::u32string() const { return string<char32_t>(); }

1204

1205 template<typename _CharT, typename _Traits, typename _Allocator>

1207 path::generic_string(const _Allocator& __a) const

1208 {

1209#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS

1210 const value_type __slash = L'/';

1211#else

1212 const value_type __slash = '/';

1213#endif

1214 using _Alloc2 = typename allocator_traits<_Allocator>::template

1215 rebind_alloc<value_type>;

1216 basic_string<value_type, char_traits<value_type>, _Alloc2> __str(__a);

1217

1218 if (_M_type() == _Type::_Root_dir)

1219 __str.assign(1, __slash);

1220 else

1221 {

1222 __str.reserve(_M_pathname.size());

1223 bool __add_slash = false;

1224 for (auto& __elem : *this)

1225 {

1226#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS

1227 if (__elem._M_type() == _Type::_Root_dir)

1228 {

1229 __str += __slash;

1230 continue;

1231 }

1232#endif

1233 if (__add_slash)

1234 __str += __slash;

1235 __str += basic_string_view<value_type>(__elem._M_pathname);

1236 __add_slash = __elem._M_type() == _Type::_Filename;

1237 }

1238 }

1239

1240 if constexpr (is_same_v<_CharT, value_type>)

1241 return __str;

1242 else

1243 return _S_str_convert<_CharT, _Traits>(__str, __a);

1244 }

1245

1247 path::generic_string() const

1248 { return generic_string(); }

1249

1250#if _GLIBCXX_USE_WCHAR_T

1252 path::generic_wstring() const

1253 { return generic_string<wchar_t>(); }

1254#endif

1255

1256#ifdef _GLIBCXX_USE_CHAR8_T

1257 inline std::u8string

1258 path::generic_u8string() const

1259 { return generic_string<char8_t>(); }

1260#else

1262 path::generic_u8string() const

1263 { return generic_string(); }

1264#endif

1265

1267 path::generic_u16string() const

1268 { return generic_string<char16_t>(); }

1269

1271 path::generic_u32string() const

1272 { return generic_string<char32_t>(); }

1273

1274 inline int

1275 path::compare(const string_type& __s) const noexcept

1276 { return compare(basic_string_view<value_type>(__s)); }

1277

1278 inline int

1279 path::compare(const value_type* __s) const noexcept

1280 { return compare(basic_string_view<value_type>(__s)); }

1281

1282 inline path

1283 path::filename() const

1284 {

1286 return {};

1287 else if (_M_type() == _Type::_Filename)

1288 return *this;

1289 else if (_M_type() == _Type::_Multi)

1290 {

1291 if (_M_pathname.back() == preferred_separator)

1292 return {};

1293 auto __last = --end();

1294 if (__last->_M_type() == _Type::_Filename)

1295 return *__last;

1296 }

1297 return {};

1298 }

1299

1300 inline path

1301 path::stem() const

1302 {

1303 auto ext = _M_find_extension();

1304 if (ext.first && ext.second != 0)

1305 return path{ext.first->substr(0, ext.second)};

1306 return {};

1307 }

1308

1309 inline path

1310 path::extension() const

1311 {

1312 auto ext = _M_find_extension();

1313 if (ext.first && ext.second != string_type::npos)

1314 return path{ext.first->substr(ext.second)};

1315 return {};

1316 }

1317

1318 inline bool

1319 path::has_stem() const noexcept

1320 {

1321 auto ext = _M_find_extension();

1322 return ext.first && ext.second != 0;

1323 }

1324

1325 inline bool

1326 path::has_extension() const noexcept

1327 {

1328 auto ext = _M_find_extension();

1329 return ext.first && ext.second != string_type::npos;

1330 }

1331

1332 inline bool

1333 path::is_absolute() const noexcept

1334 {

1335#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS

1336 return has_root_name() && has_root_directory();

1337#else

1338 return has_root_directory();

1339#endif

1340 }

1341

1342 inline path::iterator

1343 path::begin() const noexcept

1344 {

1345 if (_M_type() == _Type::_Multi)

1346 return iterator(this, _M_cmpts.begin());

1347 return iterator(this, empty());

1348 }

1349

1350 inline path::iterator

1351 path::end() const noexcept

1352 {

1353 if (_M_type() == _Type::_Multi)

1354 return iterator(this, _M_cmpts.end());

1355 return iterator(this, true);

1356 }

1357

1358 inline path::iterator&

1359 path::iterator::operator++() noexcept

1360 {

1361 __glibcxx_assert(_M_path != nullptr);

1362 if (_M_is_multi())

1363 {

1364 __glibcxx_assert(_M_cur != _M_path->_M_cmpts.end());

1365 ++_M_cur;

1366 }

1367 else

1368 {

1369 __glibcxx_assert(!_M_at_end);

1370 _M_at_end = true;

1371 }

1372 return *this;

1373 }

1374

1375 inline path::iterator&

1376 path::iterator::operator--() noexcept

1377 {

1378 __glibcxx_assert(_M_path != nullptr);

1379 if (_M_is_multi())

1380 {

1381 __glibcxx_assert(_M_cur != _M_path->_M_cmpts.begin());

1382 --_M_cur;

1383 }

1384 else

1385 {

1386 __glibcxx_assert(_M_at_end);

1387 _M_at_end = false;

1388 }

1389 return *this;

1390 }

1391

1392 inline path::iterator::reference

1393 path::iterator::operator*() const noexcept

1394 {

1395 __glibcxx_assert(_M_path != nullptr);

1396 if (_M_is_multi())

1397 {

1398 __glibcxx_assert(_M_cur != _M_path->_M_cmpts.end());

1399 return *_M_cur;

1400 }

1401 return *_M_path;

1402 }

1403

1404 inline bool

1405 path::iterator::_M_equals(iterator __rhs) const noexcept

1406 {

1407 if (_M_path != __rhs._M_path)

1408 return false;

1409 if (_M_path == nullptr)

1410 return true;

1411 if (_M_is_multi())

1412 return _M_cur == __rhs._M_cur;

1413 return _M_at_end == __rhs._M_at_end;

1414 }

1415

1416

1417

1418

1419

1420 inline int

1421 path::_S_compare(const path& __lhs, const path& __rhs) noexcept

1422 { return __lhs.compare(__rhs); }

1423

1424

1425_GLIBCXX_END_NAMESPACE_CXX11

1426}

1427

1428

1429

1430inline ptrdiff_t

1431distance(filesystem::path::iterator __first, filesystem::path::iterator __last)

1432noexcept

1433{ return __path_iter_distance(__first, __last); }

1434

1435template<typename _Distance>

1436 inline void

1437 advance(filesystem::path::iterator& __i, _Distance __n) noexcept

1438 { __path_iter_advance(__i, static_cast<ptrdiff_t>(__n)); }

1439

1440extern template class __shared_ptr<const filesystem::filesystem_error::_Impl>;

1441

1442

1443

1444

1445

1446template<>

1447 struct hashfilesystem::path

1448 {

1449 size_t

1450 operator()(const filesystem::path& __p) const noexcept

1451 { return filesystem::hash_value(__p); }

1452 };

1453

1454_GLIBCXX_END_NAMESPACE_VERSION

1455}

1456

1457#endif

1458

1459#endif

constexpr bool operator>=(const duration< _Rep1, _Period1 > &__lhs, const duration< _Rep2, _Period2 > &__rhs)

constexpr bool operator>(const duration< _Rep1, _Period1 > &__lhs, const duration< _Rep2, _Period2 > &__rhs)

constexpr complex< _Tp > operator*(const complex< _Tp > &__x, const complex< _Tp > &__y)

Return new complex value x times y.

error_code make_error_code(future_errc __errc) noexcept

Overload of make_error_code for future_errc.

typename enable_if< _Cond, _Tp >::type enable_if_t

Alias template for enable_if.

constexpr std::remove_reference< _Tp >::type && move(_Tp &&__t) noexcept

Convert a value to an rvalue.

constexpr _Tp * __addressof(_Tp &__r) noexcept

Same as C++11 std::addressof.

_Tp * end(valarray< _Tp > &__va) noexcept

Return an iterator pointing to one past the last element of the valarray.

ISO C++ entities toplevel namespace is std.

constexpr iterator_traits< _InputIterator >::difference_type distance(_InputIterator __first, _InputIterator __last)

A generalization of pointer arithmetic.

constexpr auto empty(const _Container &__cont) noexcept(noexcept(__cont.empty())) -> decltype(__cont.empty())

Return whether a container is empty.

constexpr auto size(const _Container &__cont) noexcept(noexcept(__cont.size())) -> decltype(__cont.size())

Return the size of a container.

constexpr void advance(_InputIterator &__i, _Distance __n)

A generalization of pointer arithmetic.

Template class basic_istream.

Template class basic_ostream.

A non-owning reference to a string.

An exception type that includes an error_code value.

Primary class template codecvt.

const _CharT * data() const noexcept

Return const pointer to contents.

void reserve(size_type __res_arg)

Attempt to preallocate enough memory for specified number of characters.

basic_string & assign(const basic_string &__str)

Set value to contents of another string.

bool empty() const noexcept

const _CharT * c_str() const noexcept

Return const pointer to null-terminated contents.

Traits class for iterators.

friend strong_ordering operator<=>(const path &__lhs, const path &__rhs) noexcept

Compare paths.

friend path operator/(const path &__lhs, const path &__rhs)

Append one path to another.

format

path::format is ignored in this implementation

friend std::basic_istream< _CharT, _Traits > & operator>>(std::basic_istream< _CharT, _Traits > &__is, path &__p)

Read a path from a stream.

friend bool operator==(const path &__lhs, const path &__rhs) noexcept

Compare paths.

Exception type thrown by the Filesystem library.

const char * what() const noexcept

An iterator for the components of a path.

Container class for localization functionality.

Bidirectional iterators support a superset of forward iterator operations.