]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // filesystem path.hpp ---------------------------------------------------------------// |
2 | ||
3 | // Copyright Beman Dawes 2002-2005, 2009 | |
4 | // Copyright Vladimir Prus 2002 | |
5 | ||
6 | // Distributed under the Boost Software License, Version 1.0. | |
7 | // See http://www.boost.org/LICENSE_1_0.txt | |
8 | ||
9 | // Library home page: http://www.boost.org/libs/filesystem | |
10 | ||
11 | // path::stem(), extension(), and replace_extension() are based on | |
12 | // basename(), extension(), and change_extension() from the original | |
13 | // filesystem/convenience.hpp header by Vladimir Prus. | |
14 | ||
15 | #ifndef BOOST_FILESYSTEM_PATH_HPP | |
16 | #define BOOST_FILESYSTEM_PATH_HPP | |
17 | ||
18 | #include <boost/config.hpp> | |
19 | ||
20 | # if defined( BOOST_NO_STD_WSTRING ) | |
21 | # error Configuration not supported: Boost.Filesystem V3 and later requires std::wstring support | |
22 | # endif | |
23 | ||
92f5a8d4 | 24 | #include <boost/assert.hpp> |
7c673cae FG |
25 | #include <boost/filesystem/config.hpp> |
26 | #include <boost/filesystem/path_traits.hpp> // includes <cwchar> | |
27 | #include <boost/system/error_code.hpp> | |
28 | #include <boost/system/system_error.hpp> | |
29 | #include <boost/iterator/iterator_facade.hpp> | |
92f5a8d4 TL |
30 | #include <boost/iterator/iterator_categories.hpp> |
31 | #include <boost/core/enable_if.hpp> | |
7c673cae | 32 | #include <boost/io/detail/quoted_manip.hpp> |
7c673cae FG |
33 | #include <boost/functional/hash_fwd.hpp> |
34 | #include <boost/type_traits/is_integral.hpp> | |
35 | #include <string> | |
36 | #include <iterator> | |
37 | #include <cstring> | |
38 | #include <iosfwd> | |
39 | #include <stdexcept> | |
40 | #include <cassert> | |
41 | #include <locale> | |
42 | #include <algorithm> | |
43 | ||
44 | #include <boost/config/abi_prefix.hpp> // must be the last #include | |
45 | ||
46 | namespace boost | |
47 | { | |
48 | namespace filesystem | |
49 | { | |
92f5a8d4 TL |
50 | namespace path_detail // intentionally don't use filesystem::detail to not bring internal Boost.Filesystem functions into ADL via path_constants |
51 | { | |
52 | ||
53 | template< typename Char, Char Separator, Char PreferredSeparator, Char Dot > | |
54 | struct path_constants | |
55 | { | |
56 | typedef path_constants< Char, Separator, PreferredSeparator, Dot > path_constants_base; | |
57 | typedef Char value_type; | |
58 | static BOOST_CONSTEXPR_OR_CONST value_type separator = Separator; | |
59 | static BOOST_CONSTEXPR_OR_CONST value_type preferred_separator = PreferredSeparator; | |
60 | static BOOST_CONSTEXPR_OR_CONST value_type dot = Dot; | |
61 | }; | |
62 | ||
63 | #if defined(BOOST_NO_CXX17_INLINE_VARIABLES) | |
64 | template< typename Char, Char Separator, Char PreferredSeparator, Char Dot > | |
65 | BOOST_CONSTEXPR_OR_CONST typename path_constants< Char, Separator, PreferredSeparator, Dot >::value_type | |
66 | path_constants< Char, Separator, PreferredSeparator, Dot >::separator; | |
67 | template< typename Char, Char Separator, Char PreferredSeparator, Char Dot > | |
68 | BOOST_CONSTEXPR_OR_CONST typename path_constants< Char, Separator, PreferredSeparator, Dot >::value_type | |
69 | path_constants< Char, Separator, PreferredSeparator, Dot >::preferred_separator; | |
70 | template< typename Char, Char Separator, Char PreferredSeparator, Char Dot > | |
71 | BOOST_CONSTEXPR_OR_CONST typename path_constants< Char, Separator, PreferredSeparator, Dot >::value_type | |
72 | path_constants< Char, Separator, PreferredSeparator, Dot >::dot; | |
73 | #endif | |
74 | ||
75 | } // namespace path_detail | |
7c673cae FG |
76 | |
77 | //------------------------------------------------------------------------------------// | |
78 | // // | |
79 | // class path // | |
80 | // // | |
81 | //------------------------------------------------------------------------------------// | |
82 | ||
92f5a8d4 TL |
83 | class path : |
84 | public filesystem::path_detail::path_constants< | |
85 | #ifdef BOOST_WINDOWS_API | |
86 | wchar_t, L'/', L'\\', L'.' | |
87 | #else | |
88 | char, '/', '/', '.' | |
89 | #endif | |
90 | > | |
7c673cae FG |
91 | { |
92 | public: | |
93 | ||
94 | // value_type is the character type used by the operating system API to | |
95 | // represent paths. | |
96 | ||
92f5a8d4 TL |
97 | typedef path_constants_base::value_type value_type; |
98 | typedef std::basic_string<value_type> string_type; | |
7c673cae FG |
99 | typedef std::codecvt<wchar_t, char, |
100 | std::mbstate_t> codecvt_type; | |
101 | ||
102 | ||
103 | // ----- character encoding conversions ----- | |
104 | ||
105 | // Following the principle of least astonishment, path input arguments | |
106 | // passed to or obtained from the operating system via objects of | |
107 | // class path behave as if they were directly passed to or | |
108 | // obtained from the O/S API, unless conversion is explicitly requested. | |
109 | // | |
110 | // POSIX specfies that path strings are passed unchanged to and from the | |
111 | // API. Note that this is different from the POSIX command line utilities, | |
112 | // which convert according to a locale. | |
113 | // | |
114 | // Thus for POSIX, char strings do not undergo conversion. wchar_t strings | |
115 | // are converted to/from char using the path locale or, if a conversion | |
116 | // argument is given, using a conversion object modeled on | |
117 | // std::wstring_convert. | |
118 | // | |
119 | // The path locale, which is global to the thread, can be changed by the | |
120 | // imbue() function. It is initialized to an implementation defined locale. | |
92f5a8d4 | 121 | // |
7c673cae FG |
122 | // For Windows, wchar_t strings do not undergo conversion. char strings |
123 | // are converted using the "ANSI" or "OEM" code pages, as determined by | |
124 | // the AreFileApisANSI() function, or, if a conversion argument is given, | |
125 | // using a conversion object modeled on std::wstring_convert. | |
126 | // | |
127 | // See m_pathname comments for further important rationale. | |
128 | ||
129 | // TODO: rules needed for operating systems that use / or . | |
92f5a8d4 | 130 | // differently, or format directory paths differently from file paths. |
7c673cae FG |
131 | // |
132 | // ********************************************************************************** | |
133 | // | |
134 | // More work needed: How to handle an operating system that may have | |
135 | // slash characters or dot characters in valid filenames, either because | |
136 | // it doesn't follow the POSIX standard, or because it allows MBCS | |
137 | // filename encodings that may contain slash or dot characters. For | |
138 | // example, ISO/IEC 2022 (JIS) encoding which allows switching to | |
139 | // JIS x0208-1983 encoding. A valid filename in this set of encodings is | |
140 | // 0x1B 0x24 0x42 [switch to X0208-1983] 0x24 0x2F [U+304F Kiragana letter KU] | |
141 | // ^^^^ | |
142 | // Note that 0x2F is the ASCII slash character | |
143 | // | |
144 | // ********************************************************************************** | |
145 | ||
146 | // Supported source arguments: half-open iterator range, container, c-array, | |
147 | // and single pointer to null terminated string. | |
148 | ||
149 | // All source arguments except pointers to null terminated byte strings support | |
150 | // multi-byte character strings which may have embedded nulls. Embedded null | |
151 | // support is required for some Asian languages on Windows. | |
152 | ||
153 | // "const codecvt_type& cvt=codecvt()" default arguments are not used because this | |
154 | // limits the impact of locale("") initialization failures on POSIX systems to programs | |
155 | // that actually depend on locale(""). It further ensures that exceptions thrown | |
92f5a8d4 | 156 | // as a result of such failues occur after main() has started, so can be caught. |
7c673cae FG |
157 | |
158 | // ----- constructors ----- | |
159 | ||
92f5a8d4 | 160 | path() BOOST_NOEXCEPT {} |
7c673cae FG |
161 | path(const path& p) : m_pathname(p.m_pathname) {} |
162 | ||
163 | template <class Source> | |
164 | path(Source const& source, | |
165 | typename boost::enable_if<path_traits::is_pathable< | |
166 | typename boost::decay<Source>::type> >::type* =0) | |
167 | { | |
168 | path_traits::dispatch(source, m_pathname); | |
169 | } | |
170 | ||
171 | path(const value_type* s) : m_pathname(s) {} | |
172 | path(value_type* s) : m_pathname(s) {} | |
173 | path(const string_type& s) : m_pathname(s) {} | |
174 | path(string_type& s) : m_pathname(s) {} | |
175 | ||
176 | // As of October 2015 the interaction between noexcept and =default is so troublesome | |
177 | // for VC++, GCC, and probably other compilers, that =default is not used with noexcept | |
178 | // functions. GCC is not even consistent for the same release on different platforms. | |
179 | ||
180 | # if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) | |
92f5a8d4 | 181 | path(path&& p) BOOST_NOEXCEPT : m_pathname(std::move(p.m_pathname)) {} |
7c673cae FG |
182 | path& operator=(path&& p) BOOST_NOEXCEPT |
183 | { m_pathname = std::move(p.m_pathname); return *this; } | |
184 | # endif | |
185 | ||
186 | template <class Source> | |
187 | path(Source const& source, const codecvt_type& cvt) | |
188 | { | |
189 | path_traits::dispatch(source, m_pathname, cvt); | |
190 | } | |
191 | ||
192 | template <class InputIterator> | |
193 | path(InputIterator begin, InputIterator end) | |
92f5a8d4 | 194 | { |
7c673cae FG |
195 | if (begin != end) |
196 | { | |
197 | // convert requires contiguous string, so copy | |
198 | std::basic_string<typename std::iterator_traits<InputIterator>::value_type> | |
199 | seq(begin, end); | |
200 | path_traits::convert(seq.c_str(), seq.c_str()+seq.size(), m_pathname); | |
201 | } | |
202 | } | |
203 | ||
204 | template <class InputIterator> | |
205 | path(InputIterator begin, InputIterator end, const codecvt_type& cvt) | |
92f5a8d4 | 206 | { |
7c673cae FG |
207 | if (begin != end) |
208 | { | |
209 | // convert requires contiguous string, so copy | |
210 | std::basic_string<typename std::iterator_traits<InputIterator>::value_type> | |
211 | seq(begin, end); | |
212 | path_traits::convert(seq.c_str(), seq.c_str()+seq.size(), m_pathname, cvt); | |
213 | } | |
214 | } | |
215 | ||
216 | // ----- assignments ----- | |
217 | ||
218 | path& operator=(const path& p) | |
219 | { | |
220 | m_pathname = p.m_pathname; | |
221 | return *this; | |
222 | } | |
223 | ||
224 | template <class Source> | |
225 | typename boost::enable_if<path_traits::is_pathable< | |
226 | typename boost::decay<Source>::type>, path&>::type | |
227 | operator=(Source const& source) | |
228 | { | |
229 | m_pathname.clear(); | |
230 | path_traits::dispatch(source, m_pathname); | |
231 | return *this; | |
232 | } | |
233 | ||
234 | // value_type overloads | |
235 | ||
236 | path& operator=(const value_type* ptr) // required in case ptr overlaps *this | |
237 | {m_pathname = ptr; return *this;} | |
238 | path& operator=(value_type* ptr) // required in case ptr overlaps *this | |
239 | {m_pathname = ptr; return *this;} | |
240 | path& operator=(const string_type& s) {m_pathname = s; return *this;} | |
241 | path& operator=(string_type& s) {m_pathname = s; return *this;} | |
242 | ||
243 | path& assign(const value_type* ptr, const codecvt_type&) // required in case ptr overlaps *this | |
244 | {m_pathname = ptr; return *this;} | |
245 | template <class Source> | |
246 | path& assign(Source const& source, const codecvt_type& cvt) | |
247 | { | |
248 | m_pathname.clear(); | |
249 | path_traits::dispatch(source, m_pathname, cvt); | |
250 | return *this; | |
251 | } | |
252 | ||
253 | template <class InputIterator> | |
254 | path& assign(InputIterator begin, InputIterator end) | |
255 | { | |
256 | m_pathname.clear(); | |
257 | if (begin != end) | |
258 | { | |
259 | std::basic_string<typename std::iterator_traits<InputIterator>::value_type> | |
260 | seq(begin, end); | |
261 | path_traits::convert(seq.c_str(), seq.c_str()+seq.size(), m_pathname); | |
262 | } | |
263 | return *this; | |
264 | } | |
265 | ||
266 | template <class InputIterator> | |
267 | path& assign(InputIterator begin, InputIterator end, const codecvt_type& cvt) | |
92f5a8d4 | 268 | { |
7c673cae FG |
269 | m_pathname.clear(); |
270 | if (begin != end) | |
271 | { | |
272 | std::basic_string<typename std::iterator_traits<InputIterator>::value_type> | |
273 | seq(begin, end); | |
274 | path_traits::convert(seq.c_str(), seq.c_str()+seq.size(), m_pathname, cvt); | |
275 | } | |
276 | return *this; | |
277 | } | |
278 | ||
279 | // ----- concatenation ----- | |
280 | ||
281 | template <class Source> | |
282 | typename boost::enable_if<path_traits::is_pathable< | |
283 | typename boost::decay<Source>::type>, path&>::type | |
284 | operator+=(Source const& source) | |
285 | { | |
286 | return concat(source); | |
287 | } | |
288 | ||
289 | // value_type overloads. Same rationale as for constructors above | |
290 | path& operator+=(const path& p) { m_pathname += p.m_pathname; return *this; } | |
291 | path& operator+=(const value_type* ptr) { m_pathname += ptr; return *this; } | |
292 | path& operator+=(value_type* ptr) { m_pathname += ptr; return *this; } | |
293 | path& operator+=(const string_type& s) { m_pathname += s; return *this; } | |
294 | path& operator+=(string_type& s) { m_pathname += s; return *this; } | |
295 | path& operator+=(value_type c) { m_pathname += c; return *this; } | |
296 | ||
297 | template <class CharT> | |
92f5a8d4 | 298 | typename boost::enable_if<boost::is_integral<CharT>, path&>::type |
7c673cae FG |
299 | operator+=(CharT c) |
300 | { | |
301 | CharT tmp[2]; | |
302 | tmp[0] = c; | |
303 | tmp[1] = 0; | |
304 | return concat(tmp); | |
305 | } | |
306 | ||
307 | template <class Source> | |
308 | path& concat(Source const& source) | |
309 | { | |
310 | path_traits::dispatch(source, m_pathname); | |
311 | return *this; | |
312 | } | |
313 | ||
314 | template <class Source> | |
315 | path& concat(Source const& source, const codecvt_type& cvt) | |
316 | { | |
317 | path_traits::dispatch(source, m_pathname, cvt); | |
318 | return *this; | |
319 | } | |
320 | ||
321 | template <class InputIterator> | |
322 | path& concat(InputIterator begin, InputIterator end) | |
92f5a8d4 | 323 | { |
7c673cae FG |
324 | if (begin == end) |
325 | return *this; | |
326 | std::basic_string<typename std::iterator_traits<InputIterator>::value_type> | |
327 | seq(begin, end); | |
328 | path_traits::convert(seq.c_str(), seq.c_str()+seq.size(), m_pathname); | |
329 | return *this; | |
330 | } | |
331 | ||
332 | template <class InputIterator> | |
333 | path& concat(InputIterator begin, InputIterator end, const codecvt_type& cvt) | |
92f5a8d4 | 334 | { |
7c673cae FG |
335 | if (begin == end) |
336 | return *this; | |
337 | std::basic_string<typename std::iterator_traits<InputIterator>::value_type> | |
338 | seq(begin, end); | |
339 | path_traits::convert(seq.c_str(), seq.c_str()+seq.size(), m_pathname, cvt); | |
340 | return *this; | |
341 | } | |
342 | ||
343 | // ----- appends ----- | |
344 | ||
345 | // if a separator is added, it is the preferred separator for the platform; | |
346 | // slash for POSIX, backslash for Windows | |
347 | ||
92f5a8d4 | 348 | BOOST_FILESYSTEM_DECL path& operator/=(const path& p); |
7c673cae FG |
349 | |
350 | template <class Source> | |
351 | typename boost::enable_if<path_traits::is_pathable< | |
352 | typename boost::decay<Source>::type>, path&>::type | |
353 | operator/=(Source const& source) | |
354 | { | |
355 | return append(source); | |
356 | } | |
357 | ||
92f5a8d4 | 358 | BOOST_FILESYSTEM_DECL path& operator/=(const value_type* ptr); |
7c673cae FG |
359 | path& operator/=(value_type* ptr) |
360 | { | |
361 | return this->operator/=(const_cast<const value_type*>(ptr)); | |
362 | } | |
363 | path& operator/=(const string_type& s) { return this->operator/=(path(s)); } | |
364 | path& operator/=(string_type& s) { return this->operator/=(path(s)); } | |
365 | ||
366 | path& append(const value_type* ptr) // required in case ptr overlaps *this | |
367 | { | |
368 | this->operator/=(ptr); | |
369 | return *this; | |
370 | } | |
371 | ||
372 | path& append(const value_type* ptr, const codecvt_type&) // required in case ptr overlaps *this | |
373 | { | |
374 | this->operator/=(ptr); | |
375 | return *this; | |
376 | } | |
377 | ||
378 | template <class Source> | |
379 | path& append(Source const& source); | |
380 | ||
381 | template <class Source> | |
382 | path& append(Source const& source, const codecvt_type& cvt); | |
383 | ||
384 | template <class InputIterator> | |
385 | path& append(InputIterator begin, InputIterator end); | |
386 | ||
387 | template <class InputIterator> | |
388 | path& append(InputIterator begin, InputIterator end, const codecvt_type& cvt); | |
389 | ||
390 | // ----- modifiers ----- | |
391 | ||
92f5a8d4 | 392 | void clear() BOOST_NOEXCEPT { m_pathname.clear(); } |
7c673cae | 393 | # ifdef BOOST_POSIX_API |
92f5a8d4 | 394 | path& make_preferred() { return *this; } // POSIX no effect |
7c673cae | 395 | # else // BOOST_WINDOWS_API |
92f5a8d4 | 396 | BOOST_FILESYSTEM_DECL path& make_preferred(); // change slashes to backslashes |
7c673cae | 397 | # endif |
92f5a8d4 TL |
398 | BOOST_FILESYSTEM_DECL path& remove_filename(); |
399 | BOOST_FILESYSTEM_DECL path& remove_trailing_separator(); | |
400 | BOOST_FILESYSTEM_DECL path& replace_extension(const path& new_extension = path()); | |
401 | void swap(path& rhs) BOOST_NOEXCEPT { m_pathname.swap(rhs.m_pathname); } | |
7c673cae FG |
402 | |
403 | // ----- observers ----- | |
92f5a8d4 | 404 | |
7c673cae FG |
405 | // For operating systems that format file paths differently than directory |
406 | // paths, return values from observers are formatted as file names unless there | |
407 | // is a trailing separator, in which case returns are formatted as directory | |
408 | // paths. POSIX and Windows make no such distinction. | |
409 | ||
410 | // Implementations are permitted to return const values or const references. | |
411 | ||
412 | // The string or path returned by an observer are specified as being formatted | |
413 | // as "native" or "generic". | |
414 | // | |
415 | // For POSIX, these are all the same format; slashes and backslashes are as input and | |
416 | // are not modified. | |
417 | // | |
418 | // For Windows, native: as input; slashes and backslashes are not modified; | |
419 | // this is the format of the internally stored string. | |
420 | // generic: backslashes are converted to slashes | |
421 | ||
422 | // ----- native format observers ----- | |
423 | ||
424 | const string_type& native() const BOOST_NOEXCEPT { return m_pathname; } | |
425 | const value_type* c_str() const BOOST_NOEXCEPT { return m_pathname.c_str(); } | |
426 | string_type::size_type size() const BOOST_NOEXCEPT { return m_pathname.size(); } | |
427 | ||
428 | template <class String> | |
429 | String string() const; | |
430 | ||
431 | template <class String> | |
432 | String string(const codecvt_type& cvt) const; | |
433 | ||
434 | # ifdef BOOST_WINDOWS_API | |
435 | const std::string string() const | |
436 | { | |
437 | std::string tmp; | |
438 | if (!m_pathname.empty()) | |
92f5a8d4 | 439 | path_traits::convert(m_pathname.c_str(), m_pathname.c_str()+m_pathname.size(), |
7c673cae FG |
440 | tmp); |
441 | return tmp; | |
442 | } | |
443 | const std::string string(const codecvt_type& cvt) const | |
92f5a8d4 | 444 | { |
7c673cae FG |
445 | std::string tmp; |
446 | if (!m_pathname.empty()) | |
92f5a8d4 | 447 | path_traits::convert(m_pathname.c_str(), m_pathname.c_str()+m_pathname.size(), |
7c673cae FG |
448 | tmp, cvt); |
449 | return tmp; | |
450 | } | |
7c673cae | 451 | |
92f5a8d4 TL |
452 | // string_type is std::wstring, so there is no conversion |
453 | const std::wstring& wstring() const { return m_pathname; } | |
454 | const std::wstring& wstring(const codecvt_type&) const { return m_pathname; } | |
7c673cae FG |
455 | # else // BOOST_POSIX_API |
456 | // string_type is std::string, so there is no conversion | |
92f5a8d4 TL |
457 | const std::string& string() const { return m_pathname; } |
458 | const std::string& string(const codecvt_type&) const { return m_pathname; } | |
7c673cae | 459 | |
92f5a8d4 | 460 | const std::wstring wstring() const |
7c673cae FG |
461 | { |
462 | std::wstring tmp; | |
463 | if (!m_pathname.empty()) | |
92f5a8d4 | 464 | path_traits::convert(m_pathname.c_str(), m_pathname.c_str()+m_pathname.size(), |
7c673cae FG |
465 | tmp); |
466 | return tmp; | |
467 | } | |
92f5a8d4 TL |
468 | const std::wstring wstring(const codecvt_type& cvt) const |
469 | { | |
7c673cae FG |
470 | std::wstring tmp; |
471 | if (!m_pathname.empty()) | |
92f5a8d4 | 472 | path_traits::convert(m_pathname.c_str(), m_pathname.c_str()+m_pathname.size(), |
7c673cae FG |
473 | tmp, cvt); |
474 | return tmp; | |
475 | } | |
7c673cae FG |
476 | # endif |
477 | ||
478 | // ----- generic format observers ----- | |
479 | ||
480 | // Experimental generic function returning generic formatted path (i.e. separators | |
481 | // are forward slashes). Motivation: simpler than a family of generic_*string | |
482 | // functions. | |
7c673cae | 483 | # ifdef BOOST_WINDOWS_API |
92f5a8d4 | 484 | BOOST_FILESYSTEM_DECL path generic_path() const; |
7c673cae | 485 | # else |
92f5a8d4 | 486 | path generic_path() const { return path(*this); } |
7c673cae | 487 | # endif |
7c673cae FG |
488 | |
489 | template <class String> | |
490 | String generic_string() const; | |
491 | ||
492 | template <class String> | |
493 | String generic_string(const codecvt_type& cvt) const; | |
494 | ||
495 | # ifdef BOOST_WINDOWS_API | |
92f5a8d4 TL |
496 | const std::string generic_string() const { return generic_path().string(); } |
497 | const std::string generic_string(const codecvt_type& cvt) const { return generic_path().string(cvt); } | |
498 | const std::wstring generic_wstring() const { return generic_path().wstring(); } | |
499 | const std::wstring generic_wstring(const codecvt_type&) const { return generic_wstring(); } | |
7c673cae FG |
500 | # else // BOOST_POSIX_API |
501 | // On POSIX-like systems, the generic format is the same as the native format | |
502 | const std::string& generic_string() const { return m_pathname; } | |
503 | const std::string& generic_string(const codecvt_type&) const { return m_pathname; } | |
92f5a8d4 TL |
504 | const std::wstring generic_wstring() const { return this->wstring(); } |
505 | const std::wstring generic_wstring(const codecvt_type& cvt) const { return this->wstring(cvt); } | |
7c673cae FG |
506 | # endif |
507 | ||
508 | // ----- compare ----- | |
509 | ||
92f5a8d4 | 510 | BOOST_FILESYSTEM_DECL int compare(const path& p) const BOOST_NOEXCEPT; // generic, lexicographical |
7c673cae FG |
511 | int compare(const std::string& s) const { return compare(path(s)); } |
512 | int compare(const value_type* s) const { return compare(path(s)); } | |
513 | ||
514 | // ----- decomposition ----- | |
515 | ||
92f5a8d4 TL |
516 | BOOST_FILESYSTEM_DECL path root_path() const; |
517 | BOOST_FILESYSTEM_DECL path root_name() const; // returns 0 or 1 element path | |
518 | // even on POSIX, root_name() is non-empty() for network paths | |
519 | BOOST_FILESYSTEM_DECL path root_directory() const; // returns 0 or 1 element path | |
520 | BOOST_FILESYSTEM_DECL path relative_path() const; | |
521 | BOOST_FILESYSTEM_DECL path parent_path() const; | |
522 | BOOST_FILESYSTEM_DECL path filename() const; // returns 0 or 1 element path | |
523 | BOOST_FILESYSTEM_DECL path stem() const; // returns 0 or 1 element path | |
524 | BOOST_FILESYSTEM_DECL path extension() const; // returns 0 or 1 element path | |
7c673cae FG |
525 | |
526 | // ----- query ----- | |
527 | ||
92f5a8d4 | 528 | bool empty() const BOOST_NOEXCEPT { return m_pathname.empty(); } |
b32b8144 FG |
529 | bool filename_is_dot() const; |
530 | bool filename_is_dot_dot() const; | |
7c673cae FG |
531 | bool has_root_path() const { return has_root_directory() || has_root_name(); } |
532 | bool has_root_name() const { return !root_name().empty(); } | |
533 | bool has_root_directory() const { return !root_directory().empty(); } | |
534 | bool has_relative_path() const { return !relative_path().empty(); } | |
535 | bool has_parent_path() const { return !parent_path().empty(); } | |
536 | bool has_filename() const { return !m_pathname.empty(); } | |
537 | bool has_stem() const { return !stem().empty(); } | |
538 | bool has_extension() const { return !extension().empty(); } | |
92f5a8d4 | 539 | bool is_relative() const { return !is_absolute(); } |
7c673cae FG |
540 | bool is_absolute() const |
541 | { | |
92f5a8d4 TL |
542 | // Windows CE has no root name (aka drive letters) |
543 | # if defined(BOOST_WINDOWS_API) && !defined(UNDER_CE) | |
7c673cae FG |
544 | return has_root_name() && has_root_directory(); |
545 | # else | |
546 | return has_root_directory(); | |
547 | # endif | |
548 | } | |
549 | ||
550 | // ----- lexical operations ----- | |
551 | ||
92f5a8d4 TL |
552 | BOOST_FILESYSTEM_DECL path lexically_normal() const; |
553 | BOOST_FILESYSTEM_DECL path lexically_relative(const path& base) const; | |
554 | path lexically_proximate(const path& base) const | |
7c673cae FG |
555 | { |
556 | path tmp(lexically_relative(base)); | |
557 | return tmp.empty() ? *this : tmp; | |
558 | } | |
559 | ||
560 | // ----- iterators ----- | |
561 | ||
562 | class iterator; | |
563 | typedef iterator const_iterator; | |
564 | class reverse_iterator; | |
565 | typedef reverse_iterator const_reverse_iterator; | |
566 | ||
92f5a8d4 TL |
567 | BOOST_FILESYSTEM_DECL iterator begin() const; |
568 | BOOST_FILESYSTEM_DECL iterator end() const; | |
7c673cae FG |
569 | reverse_iterator rbegin() const; |
570 | reverse_iterator rend() const; | |
571 | ||
572 | // ----- static member functions ----- | |
573 | ||
92f5a8d4 TL |
574 | static BOOST_FILESYSTEM_DECL std::locale imbue(const std::locale& loc); |
575 | static BOOST_FILESYSTEM_DECL const codecvt_type& codecvt(); | |
7c673cae FG |
576 | |
577 | // ----- deprecated functions ----- | |
578 | ||
579 | # if defined(BOOST_FILESYSTEM_DEPRECATED) && defined(BOOST_FILESYSTEM_NO_DEPRECATED) | |
580 | # error both BOOST_FILESYSTEM_DEPRECATED and BOOST_FILESYSTEM_NO_DEPRECATED are defined | |
581 | # endif | |
582 | ||
583 | # if !defined(BOOST_FILESYSTEM_NO_DEPRECATED) | |
584 | // recently deprecated functions supplied by default | |
92f5a8d4 | 585 | path& normalize() { |
7c673cae FG |
586 | path tmp(lexically_normal()); |
587 | m_pathname.swap(tmp.m_pathname); | |
588 | return *this; | |
589 | } | |
590 | path& remove_leaf() { return remove_filename(); } | |
591 | path leaf() const { return filename(); } | |
592 | path branch_path() const { return parent_path(); } | |
b32b8144 | 593 | path generic() const { return generic_path(); } |
7c673cae FG |
594 | bool has_leaf() const { return !m_pathname.empty(); } |
595 | bool has_branch_path() const { return !parent_path().empty(); } | |
596 | bool is_complete() const { return is_absolute(); } | |
597 | # endif | |
598 | ||
599 | # if defined(BOOST_FILESYSTEM_DEPRECATED) | |
600 | // deprecated functions with enough signature or semantic changes that they are | |
92f5a8d4 | 601 | // not supplied by default |
7c673cae FG |
602 | const std::string file_string() const { return string(); } |
603 | const std::string directory_string() const { return string(); } | |
604 | const std::string native_file_string() const { return string(); } | |
605 | const std::string native_directory_string() const { return string(); } | |
606 | const string_type external_file_string() const { return native(); } | |
607 | const string_type external_directory_string() const { return native(); } | |
608 | ||
609 | // older functions no longer supported | |
610 | //typedef bool (*name_check)(const std::string & name); | |
611 | //basic_path(const string_type& str, name_check) { operator/=(str); } | |
612 | //basic_path(const typename string_type::value_type* s, name_check) | |
613 | // { operator/=(s);} | |
92f5a8d4 | 614 | //static bool default_name_check_writable() { return false; } |
7c673cae FG |
615 | //static void default_name_check(name_check) {} |
616 | //static name_check default_name_check() { return 0; } | |
617 | //basic_path& canonize(); | |
618 | # endif | |
619 | ||
620 | //--------------------------------------------------------------------------------------// | |
621 | // class path private members // | |
622 | //--------------------------------------------------------------------------------------// | |
623 | ||
624 | private: | |
625 | ||
626 | # if defined(_MSC_VER) | |
627 | # pragma warning(push) // Save warning settings | |
628 | # pragma warning(disable : 4251) // disable warning: class 'std::basic_string<_Elem,_Traits,_Ax>' | |
629 | # endif // needs to have dll-interface... | |
630 | /* | |
631 | m_pathname has the type, encoding, and format required by the native | |
632 | operating system. Thus for POSIX and Windows there is no conversion for | |
633 | passing m_pathname.c_str() to the O/S API or when obtaining a path from the | |
634 | O/S API. POSIX encoding is unspecified other than for dot and slash | |
635 | characters; POSIX just treats paths as a sequence of bytes. Windows | |
636 | encoding is UCS-2 or UTF-16 depending on the version. | |
637 | */ | |
638 | string_type m_pathname; // Windows: as input; backslashes NOT converted to slashes, | |
639 | // slashes NOT converted to backslashes | |
640 | # if defined(_MSC_VER) | |
641 | # pragma warning(pop) // restore warning settings. | |
92f5a8d4 | 642 | # endif |
7c673cae | 643 | |
7c673cae FG |
644 | // Returns: If separator is to be appended, m_pathname.size() before append. Otherwise 0. |
645 | // Note: An append is never performed if size()==0, so a returned 0 is unambiguous. | |
92f5a8d4 | 646 | BOOST_FILESYSTEM_DECL string_type::size_type m_append_separator_if_needed(); |
7c673cae | 647 | |
92f5a8d4 TL |
648 | BOOST_FILESYSTEM_DECL void m_erase_redundant_separator(string_type::size_type sep_pos); |
649 | BOOST_FILESYSTEM_DECL string_type::size_type m_parent_path_end() const; | |
7c673cae FG |
650 | |
651 | // Was qualified; como433beta8 reports: | |
92f5a8d4 | 652 | // warning #427-D: qualified name is not allowed in member declaration |
7c673cae FG |
653 | friend class iterator; |
654 | friend bool operator<(const path& lhs, const path& rhs); | |
655 | ||
656 | // see path::iterator::increment/decrement comment below | |
92f5a8d4 TL |
657 | static BOOST_FILESYSTEM_DECL void m_path_iterator_increment(path::iterator& it); |
658 | static BOOST_FILESYSTEM_DECL void m_path_iterator_decrement(path::iterator& it); | |
7c673cae FG |
659 | |
660 | }; // class path | |
661 | ||
662 | namespace detail | |
663 | { | |
664 | BOOST_FILESYSTEM_DECL | |
665 | int lex_compare(path::iterator first1, path::iterator last1, | |
666 | path::iterator first2, path::iterator last2); | |
667 | BOOST_FILESYSTEM_DECL | |
668 | const path& dot_path(); | |
669 | BOOST_FILESYSTEM_DECL | |
670 | const path& dot_dot_path(); | |
671 | } | |
672 | ||
673 | # ifndef BOOST_FILESYSTEM_NO_DEPRECATED | |
674 | typedef path wpath; | |
675 | # endif | |
676 | ||
677 | //------------------------------------------------------------------------------------// | |
678 | // class path::iterator // | |
679 | //------------------------------------------------------------------------------------// | |
92f5a8d4 | 680 | |
7c673cae FG |
681 | class path::iterator |
682 | : public boost::iterator_facade< | |
683 | path::iterator, | |
684 | path const, | |
685 | boost::bidirectional_traversal_tag > | |
686 | { | |
687 | private: | |
688 | friend class boost::iterator_core_access; | |
689 | friend class boost::filesystem::path; | |
690 | friend class boost::filesystem::path::reverse_iterator; | |
691 | friend void m_path_iterator_increment(path::iterator & it); | |
692 | friend void m_path_iterator_decrement(path::iterator & it); | |
693 | ||
694 | const path& dereference() const { return m_element; } | |
695 | ||
696 | bool equal(const iterator & rhs) const | |
697 | { | |
698 | return m_path_ptr == rhs.m_path_ptr && m_pos == rhs.m_pos; | |
699 | } | |
700 | ||
701 | // iterator_facade derived classes don't seem to like implementations in | |
702 | // separate translation unit dll's, so forward to class path static members | |
703 | void increment() { m_path_iterator_increment(*this); } | |
704 | void decrement() { m_path_iterator_decrement(*this); } | |
705 | ||
706 | path m_element; // current element | |
707 | const path* m_path_ptr; // path being iterated over | |
708 | string_type::size_type m_pos; // position of m_element in | |
709 | // m_path_ptr->m_pathname. | |
710 | // if m_element is implicit dot, m_pos is the | |
711 | // position of the last separator in the path. | |
92f5a8d4 | 712 | // end() iterator is indicated by |
7c673cae FG |
713 | // m_pos == m_path_ptr->m_pathname.size() |
714 | }; // path::iterator | |
715 | ||
716 | //------------------------------------------------------------------------------------// | |
717 | // class path::reverse_iterator // | |
718 | //------------------------------------------------------------------------------------// | |
92f5a8d4 | 719 | |
7c673cae FG |
720 | class path::reverse_iterator |
721 | : public boost::iterator_facade< | |
722 | path::reverse_iterator, | |
723 | path const, | |
724 | boost::bidirectional_traversal_tag > | |
725 | { | |
726 | public: | |
7c673cae FG |
727 | explicit reverse_iterator(iterator itr) : m_itr(itr) |
728 | { | |
729 | if (itr != itr.m_path_ptr->begin()) | |
730 | m_element = *--itr; | |
731 | } | |
92f5a8d4 | 732 | |
7c673cae FG |
733 | private: |
734 | friend class boost::iterator_core_access; | |
735 | friend class boost::filesystem::path; | |
736 | ||
737 | const path& dereference() const { return m_element; } | |
738 | bool equal(const reverse_iterator& rhs) const { return m_itr == rhs.m_itr; } | |
739 | void increment() | |
92f5a8d4 | 740 | { |
7c673cae FG |
741 | --m_itr; |
742 | if (m_itr != m_itr.m_path_ptr->begin()) | |
743 | { | |
744 | iterator tmp = m_itr; | |
745 | m_element = *--tmp; | |
746 | } | |
747 | } | |
748 | void decrement() | |
749 | { | |
750 | m_element = *m_itr; | |
751 | ++m_itr; | |
752 | } | |
753 | ||
754 | iterator m_itr; | |
755 | path m_element; | |
756 | ||
757 | }; // path::reverse_iterator | |
758 | ||
7c673cae FG |
759 | //------------------------------------------------------------------------------------// |
760 | // // | |
761 | // non-member functions // | |
762 | // // | |
763 | //------------------------------------------------------------------------------------// | |
764 | ||
92f5a8d4 | 765 | // std::lexicographical_compare would infinitely recurse because path iterators |
7c673cae FG |
766 | // yield paths, so provide a path aware version |
767 | inline bool lexicographical_compare(path::iterator first1, path::iterator last1, | |
768 | path::iterator first2, path::iterator last2) | |
769 | { return detail::lex_compare(first1, last1, first2, last2) < 0; } | |
92f5a8d4 | 770 | |
7c673cae | 771 | inline bool operator==(const path& lhs, const path& rhs) {return lhs.compare(rhs) == 0;} |
92f5a8d4 | 772 | inline bool operator==(const path& lhs, const path::string_type& rhs) {return lhs.compare(rhs) == 0;} |
7c673cae FG |
773 | inline bool operator==(const path::string_type& lhs, const path& rhs) {return rhs.compare(lhs) == 0;} |
774 | inline bool operator==(const path& lhs, const path::value_type* rhs) {return lhs.compare(rhs) == 0;} | |
775 | inline bool operator==(const path::value_type* lhs, const path& rhs) {return rhs.compare(lhs) == 0;} | |
92f5a8d4 | 776 | |
7c673cae | 777 | inline bool operator!=(const path& lhs, const path& rhs) {return lhs.compare(rhs) != 0;} |
92f5a8d4 | 778 | inline bool operator!=(const path& lhs, const path::string_type& rhs) {return lhs.compare(rhs) != 0;} |
7c673cae FG |
779 | inline bool operator!=(const path::string_type& lhs, const path& rhs) {return rhs.compare(lhs) != 0;} |
780 | inline bool operator!=(const path& lhs, const path::value_type* rhs) {return lhs.compare(rhs) != 0;} | |
781 | inline bool operator!=(const path::value_type* lhs, const path& rhs) {return rhs.compare(lhs) != 0;} | |
782 | ||
783 | // TODO: why do == and != have additional overloads, but the others don't? | |
784 | ||
785 | inline bool operator<(const path& lhs, const path& rhs) {return lhs.compare(rhs) < 0;} | |
786 | inline bool operator<=(const path& lhs, const path& rhs) {return !(rhs < lhs);} | |
787 | inline bool operator> (const path& lhs, const path& rhs) {return rhs < lhs;} | |
788 | inline bool operator>=(const path& lhs, const path& rhs) {return !(lhs < rhs);} | |
789 | ||
92f5a8d4 | 790 | inline std::size_t hash_value(const path& x) BOOST_NOEXCEPT |
7c673cae FG |
791 | { |
792 | # ifdef BOOST_WINDOWS_API | |
793 | std::size_t seed = 0; | |
794 | for(const path::value_type* it = x.c_str(); *it; ++it) | |
92f5a8d4 | 795 | hash_combine(seed, *it == L'/' ? L'\\' : *it); |
7c673cae FG |
796 | return seed; |
797 | # else // BOOST_POSIX_API | |
798 | return hash_range(x.native().begin(), x.native().end()); | |
799 | # endif | |
800 | } | |
801 | ||
92f5a8d4 | 802 | inline void swap(path& lhs, path& rhs) BOOST_NOEXCEPT { lhs.swap(rhs); } |
7c673cae | 803 | |
92f5a8d4 TL |
804 | inline path operator/(const path& lhs, const path& rhs) |
805 | { | |
806 | path p = lhs; | |
807 | p /= rhs; | |
808 | return p; | |
809 | } | |
810 | # if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) | |
811 | inline path operator/(path&& lhs, const path& rhs) | |
812 | { | |
813 | lhs /= rhs; | |
814 | return std::move(lhs); | |
815 | } | |
816 | # endif | |
7c673cae FG |
817 | |
818 | // inserters and extractors | |
819 | // use boost::io::quoted() to handle spaces in paths | |
820 | // use '&' as escape character to ease use for Windows paths | |
821 | ||
822 | template <class Char, class Traits> | |
823 | inline std::basic_ostream<Char, Traits>& | |
824 | operator<<(std::basic_ostream<Char, Traits>& os, const path& p) | |
825 | { | |
826 | return os | |
827 | << boost::io::quoted(p.template string<std::basic_string<Char> >(), static_cast<Char>('&')); | |
828 | } | |
92f5a8d4 | 829 | |
7c673cae FG |
830 | template <class Char, class Traits> |
831 | inline std::basic_istream<Char, Traits>& | |
832 | operator>>(std::basic_istream<Char, Traits>& is, path& p) | |
833 | { | |
834 | std::basic_string<Char> str; | |
835 | is >> boost::io::quoted(str, static_cast<Char>('&')); | |
836 | p = str; | |
837 | return is; | |
838 | } | |
92f5a8d4 | 839 | |
7c673cae FG |
840 | // name_checks |
841 | ||
842 | // These functions are holdovers from version 1. It isn't clear they have much | |
843 | // usefulness, or how to generalize them for later versions. | |
844 | ||
845 | BOOST_FILESYSTEM_DECL bool portable_posix_name(const std::string & name); | |
846 | BOOST_FILESYSTEM_DECL bool windows_name(const std::string & name); | |
847 | BOOST_FILESYSTEM_DECL bool portable_name(const std::string & name); | |
848 | BOOST_FILESYSTEM_DECL bool portable_directory_name(const std::string & name); | |
849 | BOOST_FILESYSTEM_DECL bool portable_file_name(const std::string & name); | |
850 | BOOST_FILESYSTEM_DECL bool native(const std::string & name); | |
b32b8144 FG |
851 | |
852 | namespace detail | |
853 | { | |
854 | // For POSIX, is_directory_separator() and is_element_separator() are identical since | |
855 | // a forward slash is the only valid directory separator and also the only valid | |
856 | // element separator. For Windows, forward slash and back slash are the possible | |
857 | // directory separators, but colon (example: "c:foo") is also an element separator. | |
858 | ||
859 | inline bool is_directory_separator(path::value_type c) BOOST_NOEXCEPT | |
860 | { | |
861 | return c == path::separator | |
862 | # ifdef BOOST_WINDOWS_API | |
863 | || c == path::preferred_separator | |
864 | # endif | |
865 | ; | |
866 | } | |
867 | inline bool is_element_separator(path::value_type c) BOOST_NOEXCEPT | |
868 | { | |
869 | return c == path::separator | |
870 | # ifdef BOOST_WINDOWS_API | |
871 | || c == path::preferred_separator || c == L':' | |
872 | # endif | |
873 | ; | |
874 | } | |
875 | } // namespace detail | |
876 | ||
877 | //------------------------------------------------------------------------------------// | |
878 | // class path miscellaneous function implementations // | |
879 | //------------------------------------------------------------------------------------// | |
880 | ||
881 | inline path::reverse_iterator path::rbegin() const { return reverse_iterator(end()); } | |
882 | inline path::reverse_iterator path::rend() const { return reverse_iterator(begin()); } | |
883 | ||
884 | inline bool path::filename_is_dot() const | |
885 | { | |
886 | // implicit dot is tricky, so actually call filename(); see path::filename() example | |
92f5a8d4 | 887 | // in reference.html |
b32b8144 FG |
888 | path p(filename()); |
889 | return p.size() == 1 && *p.c_str() == dot; | |
890 | } | |
891 | ||
892 | inline bool path::filename_is_dot_dot() const | |
893 | { | |
894 | return size() >= 2 && m_pathname[size()-1] == dot && m_pathname[size()-2] == dot | |
895 | && (m_pathname.size() == 2 || detail::is_element_separator(m_pathname[size()-3])); | |
896 | // use detail::is_element_separator() rather than detail::is_directory_separator | |
897 | // to deal with "c:.." edge case on Windows when ':' acts as a separator | |
898 | } | |
92f5a8d4 | 899 | |
7c673cae FG |
900 | //--------------------------------------------------------------------------------------// |
901 | // class path member template implementation // | |
902 | //--------------------------------------------------------------------------------------// | |
903 | ||
904 | template <class InputIterator> | |
905 | path& path::append(InputIterator begin, InputIterator end) | |
906 | { | |
907 | if (begin == end) | |
908 | return *this; | |
909 | string_type::size_type sep_pos(m_append_separator_if_needed()); | |
910 | std::basic_string<typename std::iterator_traits<InputIterator>::value_type> | |
911 | seq(begin, end); | |
912 | path_traits::convert(seq.c_str(), seq.c_str()+seq.size(), m_pathname); | |
913 | if (sep_pos) | |
914 | m_erase_redundant_separator(sep_pos); | |
915 | return *this; | |
916 | } | |
917 | ||
918 | template <class InputIterator> | |
919 | path& path::append(InputIterator begin, InputIterator end, const codecvt_type& cvt) | |
920 | { | |
921 | if (begin == end) | |
922 | return *this; | |
923 | string_type::size_type sep_pos(m_append_separator_if_needed()); | |
924 | std::basic_string<typename std::iterator_traits<InputIterator>::value_type> | |
925 | seq(begin, end); | |
926 | path_traits::convert(seq.c_str(), seq.c_str()+seq.size(), m_pathname, cvt); | |
927 | if (sep_pos) | |
928 | m_erase_redundant_separator(sep_pos); | |
929 | return *this; | |
930 | } | |
931 | ||
932 | template <class Source> | |
933 | path& path::append(Source const& source) | |
934 | { | |
935 | if (path_traits::empty(source)) | |
936 | return *this; | |
937 | string_type::size_type sep_pos(m_append_separator_if_needed()); | |
938 | path_traits::dispatch(source, m_pathname); | |
939 | if (sep_pos) | |
940 | m_erase_redundant_separator(sep_pos); | |
941 | return *this; | |
942 | } | |
943 | ||
944 | template <class Source> | |
945 | path& path::append(Source const& source, const codecvt_type& cvt) | |
946 | { | |
947 | if (path_traits::empty(source)) | |
948 | return *this; | |
949 | string_type::size_type sep_pos(m_append_separator_if_needed()); | |
950 | path_traits::dispatch(source, m_pathname, cvt); | |
951 | if (sep_pos) | |
952 | m_erase_redundant_separator(sep_pos); | |
953 | return *this; | |
954 | } | |
955 | ||
956 | //--------------------------------------------------------------------------------------// | |
957 | // class path member template specializations // | |
958 | //--------------------------------------------------------------------------------------// | |
959 | ||
960 | template <> inline | |
961 | std::string path::string<std::string>() const | |
962 | { return string(); } | |
963 | ||
964 | template <> inline | |
965 | std::wstring path::string<std::wstring>() const | |
966 | { return wstring(); } | |
967 | ||
968 | template <> inline | |
969 | std::string path::string<std::string>(const codecvt_type& cvt) const | |
970 | { return string(cvt); } | |
971 | ||
972 | template <> inline | |
973 | std::wstring path::string<std::wstring>(const codecvt_type& cvt) const | |
974 | { return wstring(cvt); } | |
975 | ||
976 | template <> inline | |
977 | std::string path::generic_string<std::string>() const | |
978 | { return generic_string(); } | |
979 | ||
980 | template <> inline | |
981 | std::wstring path::generic_string<std::wstring>() const | |
982 | { return generic_wstring(); } | |
983 | ||
984 | template <> inline | |
985 | std::string path::generic_string<std::string>(const codecvt_type& cvt) const | |
986 | { return generic_string(cvt); } | |
987 | ||
988 | template <> inline | |
989 | std::wstring path::generic_string<std::wstring>(const codecvt_type& cvt) const | |
990 | { return generic_wstring(cvt); } | |
991 | ||
992 | //--------------------------------------------------------------------------------------// | |
993 | // path_traits convert function implementations // | |
994 | // requiring path::codecvt() be visable // | |
995 | //--------------------------------------------------------------------------------------// | |
996 | ||
997 | namespace path_traits | |
998 | { // without codecvt | |
999 | ||
1000 | inline | |
1001 | void convert(const char* from, | |
1002 | const char* from_end, // 0 for null terminated MBCS | |
1003 | std::wstring & to) | |
1004 | { | |
1005 | convert(from, from_end, to, path::codecvt()); | |
1006 | } | |
1007 | ||
1008 | inline | |
1009 | void convert(const wchar_t* from, | |
1010 | const wchar_t* from_end, // 0 for null terminated MBCS | |
1011 | std::string & to) | |
1012 | { | |
1013 | convert(from, from_end, to, path::codecvt()); | |
1014 | } | |
1015 | ||
1016 | inline | |
1017 | void convert(const char* from, | |
1018 | std::wstring & to) | |
1019 | { | |
92f5a8d4 | 1020 | BOOST_ASSERT(!!from); |
7c673cae FG |
1021 | convert(from, 0, to, path::codecvt()); |
1022 | } | |
1023 | ||
1024 | inline | |
1025 | void convert(const wchar_t* from, | |
1026 | std::string & to) | |
1027 | { | |
92f5a8d4 | 1028 | BOOST_ASSERT(!!from); |
7c673cae FG |
1029 | convert(from, 0, to, path::codecvt()); |
1030 | } | |
1031 | } // namespace path_traits | |
1032 | } // namespace filesystem | |
1033 | } // namespace boost | |
1034 | ||
1035 | //----------------------------------------------------------------------------// | |
1036 | ||
1037 | #include <boost/config/abi_suffix.hpp> // pops abi_prefix.hpp pragmas | |
1038 | ||
1039 | #endif // BOOST_FILESYSTEM_PATH_HPP |