/src/boost/boost/filesystem/path.hpp
Line | Count | Source |
1 | | // filesystem path.hpp ---------------------------------------------------------------// |
2 | | |
3 | | // Copyright Vladimir Prus 2002 |
4 | | // Copyright Beman Dawes 2002-2005, 2009 |
5 | | // Copyright Andrey Semashev 2021-2024 |
6 | | |
7 | | // Distributed under the Boost Software License, Version 1.0. |
8 | | // See http://www.boost.org/LICENSE_1_0.txt |
9 | | |
10 | | // Library home page: http://www.boost.org/libs/filesystem |
11 | | |
12 | | // path::stem(), extension(), and replace_extension() are based on |
13 | | // basename(), extension(), and change_extension() from the original |
14 | | // filesystem/convenience.hpp header by Vladimir Prus. |
15 | | |
16 | | #ifndef BOOST_FILESYSTEM_PATH_HPP |
17 | | #define BOOST_FILESYSTEM_PATH_HPP |
18 | | |
19 | | #include <boost/filesystem/config.hpp> |
20 | | #include <cstddef> |
21 | | #include <iosfwd> |
22 | | #include <locale> |
23 | | #include <string> |
24 | | #include <iterator> |
25 | | #include <type_traits> |
26 | | #if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) |
27 | | #include <string_view> |
28 | | #endif |
29 | | #include <boost/assert.hpp> |
30 | | #include <boost/iterator/iterator_facade.hpp> |
31 | | #include <boost/iterator/iterator_categories.hpp> |
32 | | #include <boost/io/quoted.hpp> |
33 | | #include <boost/functional/hash_fwd.hpp> |
34 | | #include <boost/filesystem/detail/path_traits.hpp> |
35 | | #include <boost/filesystem/detail/type_traits/negation.hpp> |
36 | | #include <boost/filesystem/detail/type_traits/conjunction.hpp> |
37 | | #include <boost/filesystem/detail/type_traits/disjunction.hpp> |
38 | | |
39 | | #include <boost/filesystem/detail/header.hpp> // must be the last #include |
40 | | |
41 | | namespace boost { |
42 | | namespace filesystem { |
43 | | |
44 | | class path; |
45 | | |
46 | | namespace path_detail { // intentionally don't use filesystem::detail to not bring internal Boost.Filesystem functions into ADL via path_constants |
47 | | |
48 | | template< typename Char, Char Separator, Char PreferredSeparator, Char Dot > |
49 | | struct path_constants |
50 | | { |
51 | | typedef path_constants< Char, Separator, PreferredSeparator, Dot > path_constants_base; |
52 | | typedef Char value_type; |
53 | | static BOOST_CONSTEXPR_OR_CONST value_type separator = Separator; |
54 | | static BOOST_CONSTEXPR_OR_CONST value_type preferred_separator = PreferredSeparator; |
55 | | static BOOST_CONSTEXPR_OR_CONST value_type dot = Dot; |
56 | | }; |
57 | | |
58 | | #if defined(BOOST_NO_CXX17_INLINE_VARIABLES) |
59 | | template< typename Char, Char Separator, Char PreferredSeparator, Char Dot > |
60 | | BOOST_CONSTEXPR_OR_CONST typename path_constants< Char, Separator, PreferredSeparator, Dot >::value_type |
61 | | path_constants< Char, Separator, PreferredSeparator, Dot >::separator; |
62 | | template< typename Char, Char Separator, Char PreferredSeparator, Char Dot > |
63 | | BOOST_CONSTEXPR_OR_CONST typename path_constants< Char, Separator, PreferredSeparator, Dot >::value_type |
64 | | path_constants< Char, Separator, PreferredSeparator, Dot >::preferred_separator; |
65 | | template< typename Char, Char Separator, Char PreferredSeparator, Char Dot > |
66 | | BOOST_CONSTEXPR_OR_CONST typename path_constants< Char, Separator, PreferredSeparator, Dot >::value_type |
67 | | path_constants< Char, Separator, PreferredSeparator, Dot >::dot; |
68 | | #endif |
69 | | |
70 | | class path_iterator; |
71 | | class path_reverse_iterator; |
72 | | |
73 | | } // namespace path_detail |
74 | | |
75 | | namespace detail { |
76 | | |
77 | | struct path_algorithms |
78 | | { |
79 | | // A struct that denotes a contiguous range of characters in a string. A lightweight alternative to string_view. |
80 | | struct substring |
81 | | { |
82 | | std::size_t pos; |
83 | | std::size_t size; |
84 | | }; |
85 | | |
86 | | typedef path_traits::path_native_char_type value_type; |
87 | | typedef std::basic_string< value_type > string_type; |
88 | | |
89 | | static bool has_filename_v3(path const& p); |
90 | | static bool has_filename_v4(path const& p); |
91 | | BOOST_FILESYSTEM_DECL static path filename_v3(path const& p); |
92 | | static path filename_v4(path const& p); |
93 | | |
94 | | BOOST_FILESYSTEM_DECL static path stem_v3(path const& p); |
95 | | BOOST_FILESYSTEM_DECL static path stem_v4(path const& p); |
96 | | BOOST_FILESYSTEM_DECL static path extension_v3(path const& p); |
97 | | static path extension_v4(path const& p); |
98 | | |
99 | | BOOST_FILESYSTEM_DECL static void remove_filename_v3(path& p); |
100 | | BOOST_FILESYSTEM_DECL static void remove_filename_v4(path& p); |
101 | | |
102 | | BOOST_FILESYSTEM_DECL static void replace_extension_v3(path& p, path const& new_extension); |
103 | | BOOST_FILESYSTEM_DECL static void replace_extension_v4(path& p, path const& new_extension); |
104 | | |
105 | | BOOST_FILESYSTEM_DECL static path lexically_normal_v3(path const& p); |
106 | | BOOST_FILESYSTEM_DECL static path lexically_normal_v4(path const& p); |
107 | | |
108 | | BOOST_FILESYSTEM_DECL static path generic_path_v3(path const& p); |
109 | | BOOST_FILESYSTEM_DECL static path generic_path_v4(path const& p); |
110 | | |
111 | | #if defined(BOOST_FILESYSTEM_WINDOWS_API) |
112 | | BOOST_FILESYSTEM_DECL static void make_preferred_v3(path& p); |
113 | | BOOST_FILESYSTEM_DECL static void make_preferred_v4(path& p); |
114 | | #endif |
115 | | |
116 | | BOOST_FILESYSTEM_DECL static int compare_v3(path const& left, path const& right); |
117 | | BOOST_FILESYSTEM_DECL static int compare_v4(path const& left, path const& right); |
118 | | |
119 | | BOOST_FILESYSTEM_DECL static void append_v3(path& p, const value_type* b, const value_type* e); |
120 | | BOOST_FILESYSTEM_DECL static void append_v4(path& p, const value_type* b, const value_type* e); |
121 | | static void append_v4(path& left, path const& right); |
122 | | |
123 | | // Returns: If separator is to be appended, m_pathname.size() before append. Otherwise 0. |
124 | | // Note: An append is never performed if size()==0, so a returned 0 is unambiguous. |
125 | | BOOST_FILESYSTEM_DECL static string_type::size_type append_separator_if_needed(path& p); |
126 | | BOOST_FILESYSTEM_DECL static void erase_redundant_separator(path& p, string_type::size_type sep_pos); |
127 | | |
128 | | BOOST_FILESYSTEM_DECL static string_type::size_type find_root_name_size(path const& p); |
129 | | BOOST_FILESYSTEM_DECL static string_type::size_type find_root_path_size(path const& p); |
130 | | BOOST_FILESYSTEM_DECL static substring find_root_directory(path const& p); |
131 | | BOOST_FILESYSTEM_DECL static substring find_relative_path(path const& p); |
132 | | BOOST_FILESYSTEM_DECL static string_type::size_type find_parent_path_size(path const& p); |
133 | | BOOST_FILESYSTEM_DECL static string_type::size_type find_filename_v4_size(path const& p); |
134 | | BOOST_FILESYSTEM_DECL static string_type::size_type find_extension_v4_size(path const& p); |
135 | | |
136 | | BOOST_FILESYSTEM_DECL static int lex_compare_v3 |
137 | | ( |
138 | | path_detail::path_iterator first1, path_detail::path_iterator const& last1, |
139 | | path_detail::path_iterator first2, path_detail::path_iterator const& last2 |
140 | | ); |
141 | | BOOST_FILESYSTEM_DECL static int lex_compare_v4 |
142 | | ( |
143 | | path_detail::path_iterator first1, path_detail::path_iterator const& last1, |
144 | | path_detail::path_iterator first2, path_detail::path_iterator const& last2 |
145 | | ); |
146 | | |
147 | | BOOST_FILESYSTEM_DECL static void increment_v3(path_detail::path_iterator& it); |
148 | | BOOST_FILESYSTEM_DECL static void increment_v4(path_detail::path_iterator& it); |
149 | | BOOST_FILESYSTEM_DECL static void decrement_v3(path_detail::path_iterator& it); |
150 | | BOOST_FILESYSTEM_DECL static void decrement_v4(path_detail::path_iterator& it); |
151 | | }; |
152 | | |
153 | | } // namespace detail |
154 | | |
155 | | //------------------------------------------------------------------------------------// |
156 | | // // |
157 | | // class path // |
158 | | // // |
159 | | //------------------------------------------------------------------------------------// |
160 | | |
161 | | class path : |
162 | | public filesystem::path_detail::path_constants< |
163 | | #ifdef BOOST_FILESYSTEM_WINDOWS_API |
164 | | detail::path_traits::path_native_char_type, L'/', L'\\', L'.' |
165 | | #else |
166 | | detail::path_traits::path_native_char_type, '/', '/', '.' |
167 | | #endif |
168 | | > |
169 | | { |
170 | | friend class path_detail::path_iterator; |
171 | | friend class path_detail::path_reverse_iterator; |
172 | | friend struct detail::path_algorithms; |
173 | | |
174 | | public: |
175 | | // value_type is the character type used by the operating system API to |
176 | | // represent paths. |
177 | | |
178 | | typedef detail::path_algorithms::value_type value_type; |
179 | | typedef detail::path_algorithms::string_type string_type; |
180 | | typedef detail::path_traits::codecvt_type codecvt_type; |
181 | | |
182 | | // ----- character encoding conversions ----- |
183 | | |
184 | | // Following the principle of least astonishment, path input arguments |
185 | | // passed to or obtained from the operating system via objects of |
186 | | // class path behave as if they were directly passed to or |
187 | | // obtained from the O/S API, unless conversion is explicitly requested. |
188 | | // |
189 | | // POSIX specfies that path strings are passed unchanged to and from the |
190 | | // API. Note that this is different from the POSIX command line utilities, |
191 | | // which convert according to a locale. |
192 | | // |
193 | | // Thus for POSIX, char strings do not undergo conversion. wchar_t strings |
194 | | // are converted to/from char using the path locale or, if a conversion |
195 | | // argument is given, using a conversion object modeled on |
196 | | // std::wstring_convert. |
197 | | // |
198 | | // The path locale, which is global to the thread, can be changed by the |
199 | | // imbue() function. It is initialized to an implementation defined locale. |
200 | | // |
201 | | // For Windows, wchar_t strings do not undergo conversion. char strings |
202 | | // are converted using the "ANSI" or "OEM" code pages, as determined by |
203 | | // the AreFileApisANSI() function, or, if a conversion argument is given, |
204 | | // using a conversion object modeled on std::wstring_convert. |
205 | | // |
206 | | // See m_pathname comments for further important rationale. |
207 | | |
208 | | // TODO: rules needed for operating systems that use / or . |
209 | | // differently, or format directory paths differently from file paths. |
210 | | // |
211 | | // ********************************************************************************** |
212 | | // |
213 | | // More work needed: How to handle an operating system that may have |
214 | | // slash characters or dot characters in valid filenames, either because |
215 | | // it doesn't follow the POSIX standard, or because it allows MBCS |
216 | | // filename encodings that may contain slash or dot characters. For |
217 | | // example, ISO/IEC 2022 (JIS) encoding which allows switching to |
218 | | // JIS x0208-1983 encoding. A valid filename in this set of encodings is |
219 | | // 0x1B 0x24 0x42 [switch to X0208-1983] 0x24 0x2F [U+304F Kiragana letter KU] |
220 | | // ^^^^ |
221 | | // Note that 0x2F is the ASCII slash character |
222 | | // |
223 | | // ********************************************************************************** |
224 | | |
225 | | // Supported source arguments: half-open iterator range, container, c-array, |
226 | | // and single pointer to null terminated string. |
227 | | |
228 | | // All source arguments except pointers to null terminated byte strings support |
229 | | // multi-byte character strings which may have embedded nulls. Embedded null |
230 | | // support is required for some Asian languages on Windows. |
231 | | |
232 | | // "const codecvt_type& cvt=codecvt()" default arguments are not used because this |
233 | | // limits the impact of locale("") initialization failures on POSIX systems to programs |
234 | | // that actually depend on locale(""). It further ensures that exceptions thrown |
235 | | // as a result of such failues occur after main() has started, so can be caught. |
236 | | |
237 | | private: |
238 | | //! Assignment operation |
239 | | class assign_op |
240 | | { |
241 | | private: |
242 | | path& m_self; |
243 | | |
244 | | public: |
245 | | typedef void result_type; |
246 | | |
247 | 0 | explicit assign_op(path& self) noexcept : m_self(self) {} |
248 | | |
249 | | result_type operator() (const value_type* source, const value_type* source_end, const codecvt_type* = nullptr) const |
250 | 0 | { |
251 | 0 | m_self.m_pathname.assign(source, source_end); |
252 | 0 | } |
253 | | |
254 | | template< typename OtherChar > |
255 | | result_type operator() (const OtherChar* source, const OtherChar* source_end, const codecvt_type* cvt = nullptr) const |
256 | | { |
257 | | m_self.m_pathname.clear(); |
258 | | detail::path_traits::convert(source, source_end, m_self.m_pathname, cvt); |
259 | | } |
260 | | }; |
261 | | |
262 | | //! Concatenation operation |
263 | | class concat_op |
264 | | { |
265 | | private: |
266 | | path& m_self; |
267 | | |
268 | | public: |
269 | | typedef void result_type; |
270 | | |
271 | 0 | explicit concat_op(path& self) noexcept : m_self(self) {} |
272 | | |
273 | | result_type operator() (const value_type* source, const value_type* source_end, const codecvt_type* = nullptr) const |
274 | 0 | { |
275 | 0 | m_self.m_pathname.append(source, source_end); |
276 | 0 | } |
277 | | |
278 | | template< typename OtherChar > |
279 | | result_type operator() (const OtherChar* source, const OtherChar* source_end, const codecvt_type* cvt = nullptr) const |
280 | | { |
281 | | detail::path_traits::convert(source, source_end, m_self.m_pathname, cvt); |
282 | | } |
283 | | }; |
284 | | |
285 | | //! Path appending operation |
286 | | class append_op |
287 | | { |
288 | | private: |
289 | | path& m_self; |
290 | | |
291 | | public: |
292 | | typedef void result_type; |
293 | | |
294 | 0 | explicit append_op(path& self) noexcept : m_self(self) {} |
295 | | |
296 | | BOOST_FORCEINLINE result_type operator() (const value_type* source, const value_type* source_end, const codecvt_type* = nullptr) const |
297 | 0 | { |
298 | 0 | m_self.append(source, source_end); |
299 | 0 | } |
300 | | |
301 | | template< typename OtherChar > |
302 | | BOOST_FORCEINLINE result_type operator() (const OtherChar* source, const OtherChar* source_end, const codecvt_type* cvt = nullptr) const |
303 | | { |
304 | | string_type src; |
305 | | detail::path_traits::convert(source, source_end, src, cvt); |
306 | | m_self.append(src.data(), src.data() + src.size()); |
307 | | } |
308 | | }; |
309 | | |
310 | | //! Path comparison operation |
311 | | class compare_op |
312 | | { |
313 | | private: |
314 | | path const& m_self; |
315 | | |
316 | | public: |
317 | | typedef int result_type; |
318 | | |
319 | 0 | explicit compare_op(path const& self) noexcept : m_self(self) {} |
320 | | |
321 | | result_type operator() (const value_type* source, const value_type* source_end, const codecvt_type* = nullptr) const; |
322 | | |
323 | | template< typename OtherChar > |
324 | | result_type operator() (const OtherChar* source, const OtherChar* source_end, const codecvt_type* cvt = nullptr) const; |
325 | | }; |
326 | | |
327 | | public: |
328 | | typedef path_detail::path_iterator iterator; |
329 | | typedef iterator const_iterator; |
330 | | typedef path_detail::path_reverse_iterator reverse_iterator; |
331 | | typedef reverse_iterator const_reverse_iterator; |
332 | | |
333 | | public: |
334 | | // ----- constructors ----- |
335 | | |
336 | 30.5k | path() noexcept {} |
337 | 4.68k | path(path const& p) : m_pathname(p.m_pathname) {} |
338 | 0 | path(path const& p, codecvt_type const&) : m_pathname(p.m_pathname) {} |
339 | | |
340 | 115 | path(const value_type* s) : m_pathname(s) {} |
341 | 0 | path(const value_type* s, codecvt_type const&) : m_pathname(s) {} |
342 | 0 | path(string_type const& s) : m_pathname(s) {} |
343 | 0 | path(string_type const& s, codecvt_type const&) : m_pathname(s) {} |
344 | | #if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) |
345 | 0 | path(std::basic_string_view< value_type > const& s) : m_pathname(s) {} |
346 | 0 | path(std::basic_string_view< value_type > const& s, codecvt_type const&) : m_pathname(s) {} |
347 | | #endif |
348 | | |
349 | | template< |
350 | | typename Source, |
351 | | typename = typename std::enable_if< |
352 | | detail::conjunction< |
353 | | detail::path_traits::is_path_source< typename std::remove_cv< Source >::type >, |
354 | | detail::negation< detail::path_traits::is_native_path_source< typename std::remove_cv< Source >::type > > |
355 | | >::value |
356 | | >::type |
357 | | > |
358 | | path(Source const& source) |
359 | | { |
360 | | assign(source); |
361 | | } |
362 | | |
363 | | template< |
364 | | typename Source, |
365 | | typename = typename std::enable_if< |
366 | | detail::conjunction< |
367 | | detail::path_traits::is_path_source< typename std::remove_cv< Source >::type >, |
368 | | detail::negation< detail::path_traits::is_native_path_source< typename std::remove_cv< Source >::type > > |
369 | | >::value |
370 | | >::type |
371 | | > |
372 | | explicit path(Source const& source, codecvt_type const& cvt) |
373 | | { |
374 | | assign(source, cvt); |
375 | | } |
376 | | |
377 | | path(path&& p) noexcept : m_pathname(static_cast< string_type&& >(p.m_pathname)) |
378 | 0 | { |
379 | 0 | } |
380 | | path(path&& p, codecvt_type const&) noexcept : m_pathname(static_cast< string_type&& >(p.m_pathname)) |
381 | 0 | { |
382 | 0 | } |
383 | | path& operator=(path&& p) noexcept |
384 | 0 | { |
385 | 0 | m_pathname = static_cast< string_type&& >(p.m_pathname); |
386 | 0 | return *this; |
387 | 0 | } |
388 | | path& assign(path&& p) noexcept |
389 | 0 | { |
390 | 0 | m_pathname = static_cast< string_type&& >(p.m_pathname); |
391 | 0 | return *this; |
392 | 0 | } |
393 | | path& assign(path&& p, codecvt_type const&) noexcept |
394 | 0 | { |
395 | 0 | m_pathname = static_cast< string_type&& >(p.m_pathname); |
396 | 0 | return *this; |
397 | 0 | } |
398 | | |
399 | 2.91k | path(string_type&& s) noexcept : m_pathname(static_cast< string_type&& >(s)) |
400 | 2.91k | { |
401 | 2.91k | } |
402 | | path(string_type&& s, codecvt_type const&) noexcept : m_pathname(static_cast< string_type&& >(s)) |
403 | 0 | { |
404 | 0 | } |
405 | | path& operator=(string_type&& p) noexcept |
406 | 10.4k | { |
407 | 10.4k | m_pathname = static_cast< string_type&& >(p); |
408 | 10.4k | return *this; |
409 | 10.4k | } |
410 | | path& assign(string_type&& p) noexcept |
411 | 0 | { |
412 | 0 | m_pathname = static_cast< string_type&& >(p); |
413 | 0 | return *this; |
414 | 0 | } |
415 | | path& assign(string_type&& p, codecvt_type const&) noexcept |
416 | 0 | { |
417 | 0 | m_pathname = static_cast< string_type&& >(p); |
418 | 0 | return *this; |
419 | 0 | } |
420 | | |
421 | 5.51k | path(const value_type* begin, const value_type* end) : m_pathname(begin, end) {} |
422 | 0 | path(const value_type* begin, const value_type* end, codecvt_type const&) : m_pathname(begin, end) {} |
423 | | |
424 | | template< |
425 | | typename InputIterator, |
426 | | typename = typename std::enable_if< |
427 | | detail::conjunction< |
428 | | detail::path_traits::is_path_source_iterator< InputIterator >, |
429 | | detail::negation< detail::path_traits::is_native_char_ptr< InputIterator > > |
430 | | >::value |
431 | | >::type |
432 | | > |
433 | | path(InputIterator begin, InputIterator end) |
434 | | { |
435 | | if (begin != end) |
436 | | { |
437 | | typedef std::basic_string< typename std::iterator_traits< InputIterator >::value_type > source_t; |
438 | | source_t source(begin, end); |
439 | | assign(static_cast< source_t&& >(source)); |
440 | | } |
441 | | } |
442 | | |
443 | | template< |
444 | | typename InputIterator, |
445 | | typename = typename std::enable_if< |
446 | | detail::conjunction< |
447 | | detail::path_traits::is_path_source_iterator< InputIterator >, |
448 | | detail::negation< detail::path_traits::is_native_char_ptr< InputIterator > > |
449 | | >::value |
450 | | >::type |
451 | | > |
452 | | path(InputIterator begin, InputIterator end, codecvt_type const& cvt) |
453 | | { |
454 | | if (begin != end) |
455 | | { |
456 | | typedef std::basic_string< typename std::iterator_traits< InputIterator >::value_type > source_t; |
457 | | source_t source(begin, end); |
458 | | assign(static_cast< source_t&& >(source), cvt); |
459 | | } |
460 | | } |
461 | | |
462 | | path(std::nullptr_t) = delete; |
463 | | path& operator= (std::nullptr_t) = delete; |
464 | | |
465 | | public: |
466 | | // ----- assignments ----- |
467 | | |
468 | | // We need to explicitly define copy assignment as otherwise it will be implicitly defined as deleted because there is move assignment |
469 | | path& operator=(path const& p); |
470 | | |
471 | | template< typename Source > |
472 | | typename std::enable_if< |
473 | | detail::disjunction< |
474 | | detail::path_traits::is_path_source< typename std::remove_cv< Source >::type >, |
475 | | detail::path_traits::is_convertible_to_path_source< typename std::remove_cv< Source >::type > |
476 | | >::value, |
477 | | path& |
478 | | >::type operator=(Source const& source) |
479 | | { |
480 | | return assign(source); |
481 | | } |
482 | | |
483 | | path& assign(path const& p) |
484 | 0 | { |
485 | 0 | m_pathname = p.m_pathname; |
486 | 0 | return *this; |
487 | 0 | } |
488 | | |
489 | | template< typename Source > |
490 | | typename std::enable_if< |
491 | | detail::path_traits::is_path_source< typename std::remove_cv< Source >::type >::value, |
492 | | path& |
493 | | >::type assign(Source const& source) |
494 | | { |
495 | | detail::path_traits::dispatch(source, assign_op(*this)); |
496 | | return *this; |
497 | | } |
498 | | |
499 | | template< typename Source > |
500 | | typename std::enable_if< |
501 | | detail::conjunction< |
502 | | detail::path_traits::is_convertible_to_path_source< typename std::remove_cv< Source >::type >, |
503 | | detail::negation< detail::path_traits::is_path_source< typename std::remove_cv< Source >::type > > |
504 | | >::value, |
505 | | path& |
506 | | >::type assign(Source const& source) |
507 | | { |
508 | | detail::path_traits::dispatch_convertible(source, assign_op(*this)); |
509 | | return *this; |
510 | | } |
511 | | |
512 | | path& assign(path const& p, codecvt_type const&) |
513 | 0 | { |
514 | 0 | m_pathname = p.m_pathname; |
515 | 0 | return *this; |
516 | 0 | } |
517 | | |
518 | | template< typename Source > |
519 | | typename std::enable_if< |
520 | | detail::path_traits::is_path_source< typename std::remove_cv< Source >::type >::value, |
521 | | path& |
522 | | >::type assign(Source const& source, codecvt_type const& cvt) |
523 | | { |
524 | | detail::path_traits::dispatch(source, assign_op(*this), &cvt); |
525 | | return *this; |
526 | | } |
527 | | |
528 | | template< typename Source > |
529 | | typename std::enable_if< |
530 | | detail::conjunction< |
531 | | detail::path_traits::is_convertible_to_path_source< typename std::remove_cv< Source >::type >, |
532 | | detail::negation< detail::path_traits::is_path_source< typename std::remove_cv< Source >::type > > |
533 | | >::value, |
534 | | path& |
535 | | >::type assign(Source const& source, codecvt_type const& cvt) |
536 | | { |
537 | | detail::path_traits::dispatch_convertible(source, assign_op(*this), &cvt); |
538 | | return *this; |
539 | | } |
540 | | |
541 | | path& assign(const value_type* begin, const value_type* end) |
542 | 126 | { |
543 | 126 | m_pathname.assign(begin, end); |
544 | 126 | return *this; |
545 | 126 | } |
546 | | |
547 | | template< typename InputIterator > |
548 | | typename std::enable_if< |
549 | | detail::conjunction< |
550 | | detail::path_traits::is_path_source_iterator< InputIterator >, |
551 | | detail::negation< detail::path_traits::is_native_char_ptr< InputIterator > > |
552 | | >::value, |
553 | | path& |
554 | | >::type assign(InputIterator begin, InputIterator end) |
555 | | { |
556 | | m_pathname.clear(); |
557 | | if (begin != end) |
558 | | { |
559 | | typedef std::basic_string< typename std::iterator_traits< InputIterator >::value_type > source_t; |
560 | | source_t source(begin, end); |
561 | | assign(static_cast< source_t&& >(source)); |
562 | | } |
563 | | return *this; |
564 | | } |
565 | | |
566 | | path& assign(const value_type* begin, const value_type* end, codecvt_type const&) |
567 | 0 | { |
568 | 0 | m_pathname.assign(begin, end); |
569 | 0 | return *this; |
570 | 0 | } |
571 | | |
572 | | template< typename InputIterator > |
573 | | typename std::enable_if< |
574 | | detail::conjunction< |
575 | | detail::path_traits::is_path_source_iterator< InputIterator >, |
576 | | detail::negation< detail::path_traits::is_native_char_ptr< InputIterator > > |
577 | | >::value, |
578 | | path& |
579 | | >::type assign(InputIterator begin, InputIterator end, codecvt_type const& cvt) |
580 | | { |
581 | | m_pathname.clear(); |
582 | | if (begin != end) |
583 | | { |
584 | | typedef std::basic_string< typename std::iterator_traits< InputIterator >::value_type > source_t; |
585 | | source_t source(begin, end); |
586 | | assign(static_cast< source_t&& >(source), cvt); |
587 | | } |
588 | | return *this; |
589 | | } |
590 | | |
591 | | // ----- concatenation ----- |
592 | | |
593 | | path& operator+=(path const& p); |
594 | | |
595 | | template< typename Source > |
596 | | typename std::enable_if< |
597 | | detail::path_traits::is_convertible_to_path_source< typename std::remove_cv< Source >::type >::value, |
598 | | path& |
599 | | >::type operator+=(Source const& source) |
600 | | { |
601 | | return concat(source); |
602 | | } |
603 | | |
604 | | path& operator+=(value_type c) |
605 | 0 | { |
606 | 0 | m_pathname.push_back(c); |
607 | 0 | return *this; |
608 | 0 | } |
609 | | |
610 | | template< typename CharT > |
611 | | typename std::enable_if< |
612 | | detail::path_traits::is_path_char_type< CharT >::value, |
613 | | path& |
614 | | >::type operator+=(CharT c) |
615 | | { |
616 | | CharT tmp[2]; |
617 | | tmp[0] = c; |
618 | | tmp[1] = static_cast< CharT >(0); |
619 | | concat_op(*this)(tmp, tmp + 1); |
620 | | return *this; |
621 | | } |
622 | | |
623 | | path& concat(path const& p) |
624 | 1.45k | { |
625 | 1.45k | m_pathname.append(p.m_pathname); |
626 | 1.45k | return *this; |
627 | 1.45k | } |
628 | | |
629 | | template< typename Source > |
630 | | typename std::enable_if< |
631 | | detail::path_traits::is_path_source< typename std::remove_cv< Source >::type >::value, |
632 | | path& |
633 | | >::type concat(Source const& source) |
634 | | { |
635 | | detail::path_traits::dispatch(source, concat_op(*this)); |
636 | | return *this; |
637 | | } |
638 | | |
639 | | template< typename Source > |
640 | | typename std::enable_if< |
641 | | detail::conjunction< |
642 | | detail::path_traits::is_convertible_to_path_source< typename std::remove_cv< Source >::type >, |
643 | | detail::negation< detail::path_traits::is_path_source< typename std::remove_cv< Source >::type > > |
644 | | >::value, |
645 | | path& |
646 | | >::type concat(Source const& source) |
647 | | { |
648 | | detail::path_traits::dispatch_convertible(source, concat_op(*this)); |
649 | | return *this; |
650 | | } |
651 | | |
652 | | path& concat(path const& p, codecvt_type const&) |
653 | 0 | { |
654 | 0 | m_pathname.append(p.m_pathname); |
655 | 0 | return *this; |
656 | 0 | } |
657 | | |
658 | | template< typename Source > |
659 | | typename std::enable_if< |
660 | | detail::path_traits::is_path_source< typename std::remove_cv< Source >::type >::value, |
661 | | path& |
662 | | >::type concat(Source const& source, codecvt_type const& cvt) |
663 | | { |
664 | | detail::path_traits::dispatch(source, concat_op(*this), &cvt); |
665 | | return *this; |
666 | | } |
667 | | |
668 | | template< typename Source > |
669 | | typename std::enable_if< |
670 | | detail::conjunction< |
671 | | detail::path_traits::is_convertible_to_path_source< typename std::remove_cv< Source >::type >, |
672 | | detail::negation< detail::path_traits::is_path_source< typename std::remove_cv< Source >::type > > |
673 | | >::value, |
674 | | path& |
675 | | >::type concat(Source const& source, codecvt_type const& cvt) |
676 | | { |
677 | | detail::path_traits::dispatch_convertible(source, concat_op(*this), &cvt); |
678 | | return *this; |
679 | | } |
680 | | |
681 | | path& concat(const value_type* begin, const value_type* end) |
682 | 0 | { |
683 | 0 | m_pathname.append(begin, end); |
684 | 0 | return *this; |
685 | 0 | } |
686 | | |
687 | | template< typename InputIterator > |
688 | | typename std::enable_if< |
689 | | detail::conjunction< |
690 | | detail::path_traits::is_path_source_iterator< InputIterator >, |
691 | | detail::negation< detail::path_traits::is_native_char_ptr< InputIterator > > |
692 | | >::value, |
693 | | path& |
694 | | >::type concat(InputIterator begin, InputIterator end) |
695 | | { |
696 | | if (begin != end) |
697 | | { |
698 | | std::basic_string< typename std::iterator_traits< InputIterator >::value_type > source(begin, end); |
699 | | detail::path_traits::dispatch(source, concat_op(*this)); |
700 | | } |
701 | | return *this; |
702 | | } |
703 | | |
704 | | path& concat(const value_type* begin, const value_type* end, codecvt_type const&) |
705 | 0 | { |
706 | 0 | m_pathname.append(begin, end); |
707 | 0 | return *this; |
708 | 0 | } |
709 | | |
710 | | template< typename InputIterator > |
711 | | typename std::enable_if< |
712 | | detail::conjunction< |
713 | | detail::path_traits::is_path_source_iterator< InputIterator >, |
714 | | detail::negation< detail::path_traits::is_native_char_ptr< InputIterator > > |
715 | | >::value, |
716 | | path& |
717 | | >::type concat(InputIterator begin, InputIterator end, codecvt_type const& cvt) |
718 | | { |
719 | | if (begin != end) |
720 | | { |
721 | | std::basic_string< typename std::iterator_traits< InputIterator >::value_type > source(begin, end); |
722 | | detail::path_traits::dispatch(source, concat_op(*this), &cvt); |
723 | | } |
724 | | return *this; |
725 | | } |
726 | | |
727 | | // ----- appends ----- |
728 | | |
729 | | // if a separator is added, it is the preferred separator for the platform; |
730 | | // slash for POSIX, backslash for Windows |
731 | | |
732 | | path& operator/=(path const& p); |
733 | | |
734 | | template< typename Source > |
735 | | BOOST_FORCEINLINE typename std::enable_if< |
736 | | detail::path_traits::is_convertible_to_path_source< typename std::remove_cv< Source >::type >::value, |
737 | | path& |
738 | | >::type operator/=(Source const& source) |
739 | | { |
740 | | return append(source); |
741 | | } |
742 | | |
743 | | path& append(path const& p); |
744 | | |
745 | | template< typename Source > |
746 | | BOOST_FORCEINLINE typename std::enable_if< |
747 | | detail::path_traits::is_path_source< typename std::remove_cv< Source >::type >::value, |
748 | | path& |
749 | | >::type append(Source const& source) |
750 | | { |
751 | | detail::path_traits::dispatch(source, append_op(*this)); |
752 | | return *this; |
753 | | } |
754 | | |
755 | | template< typename Source > |
756 | | BOOST_FORCEINLINE typename std::enable_if< |
757 | | detail::conjunction< |
758 | | detail::path_traits::is_convertible_to_path_source< typename std::remove_cv< Source >::type >, |
759 | | detail::negation< detail::path_traits::is_path_source< typename std::remove_cv< Source >::type > > |
760 | | >::value, |
761 | | path& |
762 | | >::type append(Source const& source) |
763 | | { |
764 | | detail::path_traits::dispatch_convertible(source, append_op(*this)); |
765 | | return *this; |
766 | | } |
767 | | |
768 | | path& append(path const& p, codecvt_type const&); |
769 | | |
770 | | template< typename Source > |
771 | | BOOST_FORCEINLINE typename std::enable_if< |
772 | | detail::path_traits::is_path_source< typename std::remove_cv< Source >::type >::value, |
773 | | path& |
774 | | >::type append(Source const& source, codecvt_type const& cvt) |
775 | | { |
776 | | detail::path_traits::dispatch(source, append_op(*this), &cvt); |
777 | | return *this; |
778 | | } |
779 | | |
780 | | template< typename Source > |
781 | | BOOST_FORCEINLINE typename std::enable_if< |
782 | | detail::conjunction< |
783 | | detail::path_traits::is_convertible_to_path_source< typename std::remove_cv< Source >::type >, |
784 | | detail::negation< detail::path_traits::is_path_source< typename std::remove_cv< Source >::type > > |
785 | | >::value, |
786 | | path& |
787 | | >::type append(Source const& source, codecvt_type const& cvt) |
788 | | { |
789 | | detail::path_traits::dispatch_convertible(source, append_op(*this), &cvt); |
790 | | return *this; |
791 | | } |
792 | | |
793 | | path& append(const value_type* begin, const value_type* end); |
794 | | |
795 | | template< typename InputIterator > |
796 | | BOOST_FORCEINLINE typename std::enable_if< |
797 | | detail::conjunction< |
798 | | detail::path_traits::is_path_source_iterator< InputIterator >, |
799 | | detail::negation< detail::path_traits::is_native_char_ptr< InputIterator > > |
800 | | >::value, |
801 | | path& |
802 | | >::type append(InputIterator begin, InputIterator end) |
803 | | { |
804 | | std::basic_string< typename std::iterator_traits< InputIterator >::value_type > source(begin, end); |
805 | | detail::path_traits::dispatch(source, append_op(*this)); |
806 | | return *this; |
807 | | } |
808 | | |
809 | | path& append(const value_type* begin, const value_type* end, codecvt_type const&); |
810 | | |
811 | | template< typename InputIterator > |
812 | | BOOST_FORCEINLINE typename std::enable_if< |
813 | | detail::conjunction< |
814 | | detail::path_traits::is_path_source_iterator< InputIterator >, |
815 | | detail::negation< detail::path_traits::is_native_char_ptr< InputIterator > > |
816 | | >::value, |
817 | | path& |
818 | | >::type append(InputIterator begin, InputIterator end, const codecvt_type& cvt) |
819 | | { |
820 | | std::basic_string< typename std::iterator_traits< InputIterator >::value_type > source(begin, end); |
821 | | detail::path_traits::dispatch(source, append_op(*this), &cvt); |
822 | | return *this; |
823 | | } |
824 | | |
825 | | // ----- modifiers ----- |
826 | | |
827 | 1.53k | void clear() noexcept { m_pathname.clear(); } |
828 | | path& make_preferred(); |
829 | | path& remove_filename(); |
830 | | BOOST_FILESYSTEM_DECL path& remove_filename_and_trailing_separators(); |
831 | | BOOST_FILESYSTEM_DECL path& remove_trailing_separator(); |
832 | | BOOST_FILESYSTEM_DECL path& replace_filename(path const& replacement); |
833 | | path& replace_extension(path const& new_extension = path()); |
834 | | |
835 | 728 | void swap(path& rhs) noexcept { m_pathname.swap(rhs.m_pathname); } |
836 | | |
837 | | // ----- observers ----- |
838 | | |
839 | | // For operating systems that format file paths differently than directory |
840 | | // paths, return values from observers are formatted as file names unless there |
841 | | // is a trailing separator, in which case returns are formatted as directory |
842 | | // paths. POSIX and Windows make no such distinction. |
843 | | |
844 | | // Implementations are permitted to return const values or const references. |
845 | | |
846 | | // The string or path returned by an observer are specified as being formatted |
847 | | // as "native" or "generic". |
848 | | // |
849 | | // For POSIX, these are all the same format; slashes and backslashes are as input and |
850 | | // are not modified. |
851 | | // |
852 | | // For Windows, native: as input; slashes and backslashes are not modified; |
853 | | // this is the format of the internally stored string. |
854 | | // generic: backslashes are converted to slashes |
855 | | |
856 | | // ----- native format observers ----- |
857 | | |
858 | 12.2k | string_type const& native() const noexcept { return m_pathname; } |
859 | 246 | const value_type* c_str() const noexcept { return m_pathname.c_str(); } |
860 | 728 | string_type::size_type size() const noexcept { return m_pathname.size(); } |
861 | | |
862 | | template< typename String > |
863 | | String string() const; |
864 | | |
865 | | template< typename String > |
866 | | String string(codecvt_type const& cvt) const; |
867 | | |
868 | | #ifdef BOOST_FILESYSTEM_WINDOWS_API |
869 | | std::string string() const |
870 | | { |
871 | | std::string tmp; |
872 | | if (!m_pathname.empty()) |
873 | | detail::path_traits::convert(m_pathname.data(), m_pathname.data() + m_pathname.size(), tmp); |
874 | | return tmp; |
875 | | } |
876 | | std::string string(codecvt_type const& cvt) const |
877 | | { |
878 | | std::string tmp; |
879 | | if (!m_pathname.empty()) |
880 | | detail::path_traits::convert(m_pathname.data(), m_pathname.data() + m_pathname.size(), tmp, &cvt); |
881 | | return tmp; |
882 | | } |
883 | | |
884 | | // string_type is std::wstring, so there is no conversion |
885 | | std::wstring const& wstring() const { return m_pathname; } |
886 | | std::wstring const& wstring(codecvt_type const&) const { return m_pathname; } |
887 | | #else // BOOST_FILESYSTEM_POSIX_API |
888 | | // string_type is std::string, so there is no conversion |
889 | 0 | std::string const& string() const { return m_pathname; } |
890 | 0 | std::string const& string(codecvt_type const&) const { return m_pathname; } |
891 | | |
892 | | std::wstring wstring() const |
893 | 0 | { |
894 | 0 | std::wstring tmp; |
895 | 0 | if (!m_pathname.empty()) |
896 | 0 | detail::path_traits::convert(m_pathname.data(), m_pathname.data() + m_pathname.size(), tmp); |
897 | 0 | return tmp; |
898 | 0 | } |
899 | | std::wstring wstring(codecvt_type const& cvt) const |
900 | 0 | { |
901 | 0 | std::wstring tmp; |
902 | 0 | if (!m_pathname.empty()) |
903 | 0 | detail::path_traits::convert(m_pathname.data(), m_pathname.data() + m_pathname.size(), tmp, &cvt); |
904 | 0 | return tmp; |
905 | 0 | } |
906 | | #endif |
907 | | |
908 | | // ----- generic format observers ----- |
909 | | |
910 | | // Experimental generic function returning generic formatted path (i.e. separators |
911 | | // are forward slashes). Motivation: simpler than a family of generic_*string |
912 | | // functions. |
913 | | path generic_path() const; |
914 | | |
915 | | template< typename String > |
916 | | String generic_string() const; |
917 | | |
918 | | template< typename String > |
919 | | String generic_string(codecvt_type const& cvt) const; |
920 | | |
921 | 0 | std::string generic_string() const { return generic_path().string(); } |
922 | 0 | std::string generic_string(codecvt_type const& cvt) const { return generic_path().string(cvt); } |
923 | 0 | std::wstring generic_wstring() const { return generic_path().wstring(); } |
924 | 0 | std::wstring generic_wstring(codecvt_type const& cvt) const { return generic_path().wstring(cvt); } |
925 | | |
926 | | // ----- compare ----- |
927 | | |
928 | | int compare(path const& p) const; // generic, lexicographical |
929 | | |
930 | | template< typename Source > |
931 | | BOOST_FORCEINLINE typename std::enable_if< |
932 | | detail::path_traits::is_path_source< typename std::remove_cv< Source >::type >::value, |
933 | | int |
934 | | >::type compare(Source const& source) const |
935 | | { |
936 | | return detail::path_traits::dispatch(source, compare_op(*this)); |
937 | | } |
938 | | |
939 | | template< typename Source > |
940 | | BOOST_FORCEINLINE typename std::enable_if< |
941 | | detail::conjunction< |
942 | | detail::path_traits::is_convertible_to_path_source< typename std::remove_cv< Source >::type >, |
943 | | detail::negation< detail::path_traits::is_path_source< typename std::remove_cv< Source >::type > > |
944 | | >::value, |
945 | | int |
946 | | >::type compare(Source const& source) const |
947 | | { |
948 | | return detail::path_traits::dispatch_convertible(source, compare_op(*this)); |
949 | | } |
950 | | |
951 | | template< typename Source > |
952 | | BOOST_FORCEINLINE typename std::enable_if< |
953 | | detail::path_traits::is_path_source< typename std::remove_cv< Source >::type >::value, |
954 | | int |
955 | | >::type compare(Source const& source, codecvt_type const& cvt) const |
956 | | { |
957 | | return detail::path_traits::dispatch(source, compare_op(*this), &cvt); |
958 | | } |
959 | | |
960 | | template< typename Source > |
961 | | BOOST_FORCEINLINE typename std::enable_if< |
962 | | detail::conjunction< |
963 | | detail::path_traits::is_convertible_to_path_source< typename std::remove_cv< Source >::type >, |
964 | | detail::negation< detail::path_traits::is_path_source< typename std::remove_cv< Source >::type > > |
965 | | >::value, |
966 | | int |
967 | | >::type compare(Source const& source, codecvt_type const& cvt) const |
968 | | { |
969 | | return detail::path_traits::dispatch_convertible(source, compare_op(*this), &cvt); |
970 | | } |
971 | | |
972 | | // ----- decomposition ----- |
973 | | |
974 | 0 | path root_path() const { return path(m_pathname.c_str(), m_pathname.c_str() + detail::path_algorithms::find_root_path_size(*this)); } |
975 | | // returns 0 or 1 element path even on POSIX, root_name() is non-empty() for network paths |
976 | 0 | path root_name() const { return path(m_pathname.c_str(), m_pathname.c_str() + detail::path_algorithms::find_root_name_size(*this)); } |
977 | | |
978 | | // returns 0 or 1 element path |
979 | | path root_directory() const |
980 | 728 | { |
981 | 728 | detail::path_algorithms::substring root_dir = detail::path_algorithms::find_root_directory(*this); |
982 | 728 | const value_type* p = m_pathname.c_str() + root_dir.pos; |
983 | 728 | return path(p, p + root_dir.size); |
984 | 728 | } |
985 | | |
986 | | path relative_path() const |
987 | 728 | { |
988 | 728 | detail::path_algorithms::substring rel_path = detail::path_algorithms::find_relative_path(*this); |
989 | 728 | const value_type* p = m_pathname.c_str() + rel_path.pos; |
990 | 728 | return path(p, p + rel_path.size); |
991 | 728 | } |
992 | | |
993 | 728 | path parent_path() const { return path(m_pathname.c_str(), m_pathname.c_str() + detail::path_algorithms::find_parent_path_size(*this)); } |
994 | | |
995 | | path filename() const; // returns 0 or 1 element path |
996 | | path stem() const; // returns 0 or 1 element path |
997 | | path extension() const; // returns 0 or 1 element path |
998 | | |
999 | | // ----- query ----- |
1000 | | |
1001 | 2.46k | bool empty() const noexcept { return m_pathname.empty(); } |
1002 | | bool filename_is_dot() const; |
1003 | | bool filename_is_dot_dot() const; |
1004 | 0 | bool has_root_path() const { return detail::path_algorithms::find_root_path_size(*this) > 0; } |
1005 | 0 | bool has_root_name() const { return detail::path_algorithms::find_root_name_size(*this) > 0; } |
1006 | 0 | bool has_root_directory() const { return detail::path_algorithms::find_root_directory(*this).size > 0; } |
1007 | 0 | bool has_relative_path() const { return detail::path_algorithms::find_relative_path(*this).size > 0; } |
1008 | 0 | bool has_parent_path() const { return detail::path_algorithms::find_parent_path_size(*this) > 0; } |
1009 | | bool has_filename() const; |
1010 | 728 | bool has_stem() const { return !stem().empty(); } |
1011 | 728 | bool has_extension() const { return !extension().empty(); } |
1012 | 0 | bool is_relative() const { return !is_absolute(); } |
1013 | | bool is_absolute() const |
1014 | 0 | { |
1015 | 0 | #if defined(BOOST_FILESYSTEM_WINDOWS_API) |
1016 | 0 | return has_root_name() && has_root_directory(); |
1017 | 0 | #else |
1018 | 0 | return has_root_directory(); |
1019 | 0 | #endif |
1020 | 0 | } |
1021 | | |
1022 | | // ----- lexical operations ----- |
1023 | | |
1024 | | path lexically_normal() const; |
1025 | | BOOST_FILESYSTEM_DECL path lexically_relative(path const& base) const; |
1026 | | path lexically_proximate(path const& base) const; |
1027 | | |
1028 | | // ----- iterators ----- |
1029 | | |
1030 | | BOOST_FILESYSTEM_DECL iterator begin() const; |
1031 | | BOOST_FILESYSTEM_DECL iterator end() const; |
1032 | | reverse_iterator rbegin() const; |
1033 | | reverse_iterator rend() const; |
1034 | | |
1035 | | // ----- static member functions ----- |
1036 | | |
1037 | | static BOOST_FILESYSTEM_DECL std::locale imbue(std::locale const& loc); |
1038 | | static BOOST_FILESYSTEM_DECL codecvt_type const& codecvt(); |
1039 | | |
1040 | | //--------------------------------------------------------------------------------------// |
1041 | | // class path private members // |
1042 | | //--------------------------------------------------------------------------------------// |
1043 | | private: |
1044 | | /* |
1045 | | * m_pathname has the type, encoding, and format required by the native |
1046 | | * operating system. Thus for POSIX and Windows there is no conversion for |
1047 | | * passing m_pathname.c_str() to the O/S API or when obtaining a path from the |
1048 | | * O/S API. POSIX encoding is unspecified other than for dot and slash |
1049 | | * characters; POSIX just treats paths as a sequence of bytes. Windows |
1050 | | * encoding is UCS-2 or UTF-16 depending on the version. |
1051 | | */ |
1052 | | string_type m_pathname; // Windows: as input; backslashes NOT converted to slashes, |
1053 | | // slashes NOT converted to backslashes |
1054 | | }; |
1055 | | |
1056 | | namespace detail { |
1057 | | BOOST_FILESYSTEM_DECL path const& dot_path(); |
1058 | | BOOST_FILESYSTEM_DECL path const& dot_dot_path(); |
1059 | | } // namespace detail |
1060 | | |
1061 | | namespace path_detail { |
1062 | | |
1063 | | //------------------------------------------------------------------------------------// |
1064 | | // class path::iterator // |
1065 | | //------------------------------------------------------------------------------------// |
1066 | | |
1067 | | class path_iterator : |
1068 | | public boost::iterator_facade< |
1069 | | path_iterator, |
1070 | | const path, |
1071 | | boost::bidirectional_traversal_tag |
1072 | | > |
1073 | | { |
1074 | | private: |
1075 | | friend class boost::iterator_core_access; |
1076 | | friend class boost::filesystem::path; |
1077 | | friend class path_reverse_iterator; |
1078 | | friend struct boost::filesystem::detail::path_algorithms; |
1079 | | |
1080 | 14.3k | path const& dereference() const { return m_element; } |
1081 | | |
1082 | | bool equal(path_iterator const& rhs) const noexcept |
1083 | 24.5k | { |
1084 | 24.5k | return m_path_ptr == rhs.m_path_ptr && m_pos == rhs.m_pos; |
1085 | 24.5k | } |
1086 | | |
1087 | | void increment(); |
1088 | | void decrement(); |
1089 | | |
1090 | | private: |
1091 | | // current element |
1092 | | path m_element; |
1093 | | // path being iterated over |
1094 | | const path* m_path_ptr; |
1095 | | // position of m_element in m_path_ptr->m_pathname. |
1096 | | // if m_element is implicit dot, m_pos is the |
1097 | | // position of the last separator in the path. |
1098 | | // end() iterator is indicated by |
1099 | | // m_pos == m_path_ptr->m_pathname.size() |
1100 | | path::string_type::size_type m_pos; |
1101 | | }; |
1102 | | |
1103 | | //------------------------------------------------------------------------------------// |
1104 | | // class path::reverse_iterator // |
1105 | | //------------------------------------------------------------------------------------// |
1106 | | |
1107 | | class path_reverse_iterator : |
1108 | | public boost::iterator_facade< |
1109 | | path_reverse_iterator, |
1110 | | const path, |
1111 | | boost::bidirectional_traversal_tag |
1112 | | > |
1113 | | { |
1114 | | public: |
1115 | | explicit path_reverse_iterator(path_iterator itr) : |
1116 | | m_itr(itr) |
1117 | 0 | { |
1118 | 0 | if (itr != itr.m_path_ptr->begin()) |
1119 | 0 | m_element = *--itr; |
1120 | 0 | } |
1121 | | |
1122 | | private: |
1123 | | friend class boost::iterator_core_access; |
1124 | | friend class boost::filesystem::path; |
1125 | | |
1126 | 0 | path const& dereference() const { return m_element; } |
1127 | 0 | bool equal(path_reverse_iterator const& rhs) const noexcept { return m_itr == rhs.m_itr; } |
1128 | | |
1129 | | void increment() |
1130 | 0 | { |
1131 | 0 | --m_itr; |
1132 | 0 | if (m_itr != m_itr.m_path_ptr->begin()) |
1133 | 0 | { |
1134 | 0 | path_iterator tmp = m_itr; |
1135 | 0 | m_element = *--tmp; |
1136 | 0 | } |
1137 | 0 | } |
1138 | | |
1139 | | void decrement() |
1140 | 0 | { |
1141 | 0 | m_element = *m_itr; |
1142 | 0 | ++m_itr; |
1143 | 0 | } |
1144 | | |
1145 | | private: |
1146 | | path_iterator m_itr; |
1147 | | path m_element; |
1148 | | }; |
1149 | | |
1150 | | // std::lexicographical_compare would infinitely recurse because path iterators |
1151 | | // yield paths, so provide a path aware version |
1152 | | bool lexicographical_compare(path_iterator first1, path_iterator const& last1, path_iterator first2, path_iterator const& last2); |
1153 | | |
1154 | | } // namespace path_detail |
1155 | | |
1156 | | using path_detail::lexicographical_compare; |
1157 | | |
1158 | | //------------------------------------------------------------------------------------// |
1159 | | // // |
1160 | | // non-member functions // |
1161 | | // // |
1162 | | //------------------------------------------------------------------------------------// |
1163 | | |
1164 | | BOOST_FORCEINLINE bool operator==(path const& lhs, path const& rhs) |
1165 | 0 | { |
1166 | 0 | return lhs.compare(rhs) == 0; |
1167 | 0 | } |
1168 | | |
1169 | | template< typename Path, typename Source > |
1170 | | BOOST_FORCEINLINE typename std::enable_if< |
1171 | | detail::conjunction< |
1172 | | std::is_same< Path, path >, |
1173 | | detail::path_traits::is_convertible_to_path_source< typename std::remove_cv< Source >::type > |
1174 | | >::value, |
1175 | | bool |
1176 | | >::type operator==(Path const& lhs, Source const& rhs) |
1177 | | { |
1178 | | return lhs.compare(rhs) == 0; |
1179 | | } |
1180 | | |
1181 | | template< typename Source, typename Path > |
1182 | | BOOST_FORCEINLINE typename std::enable_if< |
1183 | | detail::conjunction< |
1184 | | std::is_same< Path, path >, |
1185 | | detail::path_traits::is_convertible_to_path_source< typename std::remove_cv< Source >::type > |
1186 | | >::value, |
1187 | | bool |
1188 | | >::type operator==(Source const& lhs, Path const& rhs) |
1189 | | { |
1190 | | return rhs.compare(lhs) == 0; |
1191 | | } |
1192 | | |
1193 | | BOOST_FORCEINLINE bool operator!=(path const& lhs, path const& rhs) |
1194 | 0 | { |
1195 | 0 | return lhs.compare(rhs) != 0; |
1196 | 0 | } |
1197 | | |
1198 | | template< typename Path, typename Source > |
1199 | | BOOST_FORCEINLINE typename std::enable_if< |
1200 | | detail::conjunction< |
1201 | | std::is_same< Path, path >, |
1202 | | detail::path_traits::is_convertible_to_path_source< typename std::remove_cv< Source >::type > |
1203 | | >::value, |
1204 | | bool |
1205 | | >::type operator!=(Path const& lhs, Source const& rhs) |
1206 | | { |
1207 | | return lhs.compare(rhs) != 0; |
1208 | | } |
1209 | | |
1210 | | template< typename Source, typename Path > |
1211 | | BOOST_FORCEINLINE typename std::enable_if< |
1212 | | detail::conjunction< |
1213 | | std::is_same< Path, path >, |
1214 | | detail::path_traits::is_convertible_to_path_source< typename std::remove_cv< Source >::type > |
1215 | | >::value, |
1216 | | bool |
1217 | | >::type operator!=(Source const& lhs, Path const& rhs) |
1218 | | { |
1219 | | return rhs.compare(lhs) != 0; |
1220 | | } |
1221 | | |
1222 | | BOOST_FORCEINLINE bool operator<(path const& lhs, path const& rhs) |
1223 | 0 | { |
1224 | 0 | return lhs.compare(rhs) < 0; |
1225 | 0 | } |
1226 | | |
1227 | | template< typename Path, typename Source > |
1228 | | BOOST_FORCEINLINE typename std::enable_if< |
1229 | | detail::conjunction< |
1230 | | std::is_same< Path, path >, |
1231 | | detail::path_traits::is_convertible_to_path_source< typename std::remove_cv< Source >::type > |
1232 | | >::value, |
1233 | | bool |
1234 | | >::type operator<(Path const& lhs, Source const& rhs) |
1235 | | { |
1236 | | return lhs.compare(rhs) < 0; |
1237 | | } |
1238 | | |
1239 | | template< typename Source, typename Path > |
1240 | | BOOST_FORCEINLINE typename std::enable_if< |
1241 | | detail::conjunction< |
1242 | | std::is_same< Path, path >, |
1243 | | detail::path_traits::is_convertible_to_path_source< typename std::remove_cv< Source >::type > |
1244 | | >::value, |
1245 | | bool |
1246 | | >::type operator<(Source const& lhs, Path const& rhs) |
1247 | | { |
1248 | | return rhs.compare(lhs) > 0; |
1249 | | } |
1250 | | |
1251 | | BOOST_FORCEINLINE bool operator<=(path const& lhs, path const& rhs) |
1252 | 0 | { |
1253 | 0 | return lhs.compare(rhs) <= 0; |
1254 | 0 | } |
1255 | | |
1256 | | template< typename Path, typename Source > |
1257 | | BOOST_FORCEINLINE typename std::enable_if< |
1258 | | detail::conjunction< |
1259 | | std::is_same< Path, path >, |
1260 | | detail::path_traits::is_convertible_to_path_source< typename std::remove_cv< Source >::type > |
1261 | | >::value, |
1262 | | bool |
1263 | | >::type operator<=(Path const& lhs, Source const& rhs) |
1264 | | { |
1265 | | return lhs.compare(rhs) <= 0; |
1266 | | } |
1267 | | |
1268 | | template< typename Source, typename Path > |
1269 | | BOOST_FORCEINLINE typename std::enable_if< |
1270 | | detail::conjunction< |
1271 | | std::is_same< Path, path >, |
1272 | | detail::path_traits::is_convertible_to_path_source< typename std::remove_cv< Source >::type > |
1273 | | >::value, |
1274 | | bool |
1275 | | >::type operator<=(Source const& lhs, Path const& rhs) |
1276 | | { |
1277 | | return rhs.compare(lhs) >= 0; |
1278 | | } |
1279 | | |
1280 | | BOOST_FORCEINLINE bool operator>(path const& lhs, path const& rhs) |
1281 | 0 | { |
1282 | 0 | return lhs.compare(rhs) > 0; |
1283 | 0 | } |
1284 | | |
1285 | | template< typename Path, typename Source > |
1286 | | BOOST_FORCEINLINE typename std::enable_if< |
1287 | | detail::conjunction< |
1288 | | std::is_same< Path, path >, |
1289 | | detail::path_traits::is_convertible_to_path_source< typename std::remove_cv< Source >::type > |
1290 | | >::value, |
1291 | | bool |
1292 | | >::type operator>(Path const& lhs, Source const& rhs) |
1293 | | { |
1294 | | return lhs.compare(rhs) > 0; |
1295 | | } |
1296 | | |
1297 | | template< typename Source, typename Path > |
1298 | | BOOST_FORCEINLINE typename std::enable_if< |
1299 | | detail::conjunction< |
1300 | | std::is_same< Path, path >, |
1301 | | detail::path_traits::is_convertible_to_path_source< typename std::remove_cv< Source >::type > |
1302 | | >::value, |
1303 | | bool |
1304 | | >::type operator>(Source const& lhs, Path const& rhs) |
1305 | | { |
1306 | | return rhs.compare(lhs) < 0; |
1307 | | } |
1308 | | |
1309 | | BOOST_FORCEINLINE bool operator>=(path const& lhs, path const& rhs) |
1310 | 0 | { |
1311 | 0 | return lhs.compare(rhs) >= 0; |
1312 | 0 | } |
1313 | | |
1314 | | template< typename Path, typename Source > |
1315 | | BOOST_FORCEINLINE typename std::enable_if< |
1316 | | detail::conjunction< |
1317 | | std::is_same< Path, path >, |
1318 | | detail::path_traits::is_convertible_to_path_source< typename std::remove_cv< Source >::type > |
1319 | | >::value, |
1320 | | bool |
1321 | | >::type operator>=(Path const& lhs, Source const& rhs) |
1322 | | { |
1323 | | return lhs.compare(rhs) >= 0; |
1324 | | } |
1325 | | |
1326 | | template< typename Source, typename Path > |
1327 | | BOOST_FORCEINLINE typename std::enable_if< |
1328 | | detail::conjunction< |
1329 | | std::is_same< Path, path >, |
1330 | | detail::path_traits::is_convertible_to_path_source< typename std::remove_cv< Source >::type > |
1331 | | >::value, |
1332 | | bool |
1333 | | >::type operator>=(Source const& lhs, Path const& rhs) |
1334 | | { |
1335 | | return rhs.compare(lhs) <= 0; |
1336 | | } |
1337 | | |
1338 | | |
1339 | | // Note: Declared as a template to delay binding to Boost.ContainerHash functions and make the dependency optional |
1340 | | template< typename Path > |
1341 | | inline typename std::enable_if< |
1342 | | std::is_same< Path, path >::value, |
1343 | | std::size_t |
1344 | | >::type hash_value(Path const& p) noexcept |
1345 | | { |
1346 | | #ifdef BOOST_FILESYSTEM_WINDOWS_API |
1347 | | std::size_t seed = 0u; |
1348 | | for (typename Path::value_type const* it = p.c_str(); *it; ++it) |
1349 | | hash_combine(seed, *it == L'/' ? L'\\' : *it); |
1350 | | return seed; |
1351 | | #else // BOOST_FILESYSTEM_POSIX_API |
1352 | | return hash_range(p.native().begin(), p.native().end()); |
1353 | | #endif |
1354 | | } |
1355 | | |
1356 | | inline void swap(path& lhs, path& rhs) noexcept |
1357 | 0 | { |
1358 | 0 | lhs.swap(rhs); |
1359 | 0 | } |
1360 | | |
1361 | | BOOST_FORCEINLINE path operator/(path lhs, path const& rhs) |
1362 | 0 | { |
1363 | 0 | lhs.append(rhs); |
1364 | 0 | return lhs; |
1365 | 0 | } |
1366 | | |
1367 | | template< typename Source > |
1368 | | BOOST_FORCEINLINE typename std::enable_if< |
1369 | | detail::path_traits::is_convertible_to_path_source< typename std::remove_cv< Source >::type >::value, |
1370 | | path |
1371 | | >::type operator/(path lhs, Source const& rhs) |
1372 | | { |
1373 | | lhs.append(rhs); |
1374 | | return lhs; |
1375 | | } |
1376 | | |
1377 | | // inserters and extractors |
1378 | | // use boost::io::quoted() to handle spaces in paths |
1379 | | // use '&' as escape character to ease use for Windows paths |
1380 | | |
1381 | | template< typename Char, typename Traits > |
1382 | | inline std::basic_ostream< Char, Traits >& |
1383 | | operator<<(std::basic_ostream< Char, Traits >& os, path const& p) |
1384 | | { |
1385 | | return os << boost::io::quoted(p.template string< std::basic_string< Char > >(), static_cast< Char >('&')); |
1386 | | } |
1387 | | |
1388 | | template< typename Char, typename Traits > |
1389 | | inline std::basic_istream< Char, Traits >& |
1390 | | operator>>(std::basic_istream< Char, Traits >& is, path& p) |
1391 | | { |
1392 | | std::basic_string< Char > str; |
1393 | | is >> boost::io::quoted(str, static_cast< Char >('&')); |
1394 | | p = str; |
1395 | | return is; |
1396 | | } |
1397 | | |
1398 | | // name_checks |
1399 | | |
1400 | | // These functions are holdovers from version 1. It isn't clear they have much |
1401 | | // usefulness, or how to generalize them for later versions. |
1402 | | |
1403 | | BOOST_FILESYSTEM_DECL bool portable_posix_name(std::string const& name); |
1404 | | BOOST_FILESYSTEM_DECL bool windows_name(std::string const& name); |
1405 | | BOOST_FILESYSTEM_DECL bool portable_name(std::string const& name); |
1406 | | BOOST_FILESYSTEM_DECL bool portable_directory_name(std::string const& name); |
1407 | | BOOST_FILESYSTEM_DECL bool portable_file_name(std::string const& name); |
1408 | | BOOST_FILESYSTEM_DECL bool native(std::string const& name); |
1409 | | |
1410 | | namespace detail { |
1411 | | |
1412 | | // For POSIX, is_directory_separator() and is_element_separator() are identical since |
1413 | | // a forward slash is the only valid directory separator and also the only valid |
1414 | | // element separator. For Windows, forward slash and back slash are the possible |
1415 | | // directory separators, but colon (example: "c:foo") is also an element separator. |
1416 | | inline bool is_directory_separator(path::value_type c) noexcept |
1417 | 41.3k | { |
1418 | 41.3k | return c == path::separator |
1419 | | #ifdef BOOST_FILESYSTEM_WINDOWS_API |
1420 | | || c == path::preferred_separator |
1421 | | #endif |
1422 | 41.3k | ; |
1423 | 41.3k | } |
1424 | | |
1425 | | inline bool is_element_separator(path::value_type c) noexcept |
1426 | 0 | { |
1427 | 0 | return c == path::separator |
1428 | | #ifdef BOOST_FILESYSTEM_WINDOWS_API |
1429 | | || c == path::preferred_separator || c == L':' |
1430 | | #endif |
1431 | 0 | ; |
1432 | 0 | } |
1433 | | |
1434 | | } // namespace detail |
1435 | | |
1436 | | //------------------------------------------------------------------------------------// |
1437 | | // class path miscellaneous function implementations // |
1438 | | //------------------------------------------------------------------------------------// |
1439 | | |
1440 | | namespace detail { |
1441 | | |
1442 | | inline bool path_algorithms::has_filename_v3(path const& p) |
1443 | 0 | { |
1444 | 0 | return !p.m_pathname.empty(); |
1445 | 0 | } |
1446 | | |
1447 | | inline bool path_algorithms::has_filename_v4(path const& p) |
1448 | 470 | { |
1449 | 470 | return path_algorithms::find_filename_v4_size(p) > 0; |
1450 | 470 | } |
1451 | | |
1452 | | inline path path_algorithms::filename_v4(path const& p) |
1453 | 0 | { |
1454 | 0 | string_type::size_type filename_size = path_algorithms::find_filename_v4_size(p); |
1455 | 0 | string_type::size_type pos = p.m_pathname.size() - filename_size; |
1456 | 0 | const value_type* ptr = p.m_pathname.c_str() + pos; |
1457 | 0 | return path(ptr, ptr + filename_size); |
1458 | 0 | } |
1459 | | |
1460 | | inline path path_algorithms::extension_v4(path const& p) |
1461 | 0 | { |
1462 | 0 | string_type::size_type extension_size = path_algorithms::find_extension_v4_size(p); |
1463 | 0 | string_type::size_type pos = p.m_pathname.size() - extension_size; |
1464 | 0 | const value_type* ptr = p.m_pathname.c_str() + pos; |
1465 | 0 | return path(ptr, ptr + extension_size); |
1466 | 0 | } |
1467 | | |
1468 | | inline void path_algorithms::append_v4(path& left, path const& right) |
1469 | 843 | { |
1470 | 843 | path_algorithms::append_v4(left, right.m_pathname.c_str(), right.m_pathname.c_str() + right.m_pathname.size()); |
1471 | 843 | } |
1472 | | |
1473 | | } // namespace detail |
1474 | | |
1475 | | // Note: Because of the range constructor in C++23 std::string_view that involves a check for contiguous_range concept, |
1476 | | // any non-template function call that requires a check whether the source argument (which may be fs::path) |
1477 | | // is convertible to std::string_view must be made after fs::path::iterator is defined. This includes overload |
1478 | | // resolution and SFINAE checks. Otherwise, the concept check result formally changes between fs::path::iterator |
1479 | | // is not defined and defined, which causes compilation errors with gcc 11 and later. |
1480 | | // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106808 |
1481 | | |
1482 | | BOOST_FORCEINLINE path::compare_op::result_type path::compare_op::operator() (const value_type* source, const value_type* source_end, const codecvt_type*) const |
1483 | 0 | { |
1484 | 0 | path src; |
1485 | 0 | src.m_pathname.assign(source, source_end); |
1486 | 0 | return m_self.compare(src); |
1487 | 0 | } |
1488 | | |
1489 | | template< typename OtherChar > |
1490 | | BOOST_FORCEINLINE path::compare_op::result_type path::compare_op::operator() (const OtherChar* source, const OtherChar* source_end, const codecvt_type* cvt) const |
1491 | | { |
1492 | | path src; |
1493 | | detail::path_traits::convert(source, source_end, src.m_pathname, cvt); |
1494 | | return m_self.compare(src); |
1495 | | } |
1496 | | |
1497 | | inline path& path::operator=(path const& p) |
1498 | 0 | { |
1499 | 0 | return assign(p); |
1500 | 0 | } |
1501 | | |
1502 | | inline path& path::operator+=(path const& p) |
1503 | 728 | { |
1504 | 728 | return concat(p); |
1505 | 728 | } |
1506 | | |
1507 | | BOOST_FORCEINLINE path& path::operator/=(path const& p) |
1508 | 728 | { |
1509 | 728 | return append(p); |
1510 | 728 | } |
1511 | | |
1512 | | inline path path::lexically_proximate(path const& base) const |
1513 | 0 | { |
1514 | 0 | path tmp(lexically_relative(base)); |
1515 | 0 | return tmp.empty() ? *this : tmp; |
1516 | 0 | } |
1517 | | |
1518 | | inline path::reverse_iterator path::rbegin() const |
1519 | 0 | { |
1520 | 0 | return reverse_iterator(end()); |
1521 | 0 | } |
1522 | | |
1523 | | inline path::reverse_iterator path::rend() const |
1524 | 0 | { |
1525 | 0 | return reverse_iterator(begin()); |
1526 | 0 | } |
1527 | | |
1528 | | inline bool path::filename_is_dot() const |
1529 | 728 | { |
1530 | | // implicit dot is tricky, so actually call filename(); see path::filename() example |
1531 | | // in reference.html |
1532 | 728 | path p(filename()); |
1533 | 728 | return p.size() == 1 && *p.c_str() == dot; |
1534 | 728 | } |
1535 | | |
1536 | | inline bool path::filename_is_dot_dot() const |
1537 | 0 | { |
1538 | 0 | return size() >= 2 && m_pathname[size() - 1] == dot && m_pathname[size() - 2] == dot && (m_pathname.size() == 2 || detail::is_element_separator(m_pathname[size() - 3])); |
1539 | | // use detail::is_element_separator() rather than detail::is_directory_separator |
1540 | | // to deal with "c:.." edge case on Windows when ':' acts as a separator |
1541 | 0 | } |
1542 | | |
1543 | | // The following functions are defined differently, depending on Boost.Filesystem version in use. |
1544 | | // To avoid ODR violation, these functions are not defined when the library itself is built. |
1545 | | // This makes sure they are not compiled when the library is built, and the only version there is |
1546 | | // is the one in user's code. Users are supposed to consistently use the same Boost.Filesystem version |
1547 | | // in all their translation units. |
1548 | | #if !defined(BOOST_FILESYSTEM_SOURCE) |
1549 | | |
1550 | | BOOST_FORCEINLINE path& path::append(path const& p) |
1551 | 1.45k | { |
1552 | 1.45k | BOOST_FILESYSTEM_VERSIONED_SYM(detail::path_algorithms::append)(*this, p.m_pathname.data(), p.m_pathname.data() + p.m_pathname.size()); |
1553 | 1.45k | return *this; |
1554 | 1.45k | } |
1555 | | |
1556 | | BOOST_FORCEINLINE path& path::append(path const& p, codecvt_type const&) |
1557 | 0 | { |
1558 | 0 | BOOST_FILESYSTEM_VERSIONED_SYM(detail::path_algorithms::append)(*this, p.m_pathname.data(), p.m_pathname.data() + p.m_pathname.size()); |
1559 | 0 | return *this; |
1560 | 0 | } |
1561 | | |
1562 | | BOOST_FORCEINLINE path& path::append(const value_type* begin, const value_type* end) |
1563 | 0 | { |
1564 | 0 | BOOST_FILESYSTEM_VERSIONED_SYM(detail::path_algorithms::append)(*this, begin, end); |
1565 | 0 | return *this; |
1566 | 0 | } |
1567 | | |
1568 | | BOOST_FORCEINLINE path& path::append(const value_type* begin, const value_type* end, codecvt_type const&) |
1569 | 0 | { |
1570 | 0 | BOOST_FILESYSTEM_VERSIONED_SYM(detail::path_algorithms::append)(*this, begin, end); |
1571 | 0 | return *this; |
1572 | 0 | } |
1573 | | |
1574 | | BOOST_FORCEINLINE path& path::remove_filename() |
1575 | 728 | { |
1576 | 728 | BOOST_FILESYSTEM_VERSIONED_SYM(detail::path_algorithms::remove_filename)(*this); |
1577 | 728 | return *this; |
1578 | 728 | } |
1579 | | |
1580 | | BOOST_FORCEINLINE path& path::replace_extension(path const& new_extension) |
1581 | 728 | { |
1582 | 728 | BOOST_FILESYSTEM_VERSIONED_SYM(detail::path_algorithms::replace_extension)(*this, new_extension); |
1583 | 728 | return *this; |
1584 | 728 | } |
1585 | | |
1586 | | BOOST_FORCEINLINE int path::compare(path const& p) const |
1587 | 0 | { |
1588 | 0 | return BOOST_FILESYSTEM_VERSIONED_SYM(detail::path_algorithms::compare)(*this, p); |
1589 | 0 | } |
1590 | | |
1591 | | BOOST_FORCEINLINE path path::filename() const |
1592 | 728 | { |
1593 | 728 | return BOOST_FILESYSTEM_VERSIONED_SYM(detail::path_algorithms::filename)(*this); |
1594 | 728 | } |
1595 | | |
1596 | | BOOST_FORCEINLINE path path::stem() const |
1597 | 728 | { |
1598 | 728 | return BOOST_FILESYSTEM_VERSIONED_SYM(detail::path_algorithms::stem)(*this); |
1599 | 728 | } |
1600 | | |
1601 | | BOOST_FORCEINLINE path path::extension() const |
1602 | 1.45k | { |
1603 | 1.45k | return BOOST_FILESYSTEM_VERSIONED_SYM(detail::path_algorithms::extension)(*this); |
1604 | 1.45k | } |
1605 | | |
1606 | | BOOST_FORCEINLINE bool path::has_filename() const |
1607 | 0 | { |
1608 | 0 | return BOOST_FILESYSTEM_VERSIONED_SYM(detail::path_algorithms::has_filename)(*this); |
1609 | 0 | } |
1610 | | |
1611 | | BOOST_FORCEINLINE path path::lexically_normal() const |
1612 | 0 | { |
1613 | 0 | return BOOST_FILESYSTEM_VERSIONED_SYM(detail::path_algorithms::lexically_normal)(*this); |
1614 | 0 | } |
1615 | | |
1616 | | BOOST_FORCEINLINE path path::generic_path() const |
1617 | 0 | { |
1618 | 0 | return BOOST_FILESYSTEM_VERSIONED_SYM(detail::path_algorithms::generic_path)(*this); |
1619 | 0 | } |
1620 | | |
1621 | | BOOST_FORCEINLINE path& path::make_preferred() |
1622 | 0 | { |
1623 | 0 | // No effect on POSIX |
1624 | 0 | #if defined(BOOST_FILESYSTEM_WINDOWS_API) |
1625 | 0 | BOOST_FILESYSTEM_VERSIONED_SYM(detail::path_algorithms::make_preferred)(*this); |
1626 | 0 | #endif |
1627 | 0 | return *this; |
1628 | 0 | } |
1629 | | |
1630 | | namespace path_detail { |
1631 | | |
1632 | | BOOST_FORCEINLINE void path_iterator::increment() |
1633 | 0 | { |
1634 | 0 | BOOST_FILESYSTEM_VERSIONED_SYM(detail::path_algorithms::increment)(*this); |
1635 | 0 | } |
1636 | | |
1637 | | BOOST_FORCEINLINE void path_iterator::decrement() |
1638 | 0 | { |
1639 | 0 | BOOST_FILESYSTEM_VERSIONED_SYM(detail::path_algorithms::decrement)(*this); |
1640 | 0 | } |
1641 | | |
1642 | | BOOST_FORCEINLINE bool lexicographical_compare(path_iterator first1, path_iterator const& last1, path_iterator first2, path_iterator const& last2) |
1643 | 0 | { |
1644 | 0 | return BOOST_FILESYSTEM_VERSIONED_SYM(detail::path_algorithms::lex_compare)(first1, last1, first2, last2) < 0; |
1645 | 0 | } |
1646 | | |
1647 | | } // namespace path_detail |
1648 | | |
1649 | | #endif // !defined(BOOST_FILESYSTEM_SOURCE) |
1650 | | |
1651 | | //--------------------------------------------------------------------------------------// |
1652 | | // class path member template specializations // |
1653 | | //--------------------------------------------------------------------------------------// |
1654 | | |
1655 | | template< > |
1656 | | inline std::string path::string< std::string >() const |
1657 | 0 | { |
1658 | 0 | return string(); |
1659 | 0 | } |
1660 | | |
1661 | | template< > |
1662 | | inline std::wstring path::string< std::wstring >() const |
1663 | 0 | { |
1664 | 0 | return wstring(); |
1665 | 0 | } |
1666 | | |
1667 | | template< > |
1668 | | inline std::string path::string< std::string >(codecvt_type const& cvt) const |
1669 | 0 | { |
1670 | 0 | return string(cvt); |
1671 | 0 | } |
1672 | | |
1673 | | template< > |
1674 | | inline std::wstring path::string< std::wstring >(codecvt_type const& cvt) const |
1675 | 0 | { |
1676 | 0 | return wstring(cvt); |
1677 | 0 | } |
1678 | | |
1679 | | template< > |
1680 | | inline std::string path::generic_string< std::string >() const |
1681 | 0 | { |
1682 | 0 | return generic_string(); |
1683 | 0 | } |
1684 | | |
1685 | | template< > |
1686 | | inline std::wstring path::generic_string< std::wstring >() const |
1687 | 0 | { |
1688 | 0 | return generic_wstring(); |
1689 | 0 | } |
1690 | | |
1691 | | template< > |
1692 | | inline std::string path::generic_string< std::string >(codecvt_type const& cvt) const |
1693 | 0 | { |
1694 | 0 | return generic_string(cvt); |
1695 | 0 | } |
1696 | | |
1697 | | template< > |
1698 | | inline std::wstring path::generic_string< std::wstring >(codecvt_type const& cvt) const |
1699 | 0 | { |
1700 | 0 | return generic_wstring(cvt); |
1701 | 0 | } |
1702 | | |
1703 | | } // namespace filesystem |
1704 | | } // namespace boost |
1705 | | |
1706 | | //----------------------------------------------------------------------------// |
1707 | | |
1708 | | #include <boost/filesystem/detail/footer.hpp> |
1709 | | |
1710 | | #endif // BOOST_FILESYSTEM_PATH_HPP |