summaryrefslogtreecommitdiffstats
path: root/contrib/restricted/boost/filesystem/src/path.cpp
diff options
context:
space:
mode:
authorAlexSm <[email protected]>2024-01-04 15:09:05 +0100
committerGitHub <[email protected]>2024-01-04 15:09:05 +0100
commitdab291146f6cd7d35684e3a1150e5bb1c412982c (patch)
tree36ef35f6cacb6432845a4a33f940c95871036b32 /contrib/restricted/boost/filesystem/src/path.cpp
parent63660ad5e7512029fd0218e7a636580695a24e1f (diff)
Library import 5, delete go dependencies (#832)
* Library import 5, delete go dependencies * Fix yt client
Diffstat (limited to 'contrib/restricted/boost/filesystem/src/path.cpp')
-rw-r--r--contrib/restricted/boost/filesystem/src/path.cpp1633
1 files changed, 0 insertions, 1633 deletions
diff --git a/contrib/restricted/boost/filesystem/src/path.cpp b/contrib/restricted/boost/filesystem/src/path.cpp
deleted file mode 100644
index 1d9748cac71..00000000000
--- a/contrib/restricted/boost/filesystem/src/path.cpp
+++ /dev/null
@@ -1,1633 +0,0 @@
-// filesystem path.cpp ------------------------------------------------------------- //
-
-// Copyright Beman Dawes 2008
-// Copyright Andrey Semashev 2021-2023
-
-// Distributed under the Boost Software License, Version 1.0.
-// See http://www.boost.org/LICENSE_1_0.txt
-
-// Library home page: http://www.boost.org/libs/filesystem
-
-#include "platform_config.hpp"
-
-#include <boost/filesystem/config.hpp>
-#include <boost/filesystem/path.hpp>
-#include <boost/filesystem/detail/path_traits.hpp> // codecvt_error_category()
-#include <boost/scoped_array.hpp>
-#include <boost/system/error_category.hpp> // for BOOST_SYSTEM_HAS_CONSTEXPR
-#include <boost/assert.hpp>
-#include <algorithm>
-#include <iterator>
-#include <utility>
-#include <string>
-#include <cstddef>
-#include <cstring>
-#include <cstdlib> // std::atexit
-
-#ifdef BOOST_WINDOWS_API
-#include "windows_file_codecvt.hpp"
-#include "windows_tools.hpp"
-#include <windows.h>
-#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__HAIKU__)
-#include <boost/filesystem/detail/utf8_codecvt_facet.hpp>
-#endif
-
-#ifdef BOOST_FILESYSTEM_DEBUG
-#include <iostream>
-#include <iomanip>
-#endif
-
-#include "atomic_tools.hpp"
-#include "private_config.hpp"
-
-#include <boost/filesystem/detail/header.hpp> // must be the last #include
-
-namespace fs = boost::filesystem;
-
-using boost::filesystem::path;
-
-//--------------------------------------------------------------------------------------//
-// //
-// class path helpers //
-// //
-//--------------------------------------------------------------------------------------//
-
-namespace {
-//------------------------------------------------------------------------------------//
-// miscellaneous class path helpers //
-//------------------------------------------------------------------------------------//
-
-typedef path::value_type value_type;
-typedef path::string_type string_type;
-typedef string_type::size_type size_type;
-
-#ifdef BOOST_WINDOWS_API
-
-const wchar_t dot_path_literal[] = L".";
-const wchar_t dot_dot_path_literal[] = L"..";
-const wchar_t separators[] = L"/\\";
-using boost::filesystem::detail::colon;
-using boost::filesystem::detail::questionmark;
-
-inline bool is_alnum(wchar_t c)
-{
- return boost::filesystem::detail::is_letter(c) || (c >= L'0' && c <= L'9');
-}
-
-inline bool is_device_name_char(wchar_t c)
-{
- // https://googleprojectzero.blogspot.com/2016/02/the-definitive-guide-on-win32-to-nt.html
- // Device names are:
- //
- // - PRN
- // - AUX
- // - NUL
- // - CON
- // - LPT[1-9]
- // - COM[1-9]
- // - CONIN$
- // - CONOUT$
- return is_alnum(c) || c == L'$';
-}
-
-//! Returns position of the first directory separator in the \a size initial characters of \a p, or \a size if not found
-inline size_type find_separator(const wchar_t* p, size_type size) BOOST_NOEXCEPT
-{
- size_type pos = 0u;
- for (; pos < size; ++pos)
- {
- const wchar_t c = p[pos];
- if (boost::filesystem::detail::is_directory_separator(c))
- break;
- }
- return pos;
-}
-
-#else // BOOST_WINDOWS_API
-
-const char dot_path_literal[] = ".";
-const char dot_dot_path_literal[] = "..";
-const char separators[] = "/";
-
-//! Returns position of the first directory separator in the \a size initial characters of \a p, or \a size if not found
-inline size_type find_separator(const char* p, size_type size) BOOST_NOEXCEPT
-{
- const char* sep = static_cast< const char* >(std::memchr(p, '/', size));
- size_type pos = size;
- if (BOOST_LIKELY(!!sep))
- pos = sep - p;
- return pos;
-}
-
-#endif // BOOST_WINDOWS_API
-
-// pos is position of the separator
-bool is_root_separator(string_type const& str, size_type root_dir_pos, size_type pos);
-
-// Returns: Size of the filename element that ends at end_pos (which is past-the-end position). 0 if no filename found.
-size_type find_filename_size(string_type const& str, size_type root_name_size, size_type end_pos);
-
-// Returns: starting position of root directory or size if not found. Sets root_name_size to length
-// of the root name if the characters before the returned position (if any) are considered a root name.
-size_type find_root_directory_start(const value_type* path, size_type size, size_type& root_name_size);
-
-// Finds position and size of the first element of the path
-void first_element(string_type const& src, size_type& element_pos, size_type& element_size, size_type size);
-
-// Finds position and size of the first element of the path
-inline void first_element(string_type const& src, size_type& element_pos, size_type& element_size)
-{
- first_element(src, element_pos, element_size, src.size());
-}
-
-} // unnamed namespace
-
-//--------------------------------------------------------------------------------------//
-// //
-// class path implementation //
-// //
-//--------------------------------------------------------------------------------------//
-
-namespace boost {
-namespace filesystem {
-namespace detail {
-
-// C++14 provides a mismatch algorithm with four iterator arguments(), but earlier
-// standard libraries didn't, so provide this needed functionality.
-inline std::pair< path::iterator, path::iterator > mismatch(path::iterator it1, path::iterator it1end, path::iterator it2, path::iterator it2end)
-{
- for (; it1 != it1end && it2 != it2end && path_algorithms::compare_v4(*it1, *it2) == 0;)
- {
- path_algorithms::increment_v4(it1);
- path_algorithms::increment_v4(it2);
- }
- return std::make_pair(it1, it2);
-}
-
-// normal --------------------------------------------------------------------------//
-
-BOOST_FILESYSTEM_DECL path path_algorithms::lexically_normal_v3(path const& p)
-{
- const value_type* const pathname = p.m_pathname.c_str();
- const size_type pathname_size = p.m_pathname.size();
- size_type root_name_size = 0;
- size_type root_dir_pos = find_root_directory_start(pathname, pathname_size, root_name_size);
- path normal(pathname, pathname + root_name_size);
-
-#if defined(BOOST_WINDOWS_API)
- for (size_type i = 0; i < root_name_size; ++i)
- {
- if (normal.m_pathname[i] == path::separator)
- normal.m_pathname[i] = path::preferred_separator;
- }
-#endif
-
- size_type root_path_size = root_name_size;
- if (root_dir_pos < pathname_size)
- {
- root_path_size = root_dir_pos + 1;
- normal.m_pathname.push_back(path::preferred_separator);
- }
-
- size_type i = root_path_size;
-
- // Skip redundant directory separators after the root directory
- while (i < pathname_size && detail::is_directory_separator(pathname[i]))
- ++i;
-
- if (i < pathname_size)
- {
- bool last_element_was_dot = false;
- while (true)
- {
- {
- const size_type start_pos = i;
-
- // Find next separator
- i += find_separator(pathname + i, pathname_size - i);
-
- const size_type size = i - start_pos;
-
- // Skip dot elements
- if (size == 1u && pathname[start_pos] == path::dot)
- {
- last_element_was_dot = true;
- goto skip_append;
- }
-
- last_element_was_dot = false;
-
- // Process dot dot elements
- if (size == 2u && pathname[start_pos] == path::dot && pathname[start_pos + 1] == path::dot && normal.m_pathname.size() > root_path_size)
- {
- // Don't remove previous dot dot elements
- const size_type normal_size = normal.m_pathname.size();
- size_type filename_size = find_filename_size(normal.m_pathname, root_path_size, normal_size);
- size_type pos = normal_size - filename_size;
- if (filename_size != 2u || normal.m_pathname[pos] != path::dot || normal.m_pathname[pos + 1] != path::dot)
- {
- if (pos > root_path_size && detail::is_directory_separator(normal.m_pathname[pos - 1]))
- --pos;
- normal.m_pathname.erase(normal.m_pathname.begin() + pos , normal.m_pathname.end());
- goto skip_append;
- }
- }
-
- // Append the element
- path_algorithms::append_separator_if_needed(normal);
- normal.m_pathname.append(pathname + start_pos, size);
- }
-
- skip_append:
- if (i == pathname_size)
- break;
-
- // Skip directory separators, including duplicates
- while (i < pathname_size && detail::is_directory_separator(pathname[i]))
- ++i;
-
- if (i == pathname_size)
- {
- // If a path ends with a separator, add a trailing dot element
- goto append_trailing_dot;
- }
- }
-
- if (normal.empty() || last_element_was_dot)
- {
- append_trailing_dot:
- path_algorithms::append_separator_if_needed(normal);
- normal.m_pathname.push_back(path::dot);
- }
- }
-
- return normal;
-}
-
-BOOST_FILESYSTEM_DECL path path_algorithms::lexically_normal_v4(path const& p)
-{
- const value_type* const pathname = p.m_pathname.c_str();
- const size_type pathname_size = p.m_pathname.size();
- size_type root_name_size = 0;
- size_type root_dir_pos = find_root_directory_start(pathname, pathname_size, root_name_size);
- path normal(pathname, pathname + root_name_size);
-
-#if defined(BOOST_WINDOWS_API)
- for (size_type i = 0; i < root_name_size; ++i)
- {
- if (normal.m_pathname[i] == path::separator)
- normal.m_pathname[i] = path::preferred_separator;
- }
-#endif
-
- size_type root_path_size = root_name_size;
- if (root_dir_pos < pathname_size)
- {
- root_path_size = root_dir_pos + 1;
- normal.m_pathname.push_back(path::preferred_separator);
- }
-
- size_type i = root_path_size;
-
- // Skip redundant directory separators after the root directory
- while (i < pathname_size && detail::is_directory_separator(pathname[i]))
- ++i;
-
- if (i < pathname_size)
- {
- while (true)
- {
- bool last_element_was_dot = false;
- {
- const size_type start_pos = i;
-
- // Find next separator
- i += find_separator(pathname + i, pathname_size - i);
-
- const size_type size = i - start_pos;
-
- // Skip dot elements
- if (size == 1u && pathname[start_pos] == path::dot)
- {
- last_element_was_dot = true;
- goto skip_append;
- }
-
- // Process dot dot elements
- if (size == 2u && pathname[start_pos] == path::dot && pathname[start_pos + 1] == path::dot && normal.m_pathname.size() > root_path_size)
- {
- // Don't remove previous dot dot elements
- const size_type normal_size = normal.m_pathname.size();
- size_type filename_size = find_filename_size(normal.m_pathname, root_path_size, normal_size);
- size_type pos = normal_size - filename_size;
- if (filename_size != 2u || normal.m_pathname[pos] != path::dot || normal.m_pathname[pos + 1] != path::dot)
- {
- if (pos > root_path_size && detail::is_directory_separator(normal.m_pathname[pos - 1]))
- --pos;
- normal.m_pathname.erase(normal.m_pathname.begin() + pos, normal.m_pathname.end());
- goto skip_append;
- }
- }
-
- // Append the element
- path_algorithms::append_separator_if_needed(normal);
- normal.m_pathname.append(pathname + start_pos, size);
- }
-
- skip_append:
- if (i == pathname_size)
- {
- // If a path ends with a trailing dot after a directory element, add a trailing separator
- if (last_element_was_dot && !normal.empty() && !normal.filename_is_dot_dot())
- path_algorithms::append_separator_if_needed(normal);
-
- break;
- }
-
- // Skip directory separators, including duplicates
- while (i < pathname_size && detail::is_directory_separator(pathname[i]))
- ++i;
-
- if (i == pathname_size)
- {
- // If a path ends with a separator, add a trailing separator
- if (!normal.empty() && !normal.filename_is_dot_dot())
- path_algorithms::append_separator_if_needed(normal);
- break;
- }
- }
-
- // If the original path was not empty and normalized ended up being empty, make it a dot
- if (normal.empty())
- normal.m_pathname.push_back(path::dot);
- }
-
- return normal;
-}
-
-// append --------------------------------------------------------------------------//
-
-BOOST_FILESYSTEM_DECL void path_algorithms::append_v3(path& p, const value_type* begin, const value_type* end)
-{
- if (begin != end)
- {
- if (BOOST_LIKELY(begin < p.m_pathname.data() || begin >= (p.m_pathname.data() + p.m_pathname.size())))
- {
- if (!detail::is_directory_separator(*begin))
- path_algorithms::append_separator_if_needed(p);
- p.m_pathname.append(begin, end);
- }
- else
- {
- // overlapping source
- string_type rhs(begin, end);
- path_algorithms::append_v3(p, rhs.data(), rhs.data() + rhs.size());
- }
- }
-}
-
-BOOST_FILESYSTEM_DECL void path_algorithms::append_v4(path& p, const value_type* begin, const value_type* end)
-{
- if (begin != end)
- {
- if (BOOST_LIKELY(begin < p.m_pathname.data() || begin >= (p.m_pathname.data() + p.m_pathname.size())))
- {
- const size_type that_size = end - begin;
- size_type that_root_name_size = 0;
- size_type that_root_dir_pos = find_root_directory_start(begin, that_size, that_root_name_size);
-
- // if (p.is_absolute())
- if
- (
-#if defined(BOOST_WINDOWS_API) && !defined(UNDER_CE)
- that_root_name_size > 0 &&
-#endif
- that_root_dir_pos < that_size
- )
- {
- return_assign:
- p.assign(begin, end);
- return;
- }
-
- size_type this_root_name_size = 0;
- find_root_directory_start(p.m_pathname.c_str(), p.m_pathname.size(), this_root_name_size);
-
- if
- (
- that_root_name_size > 0 &&
- (that_root_name_size != this_root_name_size || std::memcmp(p.m_pathname.c_str(), begin, this_root_name_size * sizeof(value_type)) != 0)
- )
- {
- goto return_assign;
- }
-
- if (that_root_dir_pos < that_size)
- {
- // Remove root directory (if any) and relative path to replace with those from p
- p.m_pathname.erase(p.m_pathname.begin() + this_root_name_size, p.m_pathname.end());
- }
-
- const value_type* const that_path = begin + that_root_name_size;
- if (!detail::is_directory_separator(*that_path))
- path_algorithms::append_separator_if_needed(p);
- p.m_pathname.append(that_path, end);
- }
- else
- {
- // overlapping source
- string_type rhs(begin, end);
- path_algorithms::append_v4(p, rhs.data(), rhs.data() + rhs.size());
- }
- }
- else if (path_algorithms::has_filename_v4(p))
- {
- p.m_pathname.push_back(path::preferred_separator);
- }
-}
-
-// compare -------------------------------------------------------------------------//
-
-BOOST_FILESYSTEM_DECL int path_algorithms::lex_compare_v3
-(
- path_detail::path_iterator first1, path_detail::path_iterator const& last1,
- path_detail::path_iterator first2, path_detail::path_iterator const& last2
-)
-{
- for (; first1 != last1 && first2 != last2;)
- {
- if (first1->native() < first2->native())
- return -1;
- if (first2->native() < first1->native())
- return 1;
- BOOST_ASSERT(first2->native() == first1->native());
- path_algorithms::increment_v3(first1);
- path_algorithms::increment_v3(first2);
- }
- if (first1 == last1 && first2 == last2)
- return 0;
- return first1 == last1 ? -1 : 1;
-}
-
-BOOST_FILESYSTEM_DECL int path_algorithms::lex_compare_v4
-(
- path_detail::path_iterator first1, path_detail::path_iterator const& last1,
- path_detail::path_iterator first2, path_detail::path_iterator const& last2
-)
-{
- for (; first1 != last1 && first2 != last2;)
- {
- if (first1->native() < first2->native())
- return -1;
- if (first2->native() < first1->native())
- return 1;
- BOOST_ASSERT(first2->native() == first1->native());
- path_algorithms::increment_v4(first1);
- path_algorithms::increment_v4(first2);
- }
- if (first1 == last1 && first2 == last2)
- return 0;
- return first1 == last1 ? -1 : 1;
-}
-
-BOOST_FILESYSTEM_DECL int path_algorithms::compare_v3(path const& left, path const& right)
-{
- return path_algorithms::lex_compare_v3(left.begin(), left.end(), right.begin(), right.end());
-}
-
-BOOST_FILESYSTEM_DECL int path_algorithms::compare_v4(path const& left, path const& right)
-{
- return path_algorithms::lex_compare_v4(left.begin(), left.end(), right.begin(), right.end());
-}
-
-// append_separator_if_needed ------------------------------------------------------//
-
-BOOST_FILESYSTEM_DECL path_algorithms::string_type::size_type path_algorithms::append_separator_if_needed(path& p)
-{
- if (!p.m_pathname.empty() &&
-#ifdef BOOST_WINDOWS_API
- *(p.m_pathname.end() - 1) != colon &&
-#endif
- !detail::is_directory_separator(*(p.m_pathname.end() - 1)))
- {
- string_type::size_type tmp(p.m_pathname.size());
- p.m_pathname.push_back(path::preferred_separator);
- return tmp;
- }
- return 0;
-}
-
-// erase_redundant_separator -------------------------------------------------------//
-
-BOOST_FILESYSTEM_DECL void path_algorithms::erase_redundant_separator(path& p, string_type::size_type sep_pos)
-{
- if (sep_pos // a separator was added
- && sep_pos < p.m_pathname.size() // and something was appended
- && (p.m_pathname[sep_pos + 1] == path::separator // and it was also separator
-#ifdef BOOST_WINDOWS_API
- || p.m_pathname[sep_pos + 1] == path::preferred_separator // or preferred_separator
-#endif
- ))
- {
- p.m_pathname.erase(p.m_pathname.begin() + sep_pos); // erase the added separator
- }
-}
-
-// modifiers -----------------------------------------------------------------------//
-
-BOOST_FILESYSTEM_DECL void path_algorithms::remove_filename_v3(path& p)
-{
- p.remove_filename_and_trailing_separators();
-}
-
-BOOST_FILESYSTEM_DECL void path_algorithms::remove_filename_v4(path& p)
-{
- size_type filename_size = path_algorithms::find_filename_v4_size(p);
- p.m_pathname.erase(p.m_pathname.begin() + (p.m_pathname.size() - filename_size), p.m_pathname.end());
-}
-
-BOOST_FILESYSTEM_DECL void path_algorithms::replace_extension_v3(path& p, path const& new_extension)
-{
- // erase existing extension, including the dot, if any
- size_type ext_pos = p.m_pathname.size() - path_algorithms::extension_v3(p).m_pathname.size();
- p.m_pathname.erase(p.m_pathname.begin() + ext_pos, p.m_pathname.end());
-
- if (!new_extension.empty())
- {
- // append new_extension, adding the dot if necessary
- if (new_extension.m_pathname[0] != path::dot)
- p.m_pathname.push_back(path::dot);
- p.m_pathname.append(new_extension.m_pathname);
- }
-}
-
-BOOST_FILESYSTEM_DECL void path_algorithms::replace_extension_v4(path& p, path const& new_extension)
-{
- // erase existing extension, including the dot, if any
- size_type ext_pos = p.m_pathname.size() - path_algorithms::find_extension_v4_size(p);
- p.m_pathname.erase(p.m_pathname.begin() + ext_pos, p.m_pathname.end());
-
- if (!new_extension.empty())
- {
- // append new_extension, adding the dot if necessary
- if (new_extension.m_pathname[0] != path::dot)
- p.m_pathname.push_back(path::dot);
- p.m_pathname.append(new_extension.m_pathname);
- }
-}
-
-// decomposition -------------------------------------------------------------------//
-
-BOOST_FILESYSTEM_DECL size_type path_algorithms::find_root_name_size(path const& p)
-{
- size_type root_name_size = 0;
- find_root_directory_start(p.m_pathname.c_str(), p.m_pathname.size(), root_name_size);
- return root_name_size;
-}
-
-BOOST_FILESYSTEM_DECL size_type path_algorithms::find_root_path_size(path const& p)
-{
- size_type root_name_size = 0;
- size_type root_dir_pos = find_root_directory_start(p.m_pathname.c_str(), p.m_pathname.size(), root_name_size);
-
- size_type size = root_name_size;
- if (root_dir_pos < p.m_pathname.size())
- size = root_dir_pos + 1;
-
- return size;
-}
-
-BOOST_FILESYSTEM_DECL path_algorithms::substring path_algorithms::find_root_directory(path const& p)
-{
- substring root_dir;
- size_type root_name_size = 0;
- root_dir.pos = find_root_directory_start(p.m_pathname.c_str(), p.m_pathname.size(), root_name_size);
- root_dir.size = static_cast< std::size_t >(root_dir.pos < p.m_pathname.size());
- return root_dir;
-}
-
-BOOST_FILESYSTEM_DECL path_algorithms::substring path_algorithms::find_relative_path(path const& p)
-{
- size_type root_name_size = 0;
- size_type root_dir_pos = find_root_directory_start(p.m_pathname.c_str(), p.m_pathname.size(), root_name_size);
-
- // Skip root name, root directory and any duplicate separators
- size_type size = root_name_size;
- if (root_dir_pos < p.m_pathname.size())
- {
- size = root_dir_pos + 1;
-
- for (size_type n = p.m_pathname.size(); size < n; ++size)
- {
- if (!detail::is_directory_separator(p.m_pathname[size]))
- break;
- }
- }
-
- substring rel_path;
- rel_path.pos = size;
- rel_path.size = p.m_pathname.size() - size;
-
- return rel_path;
-}
-
-BOOST_FILESYSTEM_DECL path_algorithms::string_type::size_type path_algorithms::find_parent_path_size(path const& p)
-{
- const size_type size = p.m_pathname.size();
- size_type root_name_size = 0;
- size_type root_dir_pos = find_root_directory_start(p.m_pathname.c_str(), size, root_name_size);
-
- size_type filename_size = find_filename_size(p.m_pathname, root_name_size, size);
- size_type end_pos = size - filename_size;
- while (true)
- {
- if (end_pos <= root_name_size)
- {
- // Keep the root name as the parent path if there was a filename
- if (filename_size == 0)
- end_pos = 0u;
- break;
- }
-
- --end_pos;
-
- if (!detail::is_directory_separator(p.m_pathname[end_pos]))
- {
- ++end_pos;
- break;
- }
-
- if (end_pos == root_dir_pos)
- {
- // Keep the trailing root directory if there was a filename
- end_pos += filename_size > 0;
- break;
- }
- }
-
- return end_pos;
-}
-
-BOOST_FILESYSTEM_DECL path path_algorithms::filename_v3(path const& p)
-{
- const size_type size = p.m_pathname.size();
- size_type root_name_size = 0;
- size_type root_dir_pos = find_root_directory_start(p.m_pathname.c_str(), size, root_name_size);
- size_type filename_size, pos;
- if (root_dir_pos < size && detail::is_directory_separator(p.m_pathname[size - 1]) && is_root_separator(p.m_pathname, root_dir_pos, size - 1))
- {
- // Return root directory
- pos = root_dir_pos;
- filename_size = 1u;
- }
- else if (root_name_size == size)
- {
- // Return root name
- pos = 0u;
- filename_size = root_name_size;
- }
- else
- {
- filename_size = find_filename_size(p.m_pathname, root_name_size, size);
- pos = size - filename_size;
- if (filename_size == 0u && pos > root_name_size && detail::is_directory_separator(p.m_pathname[pos - 1]) && !is_root_separator(p.m_pathname, root_dir_pos, pos - 1))
- return detail::dot_path();
- }
-
- const value_type* ptr = p.m_pathname.c_str() + pos;
- return path(ptr, ptr + filename_size);
-}
-
-BOOST_FILESYSTEM_DECL path_algorithms::string_type::size_type path_algorithms::find_filename_v4_size(path const& p)
-{
- const size_type size = p.m_pathname.size();
- size_type root_name_size = 0;
- find_root_directory_start(p.m_pathname.c_str(), size, root_name_size);
- return find_filename_size(p.m_pathname, root_name_size, size);
-}
-
-BOOST_FILESYSTEM_DECL path path_algorithms::stem_v3(path const& p)
-{
- path name(path_algorithms::filename_v3(p));
- if (path_algorithms::compare_v4(name, detail::dot_path()) != 0 && path_algorithms::compare_v4(name, detail::dot_dot_path()) != 0)
- {
- size_type pos = name.m_pathname.rfind(path::dot);
- if (pos != string_type::npos)
- name.m_pathname.erase(name.m_pathname.begin() + pos, name.m_pathname.end());
- }
- return name;
-}
-
-BOOST_FILESYSTEM_DECL path path_algorithms::stem_v4(path const& p)
-{
- path name(path_algorithms::filename_v4(p));
- if (path_algorithms::compare_v4(name, detail::dot_path()) != 0 && path_algorithms::compare_v4(name, detail::dot_dot_path()) != 0)
- {
- size_type pos = name.m_pathname.rfind(path::dot);
- if (pos != 0 && pos != string_type::npos)
- name.m_pathname.erase(name.m_pathname.begin() + pos, name.m_pathname.end());
- }
- return name;
-}
-
-BOOST_FILESYSTEM_DECL path path_algorithms::extension_v3(path const& p)
-{
- path name(path_algorithms::filename_v3(p));
- if (path_algorithms::compare_v4(name, detail::dot_path()) == 0 || path_algorithms::compare_v4(name, detail::dot_dot_path()) == 0)
- return path();
- size_type pos(name.m_pathname.rfind(path::dot));
- return pos == string_type::npos ? path() : path(name.m_pathname.c_str() + pos);
-}
-
-BOOST_FILESYSTEM_DECL path_algorithms::string_type::size_type path_algorithms::find_extension_v4_size(path const& p)
-{
- const size_type size = p.m_pathname.size();
- size_type root_name_size = 0;
- find_root_directory_start(p.m_pathname.c_str(), size, root_name_size);
- size_type filename_size = find_filename_size(p.m_pathname, root_name_size, size);
- size_type filename_pos = size - filename_size;
- if
- (
- filename_size > 0u &&
- // Check for "." and ".." filenames
- !(p.m_pathname[filename_pos] == path::dot &&
- (filename_size == 1u || (filename_size == 2u && p.m_pathname[filename_pos + 1u] == path::dot)))
- )
- {
- size_type ext_pos = size;
- while (ext_pos > filename_pos)
- {
- --ext_pos;
- if (p.m_pathname[ext_pos] == path::dot)
- break;
- }
-
- if (ext_pos > filename_pos)
- return size - ext_pos;
- }
-
- return 0u;
-}
-
-} // namespace detail
-
-BOOST_FILESYSTEM_DECL path& path::remove_filename_and_trailing_separators()
-{
- size_type end_pos = detail::path_algorithms::find_parent_path_size(*this);
- m_pathname.erase(m_pathname.begin() + end_pos, m_pathname.end());
- return *this;
-}
-
-BOOST_FILESYSTEM_DECL path& path::remove_trailing_separator()
-{
- if (!m_pathname.empty() && detail::is_directory_separator(m_pathname[m_pathname.size() - 1]))
- m_pathname.erase(m_pathname.end() - 1);
- return *this;
-}
-
-BOOST_FILESYSTEM_DECL path& path::replace_filename(path const& replacement)
-{
- detail::path_algorithms::remove_filename_v4(*this);
- detail::path_algorithms::append_v4(*this, replacement.m_pathname.data(), replacement.m_pathname.data() + replacement.m_pathname.size());
- return *this;
-}
-
-// lexical operations --------------------------------------------------------------//
-
-BOOST_FILESYSTEM_DECL path path::lexically_relative(path const& base) const
-{
- path::iterator b = begin(), e = end(), base_b = base.begin(), base_e = base.end();
- std::pair< path::iterator, path::iterator > mm = detail::mismatch(b, e, base_b, base_e);
- if (mm.first == b && mm.second == base_b)
- return path();
- if (mm.first == e && mm.second == base_e)
- return detail::dot_path();
-
- std::ptrdiff_t n = 0;
- for (; mm.second != base_e; detail::path_algorithms::increment_v4(mm.second))
- {
- path const& p = *mm.second;
- if (detail::path_algorithms::compare_v4(p, detail::dot_dot_path()) == 0)
- --n;
- else if (!p.empty() && detail::path_algorithms::compare_v4(p, detail::dot_path()) != 0)
- ++n;
- }
- if (n < 0)
- return path();
- if (n == 0 && (mm.first == e || mm.first->empty()))
- return detail::dot_path();
-
- path tmp;
- for (; n > 0; --n)
- detail::path_algorithms::append_v4(tmp, detail::dot_dot_path());
- for (; mm.first != e; detail::path_algorithms::increment_v4(mm.first))
- detail::path_algorithms::append_v4(tmp, *mm.first);
- return tmp;
-}
-
-#if defined(BOOST_WINDOWS_API)
-
-BOOST_FILESYSTEM_DECL path path::generic_path() const
-{
- path tmp(*this);
- std::replace(tmp.m_pathname.begin(), tmp.m_pathname.end(), L'\\', L'/');
- return tmp;
-}
-
-BOOST_FILESYSTEM_DECL path& path::make_preferred()
-{
- std::replace(m_pathname.begin(), m_pathname.end(), L'/', L'\\');
- return *this;
-}
-
-#endif // defined(BOOST_WINDOWS_API)
-
-} // namespace filesystem
-} // namespace boost
-
-//--------------------------------------------------------------------------------------//
-// //
-// class path helpers implementation //
-// //
-//--------------------------------------------------------------------------------------//
-
-namespace {
-
-// is_root_separator ---------------------------------------------------------------//
-
-// pos is position of the separator
-inline bool is_root_separator(string_type const& str, size_type root_dir_pos, size_type pos)
-{
- BOOST_ASSERT_MSG(pos < str.size() && fs::detail::is_directory_separator(str[pos]), "precondition violation");
-
- // root_dir_pos points at the leftmost separator, we need to skip any duplicate separators right of root dir
- while (pos > root_dir_pos && fs::detail::is_directory_separator(str[pos - 1]))
- --pos;
-
- return pos == root_dir_pos;
-}
-
-// find_filename_size --------------------------------------------------------------//
-
-// Returns: Size of the filename element that ends at end_pos (which is past-the-end position). 0 if no filename found.
-inline size_type find_filename_size(string_type const& str, size_type root_name_size, size_type end_pos)
-{
- size_type pos = end_pos;
- while (pos > root_name_size)
- {
- --pos;
-
- if (fs::detail::is_directory_separator(str[pos]))
- {
- ++pos; // filename starts past the separator
- break;
- }
- }
-
- return end_pos - pos;
-}
-
-// find_root_directory_start -------------------------------------------------------//
-
-// Returns: starting position of root directory or size if not found
-size_type find_root_directory_start(const value_type* path, size_type size, size_type& root_name_size)
-{
- root_name_size = 0;
- if (size == 0)
- return 0;
-
- bool parsing_root_name = false;
- size_type pos = 0;
-
- // case "//", possibly followed by more characters
- if (fs::detail::is_directory_separator(path[0]))
- {
- if (size >= 2 && fs::detail::is_directory_separator(path[1]))
- {
- if (size == 2)
- {
- // The whole path is just a pair of separators
- root_name_size = 2;
- return 2;
- }
-#ifdef BOOST_WINDOWS_API
- // https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file
- // cases "\\?\" and "\\.\"
- else if (size >= 4 && (path[2] == questionmark || path[2] == fs::path::dot) && fs::detail::is_directory_separator(path[3]))
- {
- parsing_root_name = true;
- pos += 4;
- }
-#endif
- else if (fs::detail::is_directory_separator(path[2]))
- {
- // The path starts with three directory separators, which is interpreted as a root directory followed by redundant separators
- return 0;
- }
- else
- {
- // case "//net {/}"
- parsing_root_name = true;
- pos += 2;
- goto find_next_separator;
- }
- }
-#ifdef BOOST_WINDOWS_API
- // https://stackoverflow.com/questions/23041983/path-prefixes-and
- // case "\??\" (NT path prefix)
- else if (size >= 4 && path[1] == questionmark && path[2] == questionmark && fs::detail::is_directory_separator(path[3]))
- {
- parsing_root_name = true;
- pos += 4;
- }
-#endif
- else
- {
- // The path starts with a separator, possibly followed by a non-separator character
- return 0;
- }
- }
-
-#ifdef BOOST_WINDOWS_API
- // case "c:" or "prn:"
- // Note: There is ambiguity in a "c:x" path interpretation. It could either mean a file "x" located at the current directory for drive C:,
- // or an alternative stream "x" of a file "c". Windows API resolve this as the former, and so do we.
- if ((size - pos) >= 2 && fs::detail::is_letter(path[pos]))
- {
- size_type i = pos + 1;
- for (; i < size; ++i)
- {
- if (!is_device_name_char(path[i]))
- break;
- }
-
- if (i < size && path[i] == colon)
- {
- pos = i + 1;
- root_name_size = pos;
- parsing_root_name = false;
-
- if (pos < size && fs::detail::is_directory_separator(path[pos]))
- return pos;
- }
- }
-#endif
-
- if (!parsing_root_name)
- return size;
-
-find_next_separator:
- pos += find_separator(path + pos, size - pos);
- if (parsing_root_name)
- root_name_size = pos;
-
- return pos;
-}
-
-//--------------------------------------------------------------------------------------//
-// //
-// class path::iterator implementation //
-// //
-//--------------------------------------------------------------------------------------//
-
-// first_element ----------------------------------------------------------------------//
-
-// sets pos and len of first element, excluding extra separators
-// if src.empty(), sets pos,len, to 0,0.
-void first_element(string_type const& src, size_type& element_pos, size_type& element_size, size_type size)
-{
- element_pos = 0;
- element_size = 0;
- if (src.empty())
- return;
-
- size_type root_name_size = 0;
- size_type root_dir_pos = find_root_directory_start(src.c_str(), size, root_name_size);
-
- // First element is the root name, if there is one
- if (root_name_size > 0)
- {
- element_size = root_name_size;
- return;
- }
-
- // Otherwise, the root directory
- if (root_dir_pos < size)
- {
- element_pos = root_dir_pos;
- element_size = 1u;
- return;
- }
-
- // Otherwise, the first filename or directory name in a relative path
- size_type end_pos = src.find_first_of(separators);
- if (end_pos == string_type::npos)
- end_pos = src.size();
- element_size = end_pos;
-}
-
-} // unnamed namespace
-
-namespace boost {
-namespace filesystem {
-namespace detail {
-
-BOOST_FILESYSTEM_DECL void path_algorithms::increment_v3(path_detail::path_iterator& it)
-{
- const size_type size = it.m_path_ptr->m_pathname.size();
- BOOST_ASSERT_MSG(it.m_pos < size, "path::iterator increment past end()");
-
- // increment to position past current element; if current element is implicit dot,
- // this will cause m_pos to represent the end iterator
- it.m_pos += it.m_element.m_pathname.size();
-
- // if the end is reached, we are done
- if (it.m_pos >= size)
- {
- BOOST_ASSERT_MSG(it.m_pos == size, "path::iterator increment after the referenced path was modified");
- it.m_element.clear(); // aids debugging
- return;
- }
-
- // process separator (Windows drive spec is only case not a separator)
- if (detail::is_directory_separator(it.m_path_ptr->m_pathname[it.m_pos]))
- {
- size_type root_name_size = 0;
- size_type root_dir_pos = find_root_directory_start(it.m_path_ptr->m_pathname.c_str(), size, root_name_size);
-
- // detect root directory and set iterator value to the separator if it is
- if (it.m_pos == root_dir_pos && it.m_element.m_pathname.size() == root_name_size)
- {
- it.m_element.m_pathname = path::separator; // generic format; see docs
- return;
- }
-
- // skip separators until m_pos points to the start of the next element
- while (it.m_pos != size && detail::is_directory_separator(it.m_path_ptr->m_pathname[it.m_pos]))
- {
- ++it.m_pos;
- }
-
- // detect trailing separator, and treat it as ".", per POSIX spec
- if (it.m_pos == size &&
- !is_root_separator(it.m_path_ptr->m_pathname, root_dir_pos, it.m_pos - 1))
- {
- --it.m_pos;
- it.m_element = detail::dot_path();
- return;
- }
- }
-
- // get m_element
- size_type end_pos = it.m_path_ptr->m_pathname.find_first_of(separators, it.m_pos);
- if (end_pos == string_type::npos)
- end_pos = size;
- const path::value_type* p = it.m_path_ptr->m_pathname.c_str();
- it.m_element.m_pathname.assign(p + it.m_pos, p + end_pos);
-}
-
-BOOST_FILESYSTEM_DECL void path_algorithms::increment_v4(path_detail::path_iterator& it)
-{
- const size_type size = it.m_path_ptr->m_pathname.size();
- BOOST_ASSERT_MSG(it.m_pos <= size, "path::iterator increment past end()");
-
- if (it.m_element.m_pathname.empty() && (it.m_pos + 1) == size && detail::is_directory_separator(it.m_path_ptr->m_pathname[it.m_pos]))
- {
- // The iterator was pointing to the last empty element of the path; set to end.
- it.m_pos = size;
- return;
- }
-
- // increment to position past current element; if current element is implicit dot,
- // this will cause m_pos to represent the end iterator
- it.m_pos += it.m_element.m_pathname.size();
-
- // if the end is reached, we are done
- if (it.m_pos >= size)
- {
- BOOST_ASSERT_MSG(it.m_pos == size, "path::iterator increment after the referenced path was modified");
- it.m_element.clear(); // aids debugging
- return;
- }
-
- // process separator (Windows drive spec is only case not a separator)
- if (detail::is_directory_separator(it.m_path_ptr->m_pathname[it.m_pos]))
- {
- size_type root_name_size = 0;
- size_type root_dir_pos = find_root_directory_start(it.m_path_ptr->m_pathname.c_str(), size, root_name_size);
-
- // detect root directory and set iterator value to the separator if it is
- if (it.m_pos == root_dir_pos && it.m_element.m_pathname.size() == root_name_size)
- {
- it.m_element.m_pathname = path::separator; // generic format; see docs
- return;
- }
-
- // skip separators until m_pos points to the start of the next element
- while (it.m_pos != size && detail::is_directory_separator(it.m_path_ptr->m_pathname[it.m_pos]))
- {
- ++it.m_pos;
- }
-
- // detect trailing separator
- if (it.m_pos == size &&
- !is_root_separator(it.m_path_ptr->m_pathname, root_dir_pos, it.m_pos - 1))
- {
- --it.m_pos;
- it.m_element.m_pathname.clear();
- return;
- }
- }
-
- // get m_element
- size_type end_pos = it.m_path_ptr->m_pathname.find_first_of(separators, it.m_pos);
- if (end_pos == string_type::npos)
- end_pos = size;
- const path::value_type* p = it.m_path_ptr->m_pathname.c_str();
- it.m_element.m_pathname.assign(p + it.m_pos, p + end_pos);
-}
-
-BOOST_FILESYSTEM_DECL void path_algorithms::decrement_v3(path_detail::path_iterator& it)
-{
- const size_type size = it.m_path_ptr->m_pathname.size();
- BOOST_ASSERT_MSG(it.m_pos > 0, "path::iterator decrement past begin()");
- BOOST_ASSERT_MSG(it.m_pos <= size, "path::iterator decrement after the referenced path was modified");
-
- size_type root_name_size = 0;
- size_type root_dir_pos = find_root_directory_start(it.m_path_ptr->m_pathname.c_str(), size, root_name_size);
-
- if (root_dir_pos < size && it.m_pos == root_dir_pos)
- {
- // Was pointing at root directory, decrement to root name
- set_to_root_name:
- it.m_pos = 0u;
- const path::value_type* p = it.m_path_ptr->m_pathname.c_str();
- it.m_element.m_pathname.assign(p, p + root_name_size);
- return;
- }
-
- // if at end and there was a trailing non-root '/', return "."
- if (it.m_pos == size &&
- size > 1 &&
- detail::is_directory_separator(it.m_path_ptr->m_pathname[it.m_pos - 1]) &&
- !is_root_separator(it.m_path_ptr->m_pathname, root_dir_pos, it.m_pos - 1))
- {
- --it.m_pos;
- it.m_element = detail::dot_path();
- return;
- }
-
- // skip separators unless root directory
- size_type end_pos = it.m_pos;
- while (end_pos > root_name_size)
- {
- --end_pos;
-
- if (end_pos == root_dir_pos)
- {
- // Decremented to the root directory
- it.m_pos = end_pos;
- it.m_element.m_pathname = path::separator; // generic format; see docs
- return;
- }
-
- if (!detail::is_directory_separator(it.m_path_ptr->m_pathname[end_pos]))
- {
- ++end_pos;
- break;
- }
- }
-
- if (end_pos <= root_name_size)
- goto set_to_root_name;
-
- size_type filename_size = find_filename_size(it.m_path_ptr->m_pathname, root_name_size, end_pos);
- it.m_pos = end_pos - filename_size;
- const path::value_type* p = it.m_path_ptr->m_pathname.c_str();
- it.m_element.m_pathname.assign(p + it.m_pos, p + end_pos);
-}
-
-BOOST_FILESYSTEM_DECL void path_algorithms::decrement_v4(path_detail::path_iterator& it)
-{
- const size_type size = it.m_path_ptr->m_pathname.size();
- BOOST_ASSERT_MSG(it.m_pos > 0, "path::iterator decrement past begin()");
- BOOST_ASSERT_MSG(it.m_pos <= size, "path::iterator decrement after the referenced path was modified");
-
- size_type root_name_size = 0;
- size_type root_dir_pos = find_root_directory_start(it.m_path_ptr->m_pathname.c_str(), size, root_name_size);
-
- if (root_dir_pos < size && it.m_pos == root_dir_pos)
- {
- // Was pointing at root directory, decrement to root name
- set_to_root_name:
- it.m_pos = 0u;
- const path::value_type* p = it.m_path_ptr->m_pathname.c_str();
- it.m_element.m_pathname.assign(p, p + root_name_size);
- return;
- }
-
- // if at end and there was a trailing '/', return ""
- if (it.m_pos == size &&
- size > 1 &&
- detail::is_directory_separator(it.m_path_ptr->m_pathname[it.m_pos - 1]) &&
- !is_root_separator(it.m_path_ptr->m_pathname, root_dir_pos, it.m_pos - 1))
- {
- --it.m_pos;
- it.m_element.m_pathname.clear();
- return;
- }
-
- // skip separators unless root directory
- size_type end_pos = it.m_pos;
- while (end_pos > root_name_size)
- {
- --end_pos;
-
- if (end_pos == root_dir_pos)
- {
- // Decremented to the root directory
- it.m_pos = end_pos;
- it.m_element.m_pathname = path::separator; // generic format; see docs
- return;
- }
-
- if (!detail::is_directory_separator(it.m_path_ptr->m_pathname[end_pos]))
- {
- ++end_pos;
- break;
- }
- }
-
- if (end_pos <= root_name_size)
- goto set_to_root_name;
-
- size_type filename_size = find_filename_size(it.m_path_ptr->m_pathname, root_name_size, end_pos);
- it.m_pos = end_pos - filename_size;
- const path::value_type* p = it.m_path_ptr->m_pathname.c_str();
- it.m_element.m_pathname.assign(p + it.m_pos, p + end_pos);
-}
-
-} // namespace detail
-
-// path iterators ------------------------------------------------------------------//
-
-BOOST_FILESYSTEM_DECL path::iterator path::begin() const
-{
- iterator itr;
- itr.m_path_ptr = this;
-
- size_type element_size;
- first_element(m_pathname, itr.m_pos, element_size);
-
- if (element_size > 0)
- {
- itr.m_element = m_pathname.substr(itr.m_pos, element_size);
-#ifdef BOOST_WINDOWS_API
- if (itr.m_element.m_pathname.size() == 1u && itr.m_element.m_pathname[0] == path::preferred_separator)
- itr.m_element.m_pathname[0] = path::separator;
-#endif
- }
-
- return itr;
-}
-
-BOOST_FILESYSTEM_DECL path::iterator path::end() const
-{
- iterator itr;
- itr.m_path_ptr = this;
- itr.m_pos = m_pathname.size();
- return itr;
-}
-
-} // namespace filesystem
-} // namespace boost
-
-namespace {
-
-//------------------------------------------------------------------------------------//
-// locale helpers //
-//------------------------------------------------------------------------------------//
-
-// Prior versions of these locale and codecvt implementations tried to take advantage
-// of static initialization where possible, kept a local copy of the current codecvt
-// facet (to avoid codecvt() having to call use_facet()), and was not multi-threading
-// safe (again for efficiency).
-//
-// This was error prone, and required different implementation techniques depending
-// on the compiler and also whether static or dynamic linking was used. Furthermore,
-// users could not easily provide their multi-threading safe wrappers because the
-// path interface requires the implementation itself to call codecvt() to obtain the
-// default facet, and the initialization of the static within path_locale() could race.
-//
-// The code below is portable to all platforms, is much simpler, and hopefully will be
-// much more robust. Timing tests (on Windows, using a Visual C++ release build)
-// indicated the current code is roughly 9% slower than the previous code, and that
-// seems a small price to pay for better code that is easier to use.
-
-std::locale default_locale()
-{
-#if defined(BOOST_WINDOWS_API)
- std::locale global_loc = std::locale();
- return std::locale(global_loc, new boost::filesystem::detail::windows_file_codecvt());
-#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__HAIKU__)
- // "All BSD system functions expect their string parameters to be in UTF-8 encoding
- // and nothing else." See
- // http://developer.apple.com/mac/library/documentation/MacOSX/Conceptual/BPInternational/Articles/FileEncodings.html
- //
- // "The kernel will reject any filename that is not a valid UTF-8 string, and it will
- // even be normalized (to Unicode NFD) before stored on disk, at least when using HFS.
- // The right way to deal with it would be to always convert the filename to UTF-8
- // before trying to open/create a file." See
- // http://lists.apple.com/archives/unix-porting/2007/Sep/msg00023.html
- //
- // "How a file name looks at the API level depends on the API. Current Carbon APIs
- // handle file names as an array of UTF-16 characters; POSIX ones handle them as an
- // array of UTF-8, which is why UTF-8 works well in Terminal. How it's stored on disk
- // depends on the disk format; HFS+ uses UTF-16, but that's not important in most
- // cases." See
- // http://lists.apple.com/archives/applescript-users/2002/Sep/msg00319.html
- //
- // Many thanks to Peter Dimov for digging out the above references!
-
- std::locale global_loc = std::locale();
- return std::locale(global_loc, new boost::filesystem::detail::utf8_codecvt_facet());
-#else // Other POSIX
- // ISO C calls std::locale("") "the locale-specific native environment", and this
- // locale is the default for many POSIX-based operating systems such as Linux.
- return std::locale("");
-#endif
-}
-
-std::locale* g_path_locale = NULL;
-
-void schedule_path_locale_cleanup() BOOST_NOEXCEPT;
-
-// std::locale("") construction, needed on non-Apple POSIX systems, can throw
-// (if environmental variables LC_MESSAGES or LANG are wrong, for example), so
-// get_path_locale() provides lazy initialization to ensure that any
-// exceptions occur after main() starts and so can be caught. Furthermore,
-// g_path_locale is only initialized if path::codecvt() or path::imbue() are themselves
-// actually called, ensuring that an exception will only be thrown if std::locale("")
-// is really needed.
-inline std::locale& get_path_locale()
-{
-#if !defined(BOOST_FILESYSTEM_SINGLE_THREADED)
- atomic_ns::atomic_ref< std::locale* > a(g_path_locale);
- std::locale* p = a.load(atomic_ns::memory_order_acquire);
- if (BOOST_UNLIKELY(!p))
- {
- std::locale* new_p = new std::locale(default_locale());
- if (a.compare_exchange_strong(p, new_p, atomic_ns::memory_order_acq_rel, atomic_ns::memory_order_acquire))
- {
- p = new_p;
- schedule_path_locale_cleanup();
- }
- else
- {
- delete new_p;
- }
- }
- return *p;
-#else // !defined(BOOST_FILESYSTEM_SINGLE_THREADED)
- std::locale* p = g_path_locale;
- if (BOOST_UNLIKELY(!p))
- {
- g_path_locale = p = new std::locale(default_locale());
- schedule_path_locale_cleanup();
- }
- return *p;
-#endif // !defined(BOOST_FILESYSTEM_SINGLE_THREADED)
-}
-
-inline std::locale* replace_path_locale(std::locale const& loc)
-{
- std::locale* new_p = new std::locale(loc);
-#if !defined(BOOST_FILESYSTEM_SINGLE_THREADED)
- std::locale* p = atomic_ns::atomic_ref< std::locale* >(g_path_locale).exchange(new_p, atomic_ns::memory_order_acq_rel);
-#else
- std::locale* p = g_path_locale;
- g_path_locale = new_p;
-#endif
- if (!p)
- schedule_path_locale_cleanup();
- return p;
-}
-
-#if defined(_MSC_VER)
-
-const boost::filesystem::path* g_dot_path = NULL;
-const boost::filesystem::path* g_dot_dot_path = NULL;
-
-inline void schedule_path_locale_cleanup() BOOST_NOEXCEPT
-{
-}
-
-inline boost::filesystem::path const& get_dot_path()
-{
-#if !defined(BOOST_FILESYSTEM_SINGLE_THREADED)
- atomic_ns::atomic_ref< const boost::filesystem::path* > a(g_dot_path);
- const boost::filesystem::path* p = a.load(atomic_ns::memory_order_acquire);
- if (BOOST_UNLIKELY(!p))
- {
- const boost::filesystem::path* new_p = new boost::filesystem::path(dot_path_literal);
- if (a.compare_exchange_strong(p, new_p, atomic_ns::memory_order_acq_rel, atomic_ns::memory_order_acquire))
- p = new_p;
- else
- delete new_p;
- }
- return *p;
-#else // !defined(BOOST_FILESYSTEM_SINGLE_THREADED)
- const boost::filesystem::path* p = g_dot_path;
- if (BOOST_UNLIKELY(!p))
- g_dot_path = p = new boost::filesystem::path(dot_path_literal);
- return *p;
-#endif // !defined(BOOST_FILESYSTEM_SINGLE_THREADED)
-}
-
-inline boost::filesystem::path const& get_dot_dot_path()
-{
-#if !defined(BOOST_FILESYSTEM_SINGLE_THREADED)
- atomic_ns::atomic_ref< const boost::filesystem::path* > a(g_dot_dot_path);
- const boost::filesystem::path* p = a.load(atomic_ns::memory_order_acquire);
- if (BOOST_UNLIKELY(!p))
- {
- const boost::filesystem::path* new_p = new boost::filesystem::path(dot_dot_path_literal);
- if (a.compare_exchange_strong(p, new_p, atomic_ns::memory_order_acq_rel, atomic_ns::memory_order_acquire))
- p = new_p;
- else
- delete new_p;
- }
- return *p;
-#else // !defined(BOOST_FILESYSTEM_SINGLE_THREADED)
- const boost::filesystem::path* p = g_dot_dot_path;
- if (BOOST_UNLIKELY(!p))
- g_dot_dot_path = p = new boost::filesystem::path(dot_dot_path_literal);
- return *p;
-#endif // !defined(BOOST_FILESYSTEM_SINGLE_THREADED)
-}
-
-void __cdecl destroy_path_globals()
-{
- delete g_dot_dot_path;
- g_dot_dot_path = NULL;
- delete g_dot_path;
- g_dot_path = NULL;
- delete g_path_locale;
- g_path_locale = NULL;
-}
-
-BOOST_FILESYSTEM_INIT_FUNC init_path_globals()
-{
-#if !defined(BOOST_SYSTEM_HAS_CONSTEXPR)
- // codecvt_error_category needs to be called early to dynamic-initialize the error category instance
- boost::filesystem::codecvt_error_category();
-#endif
- std::atexit(&destroy_path_globals);
- return BOOST_FILESYSTEM_INITRETSUCCESS_V;
-}
-
-#if _MSC_VER >= 1400
-
-#pragma section(".CRT$XCM", long, read)
-__declspec(allocate(".CRT$XCM")) BOOST_ATTRIBUTE_UNUSED BOOST_FILESYSTEM_ATTRIBUTE_RETAIN
-extern const init_func_ptr_t p_init_path_globals = &init_path_globals;
-
-#else // _MSC_VER >= 1400
-
-#if (_MSC_VER >= 1300) // 1300 == VC++ 7.0
-#pragma data_seg(push, old_seg)
-#endif
-#pragma data_seg(".CRT$XCM")
-BOOST_ATTRIBUTE_UNUSED BOOST_FILESYSTEM_ATTRIBUTE_RETAIN
-extern const init_func_ptr_t p_init_path_globals = &init_path_globals;
-#pragma data_seg()
-#if (_MSC_VER >= 1300) // 1300 == VC++ 7.0
-#pragma data_seg(pop, old_seg)
-#endif
-
-#endif // _MSC_VER >= 1400
-
-#if defined(BOOST_FILESYSTEM_NO_ATTRIBUTE_RETAIN)
-//! Makes sure the global initializer pointers are referenced and not removed by linker
-struct globals_retainer
-{
- const init_func_ptr_t* volatile m_p_init_path_globals;
-
- globals_retainer() { m_p_init_path_globals = &p_init_path_globals; }
-};
-BOOST_ATTRIBUTE_UNUSED
-static const globals_retainer g_globals_retainer;
-#endif // defined(BOOST_FILESYSTEM_NO_ATTRIBUTE_RETAIN)
-
-#else // defined(_MSC_VER)
-
-struct path_locale_deleter
-{
- ~path_locale_deleter()
- {
- delete g_path_locale;
- g_path_locale = NULL;
- }
-};
-
-#if defined(BOOST_FILESYSTEM_HAS_INIT_PRIORITY)
-
-BOOST_FILESYSTEM_INIT_PRIORITY(BOOST_FILESYSTEM_PATH_GLOBALS_INIT_PRIORITY) BOOST_ATTRIBUTE_UNUSED
-const path_locale_deleter g_path_locale_deleter = {};
-BOOST_FILESYSTEM_INIT_PRIORITY(BOOST_FILESYSTEM_PATH_GLOBALS_INIT_PRIORITY)
-const boost::filesystem::path g_dot_path(dot_path_literal);
-BOOST_FILESYSTEM_INIT_PRIORITY(BOOST_FILESYSTEM_PATH_GLOBALS_INIT_PRIORITY)
-const boost::filesystem::path g_dot_dot_path(dot_dot_path_literal);
-
-inline void schedule_path_locale_cleanup() BOOST_NOEXCEPT
-{
-}
-
-inline boost::filesystem::path const& get_dot_path()
-{
- return g_dot_path;
-}
-
-inline boost::filesystem::path const& get_dot_dot_path()
-{
- return g_dot_dot_path;
-}
-
-#else // defined(BOOST_FILESYSTEM_HAS_INIT_PRIORITY)
-
-inline void schedule_path_locale_cleanup() BOOST_NOEXCEPT
-{
- BOOST_ATTRIBUTE_UNUSED static const path_locale_deleter g_path_locale_deleter;
-}
-
-inline boost::filesystem::path const& get_dot_path()
-{
- static const boost::filesystem::path g_dot_path(dot_path_literal);
- return g_dot_path;
-}
-
-inline boost::filesystem::path const& get_dot_dot_path()
-{
- static const boost::filesystem::path g_dot_dot_path(dot_dot_path_literal);
- return g_dot_dot_path;
-}
-
-#endif // defined(BOOST_FILESYSTEM_HAS_INIT_PRIORITY)
-
-#endif // defined(_MSC_VER)
-
-} // unnamed namespace
-
-//--------------------------------------------------------------------------------------//
-// path::codecvt() and path::imbue() implementation //
-//--------------------------------------------------------------------------------------//
-
-namespace boost {
-namespace filesystem {
-
-BOOST_FILESYSTEM_DECL path::codecvt_type const& path::codecvt()
-{
-#ifdef BOOST_FILESYSTEM_DEBUG
- std::cout << "***** path::codecvt() called" << std::endl;
-#endif
- return std::use_facet< std::codecvt< wchar_t, char, std::mbstate_t > >(get_path_locale());
-}
-
-BOOST_FILESYSTEM_DECL std::locale path::imbue(std::locale const& loc)
-{
-#ifdef BOOST_FILESYSTEM_DEBUG
- std::cout << "***** path::imbue() called" << std::endl;
-#endif
- std::locale* p = replace_path_locale(loc);
- if (BOOST_LIKELY(p != NULL))
- {
- // Note: copying/moving std::locale does not throw
-#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
- std::locale temp(std::move(*p));
-#else
- std::locale temp(*p);
-#endif
- delete p;
- return temp;
- }
-
- return default_locale();
-}
-
-namespace detail {
-
-BOOST_FILESYSTEM_DECL path const& dot_path()
-{
- return get_dot_path();
-}
-
-BOOST_FILESYSTEM_DECL path const& dot_dot_path()
-{
- return get_dot_dot_path();
-}
-
-} // namespace detail
-} // namespace filesystem
-} // namespace boost
-
-#include <boost/filesystem/detail/footer.hpp>