blob: 8dee66fbe0bc379b15a05dd5063ce758bf748600 [file] [log] [blame]
Jeff Thompson86b6d642013-10-17 15:01:56 -07001// 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 NDNBOOST_FILESYSTEM_PATH_HPP
16#define NDNBOOST_FILESYSTEM_PATH_HPP
17
18#include <ndnboost/config.hpp>
19
20# if defined( NDNBOOST_NO_STD_WSTRING )
21# error Configuration not supported: Boost.Filesystem V3 and later requires std::wstring support
22# endif
23
24#include <ndnboost/filesystem/config.hpp>
25#include <ndnboost/filesystem/path_traits.hpp> // includes <cwchar>
26#include <ndnboost/system/error_code.hpp>
27#include <ndnboost/system/system_error.hpp>
28#include <ndnboost/iterator/iterator_facade.hpp>
29#include <ndnboost/shared_ptr.hpp>
30#include <ndnboost/io/detail/quoted_manip.hpp>
31#include <ndnboost/static_assert.hpp>
32#include <ndnboost/functional/hash_fwd.hpp>
33#include <ndnboost/type_traits/is_integral.hpp>
34#include <string>
35#include <iterator>
36#include <cstring>
37#include <iosfwd>
38#include <stdexcept>
39#include <cassert>
40#include <locale>
41#include <algorithm>
42
43#include <ndnboost/config/abi_prefix.hpp> // must be the last #include
44
45namespace ndnboost
46{
47namespace filesystem
48{
49 //------------------------------------------------------------------------------------//
50 // //
51 // class path //
52 // //
53 //------------------------------------------------------------------------------------//
54
55 class NDNBOOST_FILESYSTEM_DECL path
56 {
57 public:
58
59 // value_type is the character type used by the operating system API to
60 // represent paths.
61
62# ifdef NDNBOOST_WINDOWS_API
63 typedef wchar_t value_type;
64 NDNBOOST_STATIC_CONSTEXPR value_type preferred_separator = L'\\';
65# else
66 typedef char value_type;
67 NDNBOOST_STATIC_CONSTEXPR value_type preferred_separator = '/';
68# endif
69 typedef std::basic_string<value_type> string_type;
70 typedef std::codecvt<wchar_t, char,
71 std::mbstate_t> codecvt_type;
72
73
74 // ----- character encoding conversions -----
75
76 // Following the principle of least astonishment, path input arguments
77 // passed to or obtained from the operating system via objects of
78 // class path behave as if they were directly passed to or
79 // obtained from the O/S API, unless conversion is explicitly requested.
80 //
81 // POSIX specfies that path strings are passed unchanged to and from the
82 // API. Note that this is different from the POSIX command line utilities,
83 // which convert according to a locale.
84 //
85 // Thus for POSIX, char strings do not undergo conversion. wchar_t strings
86 // are converted to/from char using the path locale or, if a conversion
87 // argument is given, using a conversion object modeled on
88 // std::wstring_convert.
89 //
90 // The path locale, which is global to the thread, can be changed by the
91 // imbue() function. It is initialized to an implementation defined locale.
92 //
93 // For Windows, wchar_t strings do not undergo conversion. char strings
94 // are converted using the "ANSI" or "OEM" code pages, as determined by
95 // the AreFileApisANSI() function, or, if a conversion argument is given,
96 // using a conversion object modeled on std::wstring_convert.
97 //
98 // See m_pathname comments for further important rationale.
99
100 // TODO: rules needed for operating systems that use / or .
101 // differently, or format directory paths differently from file paths.
102 //
103 // **********************************************************************************
104 //
105 // More work needed: How to handle an operating system that may have
106 // slash characters or dot characters in valid filenames, either because
107 // it doesn't follow the POSIX standard, or because it allows MBCS
108 // filename encodings that may contain slash or dot characters. For
109 // example, ISO/IEC 2022 (JIS) encoding which allows switching to
110 // JIS x0208-1983 encoding. A valid filename in this set of encodings is
111 // 0x1B 0x24 0x42 [switch to X0208-1983] 0x24 0x2F [U+304F Kiragana letter KU]
112 // ^^^^
113 // Note that 0x2F is the ASCII slash character
114 //
115 // **********************************************************************************
116
117 // Supported source arguments: half-open iterator range, container, c-array,
118 // and single pointer to null terminated string.
119
120 // All source arguments except pointers to null terminated byte strings support
121 // multi-byte character strings which may have embedded nulls. Embedded null
122 // support is required for some Asian languages on Windows.
123
124 // [defaults] "const codecvt_type& cvt=codecvt()" default arguments are not used
125 // because some compilers, such as Microsoft prior to VC++ 10, do not handle defaults
126 // correctly in templates.
127
128 // ----- constructors -----
129
130 path(){}
131
132 path(const path& p) : m_pathname(p.m_pathname) {}
133
134 template <class Source>
135 path(Source const& source,
136 typename ndnboost::enable_if<path_traits::is_pathable<
137 typename ndnboost::decay<Source>::type> >::type* =0)
138 {
139 path_traits::dispatch(source, m_pathname, codecvt());
140 }
141
142 // Overloads for the operating system API's native character type. Rationale:
143 // - Avoids use of codecvt() for native value_type strings. This limits the
144 // impact of locale("") initialization failures on POSIX systems to programs
145 // that actually depend on locale(""). It further ensures that exceptions thrown
146 // as a result of such failues occur after main() has started, so can be caught.
147 // This is a partial resolution of tickets 4688, 5100, and 5289.
148 // - A slight optimization for a common use case, particularly on POSIX since
149 // value_type is char and that is the most common useage.
150 path(const value_type* s) : m_pathname(s) {}
151 path(const std::basic_string<value_type>& s) : m_pathname(s) {}
152
153 template <class Source>
154 path(Source const& source, const codecvt_type& cvt)
155 // see [defaults] note above explaining why codecvt() default arguments are not used
156 {
157 path_traits::dispatch(source, m_pathname, cvt);
158 }
159
160 template <class InputIterator>
161 path(InputIterator begin, InputIterator end)
162 {
163 if (begin != end)
164 {
165 std::basic_string<typename std::iterator_traits<InputIterator>::value_type>
166 s(begin, end);
167 path_traits::convert(s.c_str(), s.c_str()+s.size(), m_pathname, codecvt());
168 }
169 }
170
171 template <class InputIterator>
172 path(InputIterator begin, InputIterator end, const codecvt_type& cvt)
173 {
174 if (begin != end)
175 {
176 std::basic_string<typename std::iterator_traits<InputIterator>::value_type>
177 s(begin, end);
178 path_traits::convert(s.c_str(), s.c_str()+s.size(), m_pathname, cvt);
179 }
180 }
181
182 // ----- assignments -----
183
184 path& operator=(const path& p)
185 {
186 m_pathname = p.m_pathname;
187 return *this;
188 }
189
190 path& operator=(const value_type* ptr) // required in case ptr overlaps *this
191 {
192 m_pathname = ptr;
193 return *this;
194 }
195
196 template <class Source>
197 typename ndnboost::enable_if<path_traits::is_pathable<
198 typename ndnboost::decay<Source>::type>, path&>::type
199 operator=(Source const& source)
200 {
201 m_pathname.clear();
202 path_traits::dispatch(source, m_pathname, codecvt());
203 return *this;
204 }
205
206 path& assign(const value_type* ptr, const codecvt_type&) // required in case ptr overlaps *this
207 {
208 m_pathname = ptr;
209 return *this;
210 }
211
212 template <class Source>
213 path& assign(Source const& source, const codecvt_type& cvt)
214 {
215 m_pathname.clear();
216 path_traits::dispatch(source, m_pathname, cvt);
217 return *this;
218 }
219
220 template <class InputIterator>
221 path& assign(InputIterator begin, InputIterator end)
222 {
223 return assign(begin, end, codecvt());
224 }
225
226 template <class InputIterator>
227 path& assign(InputIterator begin, InputIterator end, const codecvt_type& cvt)
228 {
229 m_pathname.clear();
230 if (begin != end)
231 {
232 std::basic_string<typename std::iterator_traits<InputIterator>::value_type>
233 s(begin, end);
234 path_traits::convert(s.c_str(), s.c_str()+s.size(), m_pathname, cvt);
235 }
236 return *this;
237 }
238
239 // ----- concatenation -----
240
241 path& operator+=(const path& p) {m_pathname += p.m_pathname; return *this;}
242 path& operator+=(const string_type& s) {m_pathname += s; return *this;}
243 path& operator+=(const value_type* ptr) {m_pathname += ptr; return *this;}
244 path& operator+=(value_type c) {m_pathname += c; return *this;}
245
246 template <class Source>
247 typename ndnboost::enable_if<path_traits::is_pathable<
248 typename ndnboost::decay<Source>::type>, path&>::type
249 operator+=(Source const& source)
250 {
251 return concat(source, codecvt());
252 }
253
254 template <class CharT>
255 typename ndnboost::enable_if<is_integral<CharT>, path&>::type
256 operator+=(CharT c)
257 {
258 CharT tmp[2];
259 tmp[0] = c;
260 tmp[1] = 0;
261 return concat(tmp, codecvt());
262 }
263
264 template <class Source>
265 path& concat(Source const& source, const codecvt_type& cvt)
266 {
267 path_traits::dispatch(source, m_pathname, cvt);
268 return *this;
269 }
270
271 template <class InputIterator>
272 path& concat(InputIterator begin, InputIterator end)
273 {
274 return concat(begin, end, codecvt());
275 }
276
277 template <class InputIterator>
278 path& concat(InputIterator begin, InputIterator end, const codecvt_type& cvt)
279 {
280 if (begin == end)
281 return *this;
282 std::basic_string<typename std::iterator_traits<InputIterator>::value_type>
283 s(begin, end);
284 path_traits::convert(s.c_str(), s.c_str()+s.size(), m_pathname, cvt);
285 return *this;
286 }
287
288 // ----- appends -----
289
290 // if a separator is added, it is the preferred separator for the platform;
291 // slash for POSIX, backslash for Windows
292
293 path& operator/=(const path& p);
294
295 path& operator/=(const value_type* ptr);
296
297 template <class Source>
298 typename ndnboost::enable_if<path_traits::is_pathable<
299 typename ndnboost::decay<Source>::type>, path&>::type
300 operator/=(Source const& source)
301 {
302 return append(source, codecvt());
303 }
304
305 path& append(const value_type* ptr, const codecvt_type&) // required in case ptr overlaps *this
306 {
307 this->operator/=(ptr);
308 return *this;
309 }
310
311 template <class Source>
312 path& append(Source const& source, const codecvt_type& cvt);
313
314 template <class InputIterator>
315 path& append(InputIterator begin, InputIterator end)
316 {
317 return append(begin, end, codecvt());
318 }
319
320 template <class InputIterator>
321 path& append(InputIterator begin, InputIterator end, const codecvt_type& cvt);
322
323 // ----- modifiers -----
324
325 void clear() { m_pathname.clear(); }
326 path& make_preferred()
327# ifdef NDNBOOST_POSIX_API
328 { return *this; } // POSIX no effect
329# else // NDNBOOST_WINDOWS_API
330 ; // change slashes to backslashes
331# endif
332 path& remove_filename();
333 path& replace_extension(const path& new_extension = path());
334 void swap(path& rhs) { m_pathname.swap(rhs.m_pathname); }
335
336 // ----- observers -----
337
338 // For operating systems that format file paths differently than directory
339 // paths, return values from observers are formatted as file names unless there
340 // is a trailing separator, in which case returns are formatted as directory
341 // paths. POSIX and Windows make no such distinction.
342
343 // Implementations are permitted to return const values or const references.
344
345 // The string or path returned by an observer are specified as being formatted
346 // as "native" or "generic".
347 //
348 // For POSIX, these are all the same format; slashes and backslashes are as input and
349 // are not modified.
350 //
351 // For Windows, native: as input; slashes and backslashes are not modified;
352 // this is the format of the internally stored string.
353 // generic: backslashes are converted to slashes
354
355 // ----- native format observers -----
356
357 const string_type& native() const { return m_pathname; } // Throws: nothing
358 const value_type* c_str() const { return m_pathname.c_str(); } // Throws: nothing
359
360 template <class String>
361 String string() const;
362
363 template <class String>
364 String string(const codecvt_type& cvt) const;
365
366# ifdef NDNBOOST_WINDOWS_API
367 const std::string string() const { return string(codecvt()); }
368 const std::string string(const codecvt_type& cvt) const
369 {
370 std::string tmp;
371 if (!m_pathname.empty())
372 path_traits::convert(&*m_pathname.begin(), &*m_pathname.begin()+m_pathname.size(),
373 tmp, cvt);
374 return tmp;
375 }
376
377 // string_type is std::wstring, so there is no conversion
378 const std::wstring& wstring() const { return m_pathname; }
379 const std::wstring& wstring(const codecvt_type&) const { return m_pathname; }
380
381# else // NDNBOOST_POSIX_API
382 // string_type is std::string, so there is no conversion
383 const std::string& string() const { return m_pathname; }
384 const std::string& string(const codecvt_type&) const { return m_pathname; }
385
386 const std::wstring wstring() const { return wstring(codecvt()); }
387 const std::wstring wstring(const codecvt_type& cvt) const
388 {
389 std::wstring tmp;
390 if (!m_pathname.empty())
391 path_traits::convert(&*m_pathname.begin(), &*m_pathname.begin()+m_pathname.size(),
392 tmp, cvt);
393 return tmp;
394 }
395
396# endif
397
398 // ----- generic format observers -----
399
400 template <class String>
401 String generic_string() const;
402
403 template <class String>
404 String generic_string(const codecvt_type& cvt) const;
405
406# ifdef NDNBOOST_WINDOWS_API
407 const std::string generic_string() const { return generic_string(codecvt()); }
408 const std::string generic_string(const codecvt_type& cvt) const;
409 const std::wstring generic_wstring() const;
410 const std::wstring generic_wstring(const codecvt_type&) const { return generic_wstring(); };
411
412# else // NDNBOOST_POSIX_API
413 // On POSIX-like systems, the generic format is the same as the native format
414 const std::string& generic_string() const { return m_pathname; }
415 const std::string& generic_string(const codecvt_type&) const { return m_pathname; }
416 const std::wstring generic_wstring() const { return wstring(codecvt()); }
417 const std::wstring generic_wstring(const codecvt_type& cvt) const { return wstring(cvt); }
418
419# endif
420
421 // ----- compare -----
422
423 int compare(const path& p) const NDNBOOST_NOEXCEPT; // generic, lexicographical
424 int compare(const std::string& s) const { return compare(path(s)); }
425 int compare(const value_type* s) const { return compare(path(s)); }
426
427 // ----- decomposition -----
428
429 path root_path() const;
430 path root_name() const; // returns 0 or 1 element path
431 // even on POSIX, root_name() is non-empty() for network paths
432 path root_directory() const; // returns 0 or 1 element path
433 path relative_path() const;
434 path parent_path() const;
435 path filename() const; // returns 0 or 1 element path
436 path stem() const; // returns 0 or 1 element path
437 path extension() const; // returns 0 or 1 element path
438
439 // ----- query -----
440
441 bool empty() const { return m_pathname.empty(); } // name consistent with std containers
442 bool has_root_path() const { return has_root_directory() || has_root_name(); }
443 bool has_root_name() const { return !root_name().empty(); }
444 bool has_root_directory() const { return !root_directory().empty(); }
445 bool has_relative_path() const { return !relative_path().empty(); }
446 bool has_parent_path() const { return !parent_path().empty(); }
447 bool has_filename() const { return !m_pathname.empty(); }
448 bool has_stem() const { return !stem().empty(); }
449 bool has_extension() const { return !extension().empty(); }
450 bool is_absolute() const
451 {
452# ifdef NDNBOOST_WINDOWS_API
453 return has_root_name() && has_root_directory();
454# else
455 return has_root_directory();
456# endif
457 }
458 bool is_relative() const { return !is_absolute(); }
459
460 // ----- iterators -----
461
462 class iterator;
463 typedef iterator const_iterator;
464
465 iterator begin() const;
466 iterator end() const;
467
468 // ----- static member functions -----
469
470 static std::locale imbue(const std::locale& loc);
471 static const codecvt_type& codecvt();
472
473 // ----- deprecated functions -----
474
475# if defined(NDNBOOST_FILESYSTEM_DEPRECATED) && defined(NDNBOOST_FILESYSTEM_NO_DEPRECATED)
476# error both NDNBOOST_FILESYSTEM_DEPRECATED and NDNBOOST_FILESYSTEM_NO_DEPRECATED are defined
477# endif
478
479# if !defined(NDNBOOST_FILESYSTEM_NO_DEPRECATED)
480 // recently deprecated functions supplied by default
481 path& normalize() { return m_normalize(); }
482 path& remove_leaf() { return remove_filename(); }
483 path leaf() const { return filename(); }
484 path branch_path() const { return parent_path(); }
485 bool has_leaf() const { return !m_pathname.empty(); }
486 bool has_branch_path() const { return !parent_path().empty(); }
487 bool is_complete() const { return is_absolute(); }
488# endif
489
490# if defined(NDNBOOST_FILESYSTEM_DEPRECATED)
491 // deprecated functions with enough signature or semantic changes that they are
492 // not supplied by default
493 const std::string file_string() const { return string(); }
494 const std::string directory_string() const { return string(); }
495 const std::string native_file_string() const { return string(); }
496 const std::string native_directory_string() const { return string(); }
497 const string_type external_file_string() const { return native(); }
498 const string_type external_directory_string() const { return native(); }
499
500 // older functions no longer supported
501 //typedef bool (*name_check)(const std::string & name);
502 //basic_path(const string_type& str, name_check) { operator/=(str); }
503 //basic_path(const typename string_type::value_type* s, name_check)
504 // { operator/=(s);}
505 //static bool default_name_check_writable() { return false; }
506 //static void default_name_check(name_check) {}
507 //static name_check default_name_check() { return 0; }
508 //basic_path& canonize();
509# endif
510
511//--------------------------------------------------------------------------------------//
512// class path private members //
513//--------------------------------------------------------------------------------------//
514
515 private:
516# if defined(_MSC_VER)
517# pragma warning(push) // Save warning settings
518# pragma warning(disable : 4251) // disable warning: class 'std::basic_string<_Elem,_Traits,_Ax>'
519# endif // needs to have dll-interface...
520/*
521 m_pathname has the type, encoding, and format required by the native
522 operating system. Thus for POSIX and Windows there is no conversion for
523 passing m_pathname.c_str() to the O/S API or when obtaining a path from the
524 O/S API. POSIX encoding is unspecified other than for dot and slash
525 characters; POSIX just treats paths as a sequence of bytes. Windows
526 encoding is UCS-2 or UTF-16 depending on the version.
527*/
528 string_type m_pathname; // Windows: as input; backslashes NOT converted to slashes,
529 // slashes NOT converted to backslashes
530# if defined(_MSC_VER)
531# pragma warning(pop) // restore warning settings.
532# endif
533
534 string_type::size_type m_append_separator_if_needed();
535 // Returns: If separator is to be appended, m_pathname.size() before append. Otherwise 0.
536 // Note: An append is never performed if size()==0, so a returned 0 is unambiguous.
537
538 void m_erase_redundant_separator(string_type::size_type sep_pos);
539 string_type::size_type m_parent_path_end() const;
540
541 path& m_normalize();
542
543 // Was qualified; como433beta8 reports:
544 // warning #427-D: qualified name is not allowed in member declaration
545 friend class iterator;
546 friend bool operator<(const path& lhs, const path& rhs);
547
548 // see path::iterator::increment/decrement comment below
549 static void m_path_iterator_increment(path::iterator & it);
550 static void m_path_iterator_decrement(path::iterator & it);
551
552 }; // class path
553
554 namespace detail
555 {
556 NDNBOOST_FILESYSTEM_DECL
557 int lex_compare(path::iterator first1, path::iterator last1,
558 path::iterator first2, path::iterator last2);
559 }
560
561# ifndef NDNBOOST_FILESYSTEM_NO_DEPRECATED
562 typedef path wpath;
563# endif
564
565 //------------------------------------------------------------------------------------//
566 // class path::iterator //
567 //------------------------------------------------------------------------------------//
568
569 class path::iterator
570 : public ndnboost::iterator_facade<
571 path::iterator,
572 path const,
573 ndnboost::bidirectional_traversal_tag >
574 {
575 private:
576 friend class ndnboost::iterator_core_access;
577 friend class ndnboost::filesystem::path;
578 friend void m_path_iterator_increment(path::iterator & it);
579 friend void m_path_iterator_decrement(path::iterator & it);
580
581 const path& dereference() const { return m_element; }
582
583 bool equal(const iterator & rhs) const
584 {
585 return m_path_ptr == rhs.m_path_ptr && m_pos == rhs.m_pos;
586 }
587
588 // iterator_facade derived classes don't seem to like implementations in
589 // separate translation unit dll's, so forward to class path static members
590 void increment() { m_path_iterator_increment(*this); }
591 void decrement() { m_path_iterator_decrement(*this); }
592
593 path m_element; // current element
594 const path* m_path_ptr; // path being iterated over
595 string_type::size_type m_pos; // position of m_element in
596 // m_path_ptr->m_pathname.
597 // if m_element is implicit dot, m_pos is the
598 // position of the last separator in the path.
599 // end() iterator is indicated by
600 // m_pos == m_path_ptr->m_pathname.size()
601 }; // path::iterator
602
603 //------------------------------------------------------------------------------------//
604 // //
605 // non-member functions //
606 // //
607 //------------------------------------------------------------------------------------//
608
609 // std::lexicographical_compare would infinately recurse because path iterators
610 // yield paths, so provide a path aware version
611 inline bool lexicographical_compare(path::iterator first1, path::iterator last1,
612 path::iterator first2, path::iterator last2)
613 { return detail::lex_compare(first1, last1, first2, last2) < 0; }
614
615 inline bool operator==(const path& lhs, const path& rhs) {return lhs.compare(rhs) == 0;}
616 inline bool operator==(const path& lhs, const path::string_type& rhs) {return lhs.compare(rhs) == 0;}
617 inline bool operator==(const path::string_type& lhs, const path& rhs) {return rhs.compare(lhs) == 0;}
618 inline bool operator==(const path& lhs, const path::value_type* rhs) {return lhs.compare(rhs) == 0;}
619 inline bool operator==(const path::value_type* lhs, const path& rhs) {return rhs.compare(lhs) == 0;}
620
621 inline bool operator!=(const path& lhs, const path& rhs) {return lhs.compare(rhs) != 0;}
622 inline bool operator!=(const path& lhs, const path::string_type& rhs) {return lhs.compare(rhs) != 0;}
623 inline bool operator!=(const path::string_type& lhs, const path& rhs) {return rhs.compare(lhs) != 0;}
624 inline bool operator!=(const path& lhs, const path::value_type* rhs) {return lhs.compare(rhs) != 0;}
625 inline bool operator!=(const path::value_type* lhs, const path& rhs) {return rhs.compare(lhs) != 0;}
626
627 // TODO: why do == and != have additional overloads, but the others don't?
628
629 inline bool operator<(const path& lhs, const path& rhs) {return lhs.compare(rhs) < 0;}
630 inline bool operator<=(const path& lhs, const path& rhs) {return !(rhs < lhs);}
631 inline bool operator> (const path& lhs, const path& rhs) {return rhs < lhs;}
632 inline bool operator>=(const path& lhs, const path& rhs) {return !(lhs < rhs);}
633
634 inline std::size_t hash_value(const path& x)
635 {
636# ifdef NDNBOOST_WINDOWS_API
637 std::size_t seed = 0;
638 for(const path::value_type* it = x.c_str(); *it; ++it)
639 hash_combine(seed, *it == '/' ? L'\\' : *it);
640 return seed;
641# else // NDNBOOST_POSIX_API
642 return hash_range(x.native().begin(), x.native().end());
643# endif
644 }
645
646 inline void swap(path& lhs, path& rhs) { lhs.swap(rhs); }
647
648 inline path operator/(const path& lhs, const path& rhs) { return path(lhs) /= rhs; }
649
650 // inserters and extractors
651 // use ndnboost::io::quoted() to handle spaces in paths
652 // use '&' as escape character to ease use for Windows paths
653
654 template <class Char, class Traits>
655 inline std::basic_ostream<Char, Traits>&
656 operator<<(std::basic_ostream<Char, Traits>& os, const path& p)
657 {
658 return os
659 << ndnboost::io::quoted(p.template string<std::basic_string<Char> >(), static_cast<Char>('&'));
660 }
661
662 template <class Char, class Traits>
663 inline std::basic_istream<Char, Traits>&
664 operator>>(std::basic_istream<Char, Traits>& is, path& p)
665 {
666 std::basic_string<Char> str;
667 is >> ndnboost::io::quoted(str, static_cast<Char>('&'));
668 p = str;
669 return is;
670 }
671
672 // name_checks
673
674 // These functions are holdovers from version 1. It isn't clear they have much
675 // usefulness, or how to generalize them for later versions.
676
677 NDNBOOST_FILESYSTEM_DECL bool portable_posix_name(const std::string & name);
678 NDNBOOST_FILESYSTEM_DECL bool windows_name(const std::string & name);
679 NDNBOOST_FILESYSTEM_DECL bool portable_name(const std::string & name);
680 NDNBOOST_FILESYSTEM_DECL bool portable_directory_name(const std::string & name);
681 NDNBOOST_FILESYSTEM_DECL bool portable_file_name(const std::string & name);
682 NDNBOOST_FILESYSTEM_DECL bool native(const std::string & name);
683
684//--------------------------------------------------------------------------------------//
685// class path member template implementation //
686//--------------------------------------------------------------------------------------//
687
688 template <class InputIterator>
689 path& path::append(InputIterator begin, InputIterator end, const codecvt_type& cvt)
690 {
691 if (begin == end)
692 return *this;
693 string_type::size_type sep_pos(m_append_separator_if_needed());
694 std::basic_string<typename std::iterator_traits<InputIterator>::value_type>
695 s(begin, end);
696 path_traits::convert(s.c_str(), s.c_str()+s.size(), m_pathname, cvt);
697 if (sep_pos)
698 m_erase_redundant_separator(sep_pos);
699 return *this;
700 }
701
702 template <class Source>
703 path& path::append(Source const& source, const codecvt_type& cvt)
704 {
705 if (path_traits::empty(source))
706 return *this;
707 string_type::size_type sep_pos(m_append_separator_if_needed());
708 path_traits::dispatch(source, m_pathname, cvt);
709 if (sep_pos)
710 m_erase_redundant_separator(sep_pos);
711 return *this;
712 }
713
714//--------------------------------------------------------------------------------------//
715// class path member template specializations //
716//--------------------------------------------------------------------------------------//
717
718 template <> inline
719 std::string path::string<std::string>() const
720 { return string(); }
721
722 template <> inline
723 std::wstring path::string<std::wstring>() const
724 { return wstring(); }
725
726 template <> inline
727 std::string path::string<std::string>(const codecvt_type& cvt) const
728 { return string(cvt); }
729
730 template <> inline
731 std::wstring path::string<std::wstring>(const codecvt_type& cvt) const
732 { return wstring(cvt); }
733
734 template <> inline
735 std::string path::generic_string<std::string>() const
736 { return generic_string(); }
737
738 template <> inline
739 std::wstring path::generic_string<std::wstring>() const
740 { return generic_wstring(); }
741
742 template <> inline
743 std::string path::generic_string<std::string>(const codecvt_type& cvt) const
744 { return generic_string(cvt); }
745
746 template <> inline
747 std::wstring path::generic_string<std::wstring>(const codecvt_type& cvt) const
748 { return generic_wstring(cvt); }
749
750
751} // namespace filesystem
752} // namespace ndnboost
753
754//----------------------------------------------------------------------------//
755
756#include <ndnboost/config/abi_suffix.hpp> // pops abi_prefix.hpp pragmas
757
758#endif // NDNBOOST_FILESYSTEM_PATH_HPP