1 // filesystem path.cpp ------------------------------------------------------------- //
3 // Copyright Beman Dawes 2008
5 // Distributed under the Boost Software License, Version 1.0.
6 // See http://www.boost.org/LICENSE_1_0.txt
8 // Library home page: http://www.boost.org/libs/filesystem
10 // Include Boost.Predef first so that windows.h is guaranteed to be not included
11 #include <boost/predef/os/windows.h>
13 #include <boost/winapi/config.hpp>
16 // Old standard library configurations, particularly MingGW, don't support wide strings.
17 // Report this with an explicit error message.
18 #include <boost/config.hpp>
19 # if defined( BOOST_NO_STD_WSTRING )
20 # error Configuration not supported: Boost.Filesystem V3 and later requires std::wstring support
23 #ifndef BOOST_SYSTEM_NO_DEPRECATED
24 # define BOOST_SYSTEM_NO_DEPRECATED
27 #include <boost/filesystem/config.hpp>
28 #include <boost/filesystem/path.hpp>
29 #include <boost/filesystem/operations.hpp> // for filesystem_error
30 #include <boost/scoped_array.hpp>
31 #include <boost/system/error_code.hpp>
32 #include <boost/assert.hpp>
40 #ifdef BOOST_WINDOWS_API
41 # include "windows_file_codecvt.hpp"
43 #elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) \
44 || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__HAIKU__)
45 # include <boost/filesystem/detail/utf8_codecvt_facet.hpp>
48 #ifdef BOOST_FILESYSTEM_DEBUG
53 namespace fs = boost::filesystem;
55 using boost::filesystem::path;
60 using boost::system::error_code;
62 //--------------------------------------------------------------------------------------//
64 // class path helpers //
66 //--------------------------------------------------------------------------------------//
70 //------------------------------------------------------------------------------------//
71 // miscellaneous class path helpers //
72 //------------------------------------------------------------------------------------//
74 typedef path::value_type value_type;
75 typedef path::string_type string_type;
76 typedef string_type::size_type size_type;
78 # ifdef BOOST_WINDOWS_API
80 const wchar_t* const separators = L"/\\";
81 const wchar_t* separator_string = L"/";
82 const wchar_t* preferred_separator_string = L"\\";
83 const wchar_t colon = L':';
84 const wchar_t questionmark = L'?';
86 inline bool is_letter(wchar_t c)
88 return (c >= L'a' && c <=L'z') || (c >= L'A' && c <=L'Z');
93 const char* const separators = "/";
94 const char* separator_string = "/";
95 const char* preferred_separator_string = "/";
99 bool is_root_separator(const string_type& str, size_type pos);
100 // pos is position of the separator
102 size_type filename_pos(const string_type& str,
103 size_type end_pos); // end_pos is past-the-end position
104 // Returns: 0 if str itself is filename (or empty)
106 size_type root_directory_start(const string_type& path, size_type size);
107 // Returns: npos if no root_directory found
110 const string_type& src,
111 size_type& element_pos,
112 size_type& element_size,
113 # if !BOOST_WORKAROUND(BOOST_MSVC, <= 1310) // VC++ 7.1
114 size_type size = string_type::npos
120 } // unnamed namespace
122 //--------------------------------------------------------------------------------------//
124 // class path implementation //
126 //--------------------------------------------------------------------------------------//
133 BOOST_FILESYSTEM_DECL path& path::operator/=(const path& p)
137 if (this == &p) // self-append
140 if (!detail::is_directory_separator(rhs.m_pathname[0]))
141 m_append_separator_if_needed();
142 m_pathname += rhs.m_pathname;
146 if (!detail::is_directory_separator(*p.m_pathname.begin()))
147 m_append_separator_if_needed();
148 m_pathname += p.m_pathname;
153 BOOST_FILESYSTEM_DECL path& path::operator/=(const value_type* ptr)
157 if (ptr >= m_pathname.data()
158 && ptr < m_pathname.data() + m_pathname.size()) // overlapping source
161 if (!detail::is_directory_separator(rhs.m_pathname[0]))
162 m_append_separator_if_needed();
163 m_pathname += rhs.m_pathname;
167 if (!detail::is_directory_separator(*ptr))
168 m_append_separator_if_needed();
174 # ifdef BOOST_WINDOWS_API
176 BOOST_FILESYSTEM_DECL path path::generic_path() const
179 std::replace(tmp.m_pathname.begin(), tmp.m_pathname.end(), L'\\', L'/');
183 # endif // BOOST_WINDOWS_API
185 BOOST_FILESYSTEM_DECL int path::compare(const path& p) const BOOST_NOEXCEPT
187 return detail::lex_compare(begin(), end(), p.begin(), p.end());
190 // m_append_separator_if_needed ----------------------------------------------------//
192 BOOST_FILESYSTEM_DECL path::string_type::size_type path::m_append_separator_if_needed()
194 if (!m_pathname.empty() &&
195 # ifdef BOOST_WINDOWS_API
196 *(m_pathname.end()-1) != colon &&
198 !detail::is_directory_separator(*(m_pathname.end()-1)))
200 string_type::size_type tmp(m_pathname.size());
201 m_pathname += preferred_separator;
207 // m_erase_redundant_separator -----------------------------------------------------//
209 BOOST_FILESYSTEM_DECL void path::m_erase_redundant_separator(string_type::size_type sep_pos)
211 if (sep_pos // a separator was added
212 && sep_pos < m_pathname.size() // and something was appended
213 && (m_pathname[sep_pos+1] == separator // and it was also separator
214 # ifdef BOOST_WINDOWS_API
215 || m_pathname[sep_pos+1] == preferred_separator // or preferred_separator
217 )) { m_pathname.erase(sep_pos, 1); } // erase the added separator
220 // modifiers -----------------------------------------------------------------------//
222 # ifdef BOOST_WINDOWS_API
223 BOOST_FILESYSTEM_DECL path& path::make_preferred()
225 std::replace(m_pathname.begin(), m_pathname.end(), L'/', L'\\');
230 BOOST_FILESYSTEM_DECL path& path::remove_filename()
232 m_pathname.erase(m_parent_path_end());
236 BOOST_FILESYSTEM_DECL path& path::remove_trailing_separator()
238 if (!m_pathname.empty()
239 && detail::is_directory_separator(m_pathname[m_pathname.size() - 1]))
240 m_pathname.erase(m_pathname.size() - 1);
244 BOOST_FILESYSTEM_DECL path& path::replace_extension(const path& new_extension)
246 // erase existing extension, including the dot, if any
247 m_pathname.erase(m_pathname.size()-extension().m_pathname.size());
249 if (!new_extension.empty())
251 // append new_extension, adding the dot if necessary
252 if (new_extension.m_pathname[0] != dot)
253 m_pathname.push_back(dot);
254 m_pathname.append(new_extension.m_pathname);
260 // decomposition -------------------------------------------------------------------//
262 BOOST_FILESYSTEM_DECL path path::root_path() const
264 path temp(root_name());
265 if (!root_directory().empty()) temp.m_pathname += root_directory().c_str();
269 BOOST_FILESYSTEM_DECL path path::root_name() const
271 iterator itr(begin());
273 return (itr.m_pos != m_pathname.size()
275 (itr.m_element.m_pathname.size() > 1
276 && detail::is_directory_separator(itr.m_element.m_pathname[0])
277 && detail::is_directory_separator(itr.m_element.m_pathname[1]))
278 # ifdef BOOST_WINDOWS_API
279 || itr.m_element.m_pathname[itr.m_element.m_pathname.size()-1] == colon
286 BOOST_FILESYSTEM_DECL path path::root_directory() const
288 size_type pos(root_directory_start(m_pathname, m_pathname.size()));
290 return pos == string_type::npos
292 : path(m_pathname.c_str() + pos, m_pathname.c_str() + pos + 1);
295 BOOST_FILESYSTEM_DECL path path::relative_path() const
297 iterator itr(begin());
299 for (; itr.m_pos != m_pathname.size()
300 && (detail::is_directory_separator(itr.m_element.m_pathname[0])
301 # ifdef BOOST_WINDOWS_API
302 || itr.m_element.m_pathname[itr.m_element.m_pathname.size()-1] == colon
306 return path(m_pathname.c_str() + itr.m_pos);
309 BOOST_FILESYSTEM_DECL string_type::size_type path::m_parent_path_end() const
311 size_type end_pos(filename_pos(m_pathname, m_pathname.size()));
313 bool filename_was_separator(m_pathname.size()
314 && detail::is_directory_separator(m_pathname[end_pos]));
316 // skip separators unless root directory
317 size_type root_dir_pos(root_directory_start(m_pathname, end_pos));
320 && (end_pos-1) != root_dir_pos
321 && detail::is_directory_separator(m_pathname[end_pos-1])
325 return (end_pos == 1 && root_dir_pos == 0 && filename_was_separator)
330 BOOST_FILESYSTEM_DECL path path::parent_path() const
332 size_type end_pos(m_parent_path_end());
333 return end_pos == string_type::npos
335 : path(m_pathname.c_str(), m_pathname.c_str() + end_pos);
338 BOOST_FILESYSTEM_DECL path path::filename() const
340 size_type pos(filename_pos(m_pathname, m_pathname.size()));
341 return (m_pathname.size()
343 && detail::is_directory_separator(m_pathname[pos])
344 && !is_root_separator(m_pathname, pos))
346 : path(m_pathname.c_str() + pos);
349 BOOST_FILESYSTEM_DECL path path::stem() const
351 path name(filename());
352 if (name == detail::dot_path() || name == detail::dot_dot_path()) return name;
353 size_type pos(name.m_pathname.rfind(dot));
354 return pos == string_type::npos
356 : path(name.m_pathname.c_str(), name.m_pathname.c_str() + pos);
359 BOOST_FILESYSTEM_DECL path path::extension() const
361 path name(filename());
362 if (name == detail::dot_path() || name == detail::dot_dot_path()) return path();
363 size_type pos(name.m_pathname.rfind(dot));
364 return pos == string_type::npos
366 : path(name.m_pathname.c_str() + pos);
369 // lexical operations --------------------------------------------------------------//
373 // C++14 provides a mismatch algorithm with four iterator arguments(), but earlier
374 // standard libraries didn't, so provide this needed functionality.
376 std::pair<path::iterator, path::iterator> mismatch(path::iterator it1,
377 path::iterator it1end, path::iterator it2, path::iterator it2end)
379 for (; it1 != it1end && it2 != it2end && *it1 == *it2;)
384 return std::make_pair(it1, it2);
388 BOOST_FILESYSTEM_DECL path path::lexically_relative(const path& base) const
390 path::iterator b = begin(), e = end(), base_b = base.begin(), base_e = base.end();
391 std::pair<path::iterator, path::iterator> mm = detail::mismatch(b, e, base_b, base_e);
392 if (mm.first == b && mm.second == base_b)
394 if (mm.first == e && mm.second == base_e)
395 return detail::dot_path();
397 std::ptrdiff_t n = 0;
398 for (; mm.second != base_e; ++mm.second)
400 path const& p = *mm.second;
401 if (p == detail::dot_dot_path())
403 else if (!p.empty() && p != detail::dot_path())
408 if (n == 0 && (mm.first == e || mm.first->empty()))
409 return detail::dot_path();
413 tmp /= detail::dot_dot_path();
414 for (; mm.first != e; ++mm.first)
419 // normal --------------------------------------------------------------------------//
421 BOOST_FILESYSTEM_DECL path path::lexically_normal() const
423 if (m_pathname.empty())
427 iterator start(begin());
428 iterator last(end());
429 iterator stop(last--);
430 for (iterator itr(start); itr != stop; ++itr)
432 // ignore "." except at start and last
433 if (itr->native().size() == 1
434 && (itr->native())[0] == dot
436 && itr != last) continue;
438 // ignore a name and following ".."
440 && itr->native().size() == 2
441 && (itr->native())[0] == dot
442 && (itr->native())[1] == dot) // dot dot
444 string_type lf(temp.filename().native());
448 && lf[0] != separator))
452 # ifdef BOOST_WINDOWS_API
459 temp.remove_filename();
460 //// if not root directory, must also remove "/" if any
461 //if (temp.native().size() > 0
462 // && temp.native()[temp.native().size()-1]
465 // string_type::size_type rds(
466 // root_directory_start(temp.native(), temp.native().size()));
467 // if (rds == string_type::npos
468 // || rds != temp.native().size()-1)
470 // temp.m_pathname.erase(temp.native().size()-1);
475 if (temp.empty() && ++next != stop
476 && next == last && *last == detail::dot_path())
478 temp /= detail::dot_path();
488 temp /= detail::dot_path();
492 } // namespace filesystem
495 //--------------------------------------------------------------------------------------//
497 // class path helpers implementation //
499 //--------------------------------------------------------------------------------------//
504 // is_root_separator ---------------------------------------------------------------//
506 bool is_root_separator(const string_type & str, size_type pos)
507 // pos is position of the separator
509 BOOST_ASSERT_MSG(!str.empty() && fs::detail::is_directory_separator(str[pos]),
510 "precondition violation");
512 // subsequent logic expects pos to be for leftmost slash of a set
513 while (pos > 0 && fs::detail::is_directory_separator(str[pos-1]))
520 # ifdef BOOST_WINDOWS_API
522 if (pos == 2 && is_letter(str[0]) && str[1] == colon)
527 if (pos < 3 || !fs::detail::is_directory_separator(str[0])
528 || !fs::detail::is_directory_separator(str[1]))
531 return str.find_first_of(separators, 2) == pos;
534 // filename_pos --------------------------------------------------------------------//
536 size_type filename_pos(const string_type & str,
537 size_type end_pos) // end_pos is past-the-end position
538 // return 0 if str itself is filename (or empty)
542 && fs::detail::is_directory_separator(str[0])
543 && fs::detail::is_directory_separator(str[1])) return 0;
546 if (end_pos && fs::detail::is_directory_separator(str[end_pos-1]))
549 // set pos to start of last element
550 size_type pos(str.find_last_of(separators, end_pos-1));
552 # ifdef BOOST_WINDOWS_API
553 if (pos == string_type::npos && end_pos > 1)
554 pos = str.find_last_of(colon, end_pos-2);
557 return (pos == string_type::npos // path itself must be a filename (or empty)
558 || (pos == 1 && fs::detail::is_directory_separator(str[0]))) // or net
559 ? 0 // so filename is entire string
560 : pos + 1; // or starts after delimiter
563 // root_directory_start ------------------------------------------------------------//
565 size_type root_directory_start(const string_type & path, size_type size)
566 // return npos if no root_directory found
569 # ifdef BOOST_WINDOWS_API
573 && fs::detail::is_directory_separator(path[2])) return 2;
578 && fs::detail::is_directory_separator(path[0])
579 && fs::detail::is_directory_separator(path[1])) return string_type::npos;
581 # ifdef BOOST_WINDOWS_API
584 && fs::detail::is_directory_separator(path[0])
585 && fs::detail::is_directory_separator(path[1])
586 && path[2] == questionmark
587 && fs::detail::is_directory_separator(path[3]))
589 string_type::size_type pos(path.find_first_of(separators, 4));
590 return pos < size ? pos : string_type::npos;
596 && fs::detail::is_directory_separator(path[0])
597 && fs::detail::is_directory_separator(path[1])
598 && !fs::detail::is_directory_separator(path[2]))
600 string_type::size_type pos(path.find_first_of(separators, 2));
601 return pos < size ? pos : string_type::npos;
605 if (size > 0 && fs::detail::is_directory_separator(path[0])) return 0;
607 return string_type::npos;
610 // first_element --------------------------------------------------------------------//
611 // sets pos and len of first element, excluding extra separators
612 // if src.empty(), sets pos,len, to 0,0.
615 const string_type & src,
616 size_type & element_pos,
617 size_type & element_size,
621 if (size == string_type::npos) size = src.size();
624 if (src.empty()) return;
626 string_type::size_type cur(0);
628 // deal with // [network]
629 if (size >= 2 && fs::detail::is_directory_separator(src[0])
630 && fs::detail::is_directory_separator(src[1])
632 || !fs::detail::is_directory_separator(src[2])))
638 // leading (not non-network) separator
639 else if (fs::detail::is_directory_separator(src[0]))
642 // bypass extra leading separators
644 && fs::detail::is_directory_separator(src[cur+1]))
652 // at this point, we have either a plain name, a network name,
653 // or (on Windows only) a device name
657 # ifdef BOOST_WINDOWS_API
660 && !fs::detail::is_directory_separator(src[cur]))
666 # ifdef BOOST_WINDOWS_API
667 if (cur == size) return;
668 // include device delimiter
669 if (src[cur] == colon)
676 } // unnamed namespace
685 BOOST_FILESYSTEM_DECL
686 int lex_compare(path::iterator first1, path::iterator last1,
687 path::iterator first2, path::iterator last2)
689 for (; first1 != last1 && first2 != last2;)
691 if (first1->native() < first2->native()) return -1;
692 if (first2->native() < first1->native()) return 1;
693 BOOST_ASSERT(first2->native() == first1->native());
697 if (first1 == last1 && first2 == last2)
699 return first1 == last1 ? -1 : 1;
702 BOOST_FILESYSTEM_DECL
703 const path& dot_path()
705 # ifdef BOOST_WINDOWS_API
706 static const fs::path dot_pth(L".");
708 static const fs::path dot_pth(".");
713 BOOST_FILESYSTEM_DECL
714 const path& dot_dot_path()
716 # ifdef BOOST_WINDOWS_API
717 static const fs::path dot_dot(L"..");
719 static const fs::path dot_dot("..");
725 //--------------------------------------------------------------------------------------//
727 // class path::iterator implementation //
729 //--------------------------------------------------------------------------------------//
731 BOOST_FILESYSTEM_DECL path::iterator path::begin() const
734 itr.m_path_ptr = this;
735 size_type element_size;
736 first_element(m_pathname, itr.m_pos, element_size);
737 itr.m_element = m_pathname.substr(itr.m_pos, element_size);
738 if (itr.m_element.m_pathname == preferred_separator_string)
739 itr.m_element.m_pathname = separator_string; // needed for Windows, harmless on POSIX
743 BOOST_FILESYSTEM_DECL path::iterator path::end() const
746 itr.m_path_ptr = this;
747 itr.m_pos = m_pathname.size();
751 BOOST_FILESYSTEM_DECL void path::m_path_iterator_increment(path::iterator & it)
753 BOOST_ASSERT_MSG(it.m_pos < it.m_path_ptr->m_pathname.size(),
754 "path::basic_iterator increment past end()");
756 // increment to position past current element; if current element is implicit dot,
757 // this will cause it.m_pos to represent the end iterator
758 it.m_pos += it.m_element.m_pathname.size();
760 // if the end is reached, we are done
761 if (it.m_pos == it.m_path_ptr->m_pathname.size())
763 it.m_element.clear(); // aids debugging, may release unneeded memory
767 // both POSIX and Windows treat paths that begin with exactly two separators specially
768 bool was_net(it.m_element.m_pathname.size() > 2
769 && detail::is_directory_separator(it.m_element.m_pathname[0])
770 && detail::is_directory_separator(it.m_element.m_pathname[1])
771 && !detail::is_directory_separator(it.m_element.m_pathname[2]));
773 // process separator (Windows drive spec is only case not a separator)
774 if (detail::is_directory_separator(it.m_path_ptr->m_pathname[it.m_pos]))
776 // detect root directory
778 # ifdef BOOST_WINDOWS_API
780 || it.m_element.m_pathname[it.m_element.m_pathname.size()-1] == colon
784 it.m_element.m_pathname = separator; // generic format; see docs
788 // skip separators until it.m_pos points to the start of the next element
789 while (it.m_pos != it.m_path_ptr->m_pathname.size()
790 && detail::is_directory_separator(it.m_path_ptr->m_pathname[it.m_pos]))
793 // detect trailing separator, and treat it as ".", per POSIX spec
794 if (it.m_pos == it.m_path_ptr->m_pathname.size()
795 && !is_root_separator(it.m_path_ptr->m_pathname, it.m_pos-1))
798 it.m_element = detail::dot_path();
804 size_type end_pos(it.m_path_ptr->m_pathname.find_first_of(separators, it.m_pos));
805 if (end_pos == string_type::npos)
806 end_pos = it.m_path_ptr->m_pathname.size();
807 it.m_element = it.m_path_ptr->m_pathname.substr(it.m_pos, end_pos - it.m_pos);
810 BOOST_FILESYSTEM_DECL void path::m_path_iterator_decrement(path::iterator & it)
812 BOOST_ASSERT_MSG(it.m_pos, "path::iterator decrement past begin()");
814 size_type end_pos(it.m_pos);
816 // if at end and there was a trailing non-root '/', return "."
817 if (it.m_pos == it.m_path_ptr->m_pathname.size()
818 && it.m_path_ptr->m_pathname.size() > 1
819 && detail::is_directory_separator(it.m_path_ptr->m_pathname[it.m_pos-1])
820 && !is_root_separator(it.m_path_ptr->m_pathname, it.m_pos-1)
824 it.m_element = detail::dot_path();
828 size_type root_dir_pos(root_directory_start(it.m_path_ptr->m_pathname, end_pos));
830 // skip separators unless root directory
834 && (end_pos-1) != root_dir_pos
835 && detail::is_directory_separator(it.m_path_ptr->m_pathname[end_pos-1])
839 it.m_pos = filename_pos(it.m_path_ptr->m_pathname, end_pos);
840 it.m_element = it.m_path_ptr->m_pathname.substr(it.m_pos, end_pos - it.m_pos);
841 if (it.m_element.m_pathname == preferred_separator_string) // needed for Windows, harmless on POSIX
842 it.m_element.m_pathname = separator_string; // generic format; see docs
845 } // namespace filesystem
851 //------------------------------------------------------------------------------------//
853 //------------------------------------------------------------------------------------//
855 // Prior versions of these locale and codecvt implementations tried to take advantage
856 // of static initialization where possible, kept a local copy of the current codecvt
857 // facet (to avoid codecvt() having to call use_facet()), and was not multi-threading
858 // safe (again for efficiency).
860 // This was error prone, and required different implementation techniques depending
861 // on the compiler and also whether static or dynamic linking was used. Furthermore,
862 // users could not easily provide their multi-threading safe wrappers because the
863 // path interface requires the implementation itself to call codecvt() to obtain the
864 // default facet, and the initialization of the static within path_locale() could race.
866 // The code below is portable to all platforms, is much simpler, and hopefully will be
867 // much more robust. Timing tests (on Windows, using a Visual C++ release build)
868 // indicated the current code is roughly 9% slower than the previous code, and that
869 // seems a small price to pay for better code that is easier to use.
871 std::locale default_locale()
873 # if defined(BOOST_WINDOWS_API)
874 std::locale global_loc = std::locale();
875 return std::locale(global_loc, new windows_file_codecvt);
876 # elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) \
877 || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__HAIKU__)
878 // "All BSD system functions expect their string parameters to be in UTF-8 encoding
879 // and nothing else." See
880 // http://developer.apple.com/mac/library/documentation/MacOSX/Conceptual/BPInternational/Articles/FileEncodings.html
882 // "The kernel will reject any filename that is not a valid UTF-8 string, and it will
883 // even be normalized (to Unicode NFD) before stored on disk, at least when using HFS.
884 // The right way to deal with it would be to always convert the filename to UTF-8
885 // before trying to open/create a file." See
886 // http://lists.apple.com/archives/unix-porting/2007/Sep/msg00023.html
888 // "How a file name looks at the API level depends on the API. Current Carbon APIs
889 // handle file names as an array of UTF-16 characters; POSIX ones handle them as an
890 // array of UTF-8, which is why UTF-8 works well in Terminal. How it's stored on disk
891 // depends on the disk format; HFS+ uses UTF-16, but that's not important in most
893 // http://lists.apple.com/archives/applescript-users/2002/Sep/msg00319.html
895 // Many thanks to Peter Dimov for digging out the above references!
897 std::locale global_loc = std::locale();
898 return std::locale(global_loc, new boost::filesystem::detail::utf8_codecvt_facet);
899 # else // Other POSIX
900 // ISO C calls std::locale("") "the locale-specific native environment", and this
901 // locale is the default for many POSIX-based operating systems such as Linux.
902 return std::locale("");
906 std::locale& path_locale()
907 // std::locale("") construction, needed on non-Apple POSIX systems, can throw
908 // (if environmental variables LC_MESSAGES or LANG are wrong, for example), so
909 // path_locale() provides lazy initialization via a local static to ensure that any
910 // exceptions occur after main() starts and so can be caught. Furthermore,
911 // path_locale() is only called if path::codecvt() or path::imbue() are themselves
912 // actually called, ensuring that an exception will only be thrown if std::locale("")
915 // [locale] paragraph 6: Once a facet reference is obtained from a locale object by
916 // calling use_facet<>, that reference remains usable, and the results from member
917 // functions of it may be cached and re-used, as long as some locale object refers
919 static std::locale loc(default_locale());
920 #ifdef BOOST_FILESYSTEM_DEBUG
921 std::cout << "***** path_locale() called" << std::endl;
925 } // unnamed namespace
927 //--------------------------------------------------------------------------------------//
928 // path::codecvt() and path::imbue() implementation //
929 //--------------------------------------------------------------------------------------//
935 // See comments above
937 BOOST_FILESYSTEM_DECL const path::codecvt_type& path::codecvt()
939 #ifdef BOOST_FILESYSTEM_DEBUG
940 std::cout << "***** path::codecvt() called" << std::endl;
942 BOOST_ASSERT_MSG(&path_locale(), "boost::filesystem::path locale initialization error");
944 return std::use_facet<std::codecvt<wchar_t, char, std::mbstate_t> >(path_locale());
947 BOOST_FILESYSTEM_DECL std::locale path::imbue(const std::locale& loc)
949 #ifdef BOOST_FILESYSTEM_DEBUG
950 std::cout << "***** path::imbue() called" << std::endl;
952 std::locale temp(path_locale());
957 } // namespace filesystem