BVB Source Codes

mars Show path.cpp Source code

Return Download mars: download path.cpp Source code - Download mars Source code - Type:.cpp
  1. //  filesystem path.cpp  -------------------------------------------------------------  //
  2.  
  3. //  Copyright Beman Dawes 2008
  4.  
  5. //  Distributed under the Boost Software License, Version 1.0.
  6. //  See http://www.boost.org/LICENSE_1_0.txt
  7.  
  8. //  Library home page: http://www.boost.org/libs/filesystem
  9.  
  10. //  Old standard library configurations, particularly MingGW, don't support wide strings.
  11. //  Report this with an explicit error message.
  12. #include <boost/config.hpp>
  13. # if defined( BOOST_NO_STD_WSTRING )
  14. #   error Configuration not supported: Boost.Filesystem V3 and later requires std::wstring support
  15. # endif
  16.  
  17. // define BOOST_FILESYSTEM_SOURCE so that <boost/system/config.hpp> knows
  18. // the library is being built (possibly exporting rather than importing code)
  19. #define BOOST_FILESYSTEM_SOURCE
  20.  
  21. #ifndef BOOST_SYSTEM_NO_DEPRECATED
  22. # define BOOST_SYSTEM_NO_DEPRECATED
  23. #endif
  24.  
  25. #include <boost/filesystem/config.hpp>
  26. #include <boost/filesystem/path.hpp>
  27. #include <boost/filesystem/operations.hpp>  // for filesystem_error
  28. #include <boost/scoped_array.hpp>
  29. #include <boost/system/error_code.hpp>
  30. #include <boost/assert.hpp>
  31. #include <algorithm>
  32. #include <cstddef>
  33. #include <cstring>
  34. #include <cassert>
  35.  
  36. #ifdef BOOST_WINDOWS_API
  37. # include "windows_file_codecvt.hpp"
  38. # include <windows.h>
  39. #elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) \
  40.  || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__HAIKU__)
  41. # include <boost/filesystem/detail/utf8_codecvt_facet.hpp>
  42. #endif
  43.  
  44. #ifdef BOOST_FILESYSTEM_DEBUG
  45. # include <iostream>
  46. # include <iomanip>
  47. #endif
  48.  
  49. namespace fs = mars_boost::filesystem;
  50.  
  51. using mars_boost::filesystem::path;
  52.  
  53. using std::string;
  54. using std::wstring;
  55.  
  56. using mars_boost::system::error_code;
  57.  
  58. //--------------------------------------------------------------------------------------//
  59. //                                                                                      //
  60. //                                class path helpers                                    //
  61. //                                                                                      //
  62. //--------------------------------------------------------------------------------------//
  63.  
  64. namespace
  65. {
  66.   //------------------------------------------------------------------------------------//
  67.   //                        miscellaneous class path helpers                            //
  68.   //------------------------------------------------------------------------------------//
  69.  
  70.   typedef path::value_type        value_type;
  71.   typedef path::string_type       string_type;
  72.   typedef string_type::size_type  size_type;
  73.  
  74. # ifdef BOOST_WINDOWS_API
  75.  
  76.   const wchar_t separator = L'/';
  77.   const wchar_t* const separators = L"/\\";
  78.   const wchar_t* separator_string = L"/";
  79.   const wchar_t* preferred_separator_string = L"\\";
  80.   const wchar_t colon = L':';
  81.   const wchar_t dot = L'.';
  82.   const wchar_t questionmark = L'?';
  83.  
  84.   inline bool is_letter(wchar_t c)
  85.   {
  86.     return (c >= L'a' && c <=L'z') || (c >= L'A' && c <=L'Z');
  87.   }
  88.  
  89. # else
  90.  
  91.   const char separator = '/';
  92.   const char* const separators = "/";
  93.   const char* separator_string = "/";
  94.   const char* preferred_separator_string = "/";
  95.   const char dot = '.';
  96.  
  97. # endif
  98.  
  99.   inline bool is_separator(fs::path::value_type c)
  100.   {
  101.     return c == separator
  102. #     ifdef BOOST_WINDOWS_API
  103.       || c == path::preferred_separator
  104. #     endif
  105.       ;
  106.   }
  107.  
  108.   bool is_root_separator(const string_type& str, size_type pos);
  109.     // pos is position of the separator
  110.  
  111.   size_type filename_pos(const string_type& str,
  112.                           size_type end_pos); // end_pos is past-the-end position
  113.   //  Returns: 0 if str itself is filename (or empty)
  114.  
  115.   size_type root_directory_start(const string_type& path, size_type size);
  116.   //  Returns:  npos if no root_directory found
  117.  
  118.   void first_element(
  119.       const string_type& src,
  120.       size_type& element_pos,
  121.       size_type& element_size,
  122. #     if !BOOST_WORKAROUND(BOOST_MSVC, <= 1310) // VC++ 7.1
  123.       size_type size = string_type::npos
  124. #     else
  125.       size_type size = -1
  126. #     endif
  127.     );
  128.  
  129. }  // unnamed namespace
  130.  
  131. //--------------------------------------------------------------------------------------//
  132. //                                                                                      //
  133. //                            class path implementation                                 //
  134. //                                                                                      //
  135. //--------------------------------------------------------------------------------------//
  136.  
  137. namespace mars_boost {} namespace boost = mars_boost; namespace mars_boost
  138. {
  139. namespace filesystem
  140. {
  141.   path& path::operator/=(const path& p)
  142.   {
  143.     if (p.empty())
  144.       return *this;
  145.     if (this == &p)  // self-append
  146.     {
  147.       path rhs(p);
  148.       if (!is_separator(rhs.m_pathname[0]))
  149.         m_append_separator_if_needed();
  150.       m_pathname += rhs.m_pathname;
  151.     }
  152.     else
  153.     {
  154.       if (!is_separator(*p.m_pathname.begin()))
  155.         m_append_separator_if_needed();
  156.       m_pathname += p.m_pathname;
  157.     }
  158.     return *this;
  159.   }
  160.  
  161.   path& path::operator/=(const value_type* ptr)
  162.   {
  163.     if (!*ptr)
  164.       return *this;
  165.     if (ptr >= m_pathname.data()
  166.       && ptr < m_pathname.data() + m_pathname.size())  // overlapping source
  167.     {
  168.       path rhs(ptr);
  169.       if (!is_separator(rhs.m_pathname[0]))
  170.         m_append_separator_if_needed();
  171.       m_pathname += rhs.m_pathname;
  172.     }
  173.     else
  174.     {
  175.       if (!is_separator(*ptr))
  176.         m_append_separator_if_needed();
  177.       m_pathname += ptr;
  178.     }
  179.     return *this;
  180.   }
  181.  
  182.   int path::compare(const path& p) const BOOST_NOEXCEPT
  183.   {
  184.     return detail::lex_compare(begin(), end(), p.begin(), p.end());
  185.   }
  186.  
  187. # ifdef BOOST_WINDOWS_API
  188.  
  189.   const std::string path::generic_string() const
  190.   {
  191.     path tmp(*this);
  192.     std::replace(tmp.m_pathname.begin(), tmp.m_pathname.end(), L'\\', L'/');
  193.     return tmp.string();
  194.   }
  195.  
  196.   const std::string path::generic_string(const codecvt_type& cvt) const
  197.   {
  198.     path tmp(*this);
  199.     std::replace(tmp.m_pathname.begin(), tmp.m_pathname.end(), L'\\', L'/');
  200.     return tmp.string(cvt);
  201.   }
  202.  
  203.   const std::wstring path::generic_wstring() const
  204.   {
  205.     path tmp(*this);
  206.     std::replace(tmp.m_pathname.begin(), tmp.m_pathname.end(), L'\\', L'/');
  207.     return tmp.wstring();
  208.   }
  209.  
  210. # endif  // BOOST_WINDOWS_API
  211.  
  212.   //  m_append_separator_if_needed  ----------------------------------------------------//
  213.  
  214.   path::string_type::size_type path::m_append_separator_if_needed()
  215.   {
  216.     if (!m_pathname.empty() &&
  217. #     ifdef BOOST_WINDOWS_API
  218.       *(m_pathname.end()-1) != colon &&
  219. #     endif
  220.       !is_separator(*(m_pathname.end()-1)))
  221.     {
  222.       string_type::size_type tmp(m_pathname.size());
  223.       m_pathname += preferred_separator;
  224.       return tmp;
  225.     }
  226.     return 0;
  227.   }
  228.  
  229.   //  m_erase_redundant_separator  -----------------------------------------------------//
  230.  
  231.   void path::m_erase_redundant_separator(string_type::size_type sep_pos)
  232.   {
  233.     if (sep_pos                         // a separator was added
  234.       && sep_pos < m_pathname.size()         // and something was appended
  235.       && (m_pathname[sep_pos+1] == separator // and it was also separator
  236. #      ifdef BOOST_WINDOWS_API
  237.        || m_pathname[sep_pos+1] == preferred_separator  // or preferred_separator
  238. #      endif
  239. )) { m_pathname.erase(sep_pos, 1); } // erase the added separator
  240.   }
  241.  
  242.   //  modifiers  -----------------------------------------------------------------------//
  243.  
  244. # ifdef BOOST_WINDOWS_API
  245.   path & path::make_preferred()
  246.   {
  247.     std::replace(m_pathname.begin(), m_pathname.end(), L'/', L'\\');
  248.     return *this;
  249.   }
  250. # endif
  251.  
  252.   path& path::remove_filename()
  253.   {
  254.     m_pathname.erase(m_parent_path_end());
  255.     return *this;
  256.   }
  257.  
  258.   path&  path::remove_trailing_separator()
  259.   {
  260.     if (!m_pathname.empty() && is_separator(m_pathname[m_pathname.size() - 1]))
  261.       m_pathname.erase(m_pathname.size() - 1);
  262.     return *this;
  263.   }
  264.  
  265.   path& path::replace_extension(const path& new_extension)
  266.   {
  267.     // erase existing extension, including the dot, if any
  268.     m_pathname.erase(m_pathname.size()-extension().m_pathname.size());
  269.  
  270.     if (!new_extension.empty())
  271.     {
  272.       // append new_extension, adding the dot if necessary
  273.       if (new_extension.m_pathname[0] != dot)
  274.         m_pathname.push_back(dot);
  275.       m_pathname.append(new_extension.m_pathname);
  276.     }
  277.  
  278.     return *this;
  279.   }
  280.  
  281.   //  decomposition  -------------------------------------------------------------------//
  282.  
  283.   path  path::root_path() const
  284.   {
  285.     path temp(root_name());
  286.     if (!root_directory().empty()) temp.m_pathname += root_directory().c_str();
  287.     return temp;
  288.   }
  289.  
  290.   path path::root_name() const
  291.   {
  292.     iterator itr(begin());
  293.  
  294.     return (itr.m_pos != m_pathname.size()
  295.       && (
  296.           (itr.m_element.m_pathname.size() > 1
  297.             && is_separator(itr.m_element.m_pathname[0])
  298.             && is_separator(itr.m_element.m_pathname[1])
  299.    )
  300. #       ifdef BOOST_WINDOWS_API
  301.         || itr.m_element.m_pathname[itr.m_element.m_pathname.size()-1] == colon
  302. #       endif
  303.   ))
  304.       ? itr.m_element
  305.       : path();
  306.   }
  307.  
  308.   path path::root_directory() const
  309.   {
  310.     size_type pos(root_directory_start(m_pathname, m_pathname.size()));
  311.  
  312.     return pos == string_type::npos
  313.       ? path()
  314.       : path(m_pathname.c_str() + pos, m_pathname.c_str() + pos + 1);
  315.   }
  316.  
  317.   path path::relative_path() const
  318.   {
  319.     iterator itr(begin());
  320.  
  321.     for (; itr.m_pos != m_pathname.size()
  322.       && (is_separator(itr.m_element.m_pathname[0])
  323. #     ifdef BOOST_WINDOWS_API
  324.       || itr.m_element.m_pathname[itr.m_element.m_pathname.size()-1] == colon
  325. #     endif
  326.     ); ++itr) {}
  327.  
  328.     return path(m_pathname.c_str() + itr.m_pos);
  329.   }
  330.  
  331.   string_type::size_type path::m_parent_path_end() const
  332.   {
  333.     size_type end_pos(filename_pos(m_pathname, m_pathname.size()));
  334.  
  335.     bool filename_was_separator(m_pathname.size()
  336.       && is_separator(m_pathname[end_pos]));
  337.  
  338.     // skip separators unless root directory
  339.     size_type root_dir_pos(root_directory_start(m_pathname, end_pos));
  340.     for (;
  341.       end_pos > 0
  342.       && (end_pos-1) != root_dir_pos
  343.       && is_separator(m_pathname[end_pos-1])
  344.       ;
  345.       --end_pos) {}
  346.  
  347.    return (end_pos == 1 && root_dir_pos == 0 && filename_was_separator)
  348.      ? string_type::npos
  349.      : end_pos;
  350.   }
  351.  
  352.   path path::parent_path() const
  353.   {
  354.    size_type end_pos(m_parent_path_end());
  355.    return end_pos == string_type::npos
  356.      ? path()
  357.      : path(m_pathname.c_str(), m_pathname.c_str() + end_pos);
  358.   }
  359.  
  360.   path path::filename() const
  361.   {
  362.     size_type pos(filename_pos(m_pathname, m_pathname.size()));
  363.     return (m_pathname.size()
  364.               && pos
  365.               && is_separator(m_pathname[pos])
  366.               && !is_root_separator(m_pathname, pos))
  367.       ? detail::dot_path()
  368.       : path(m_pathname.c_str() + pos);
  369.   }
  370.  
  371.   path path::stem() const
  372.   {
  373.     path name(filename());
  374.     if (name == detail::dot_path() || name == detail::dot_dot_path()) return name;
  375.     size_type pos(name.m_pathname.rfind(dot));
  376.     return pos == string_type::npos
  377.       ? name
  378.       : path(name.m_pathname.c_str(), name.m_pathname.c_str() + pos);
  379.   }
  380.  
  381.   path path::extension() const
  382.   {
  383.     path name(filename());
  384.     if (name == detail::dot_path() || name == detail::dot_dot_path()) return path();
  385.     size_type pos(name.m_pathname.rfind(dot));
  386.     return pos == string_type::npos
  387.       ? path()
  388.       : path(name.m_pathname.c_str() + pos);
  389.   }
  390.  
  391.   //  lexical operations  --------------------------------------------------------------//
  392.  
  393.   namespace detail
  394.   {
  395.     // C++14 provide a mismatch algorithm with four iterator arguments(), but earlier
  396.     // standard libraries didn't, so provide this needed functionality.
  397.     inline
  398.     std::pair<path::iterator, path::iterator> mismatch(path::iterator it1,
  399.       path::iterator it1end, path::iterator it2, path::iterator it2end)
  400.     {
  401.       for (; it1 != it1end && it2 != it2end && *it1 == *it2;)
  402.       {
  403.         ++it1;
  404.         ++it2;
  405.       }
  406.       return std::make_pair(it1, it2);
  407.     }
  408.   }
  409.  
  410.   path path::lexically_relative(const path& base) const
  411.   {
  412.     std::pair<path::iterator, path::iterator> mm
  413.       = detail::mismatch(begin(), end(), base.begin(), base.end());
  414.     if (mm.first == begin() && mm.second == base.begin())
  415.       return path();
  416.     if (mm.first == end() && mm.second == base.end())
  417.       return detail::dot_path();
  418.     path tmp;
  419.     for (; mm.second != base.end(); ++mm.second)
  420.       tmp /= detail::dot_dot_path();
  421.     for (; mm.first != end(); ++mm.first)
  422.       tmp /= *mm.first;
  423.     return tmp;
  424.   }
  425.  
  426.   //  normal  --------------------------------------------------------------------------//
  427.  
  428.   path path::lexically_normal() const
  429.   {
  430.     if (m_pathname.empty())
  431.       return *this;
  432.      
  433.     path temp;
  434.     iterator start(begin());
  435.     iterator last(end());
  436.     iterator stop(last--);
  437.     for (iterator itr(start); itr != stop; ++itr)
  438.     {
  439.       // ignore "." except at start and last
  440.       if (itr->native().size() == 1
  441.         && (itr->native())[0] == dot
  442.         && itr != start
  443.         && itr != last) continue;
  444.  
  445.       // ignore a name and following ".."
  446.       if (!temp.empty()
  447.         && itr->native().size() == 2
  448.         && (itr->native())[0] == dot
  449.         && (itr->native())[1] == dot) // dot dot
  450.       {
  451.         string_type lf(temp.filename().native());  
  452.         if (lf.size() > 0  
  453.           && (lf.size() != 1
  454.             || (lf[0] != dot
  455.               && lf[0] != separator))
  456.           && (lf.size() != 2
  457.             || (lf[0] != dot
  458.               && lf[1] != dot
  459. #             ifdef BOOST_WINDOWS_API
  460.               && lf[1] != colon
  461. #             endif
  462.                )
  463.              )
  464.           )
  465.         {
  466.           temp.remove_filename();
  467.           //// if not root directory, must also remove "/" if any
  468.           //if (temp.native().size() > 0
  469.           //  && temp.native()[temp.native().size()-1]
  470.           //    == separator)
  471.           //{
  472.           //  string_type::size_type rds(
  473.           //    root_directory_start(temp.native(), temp.native().size()));
  474.           //  if (rds == string_type::npos
  475.           //    || rds != temp.native().size()-1)
  476.           //  {
  477.           //    temp.m_pathname.erase(temp.native().size()-1);
  478.           //  }
  479.           //}
  480.  
  481.           iterator next(itr);
  482.           if (temp.empty() && ++next != stop
  483.             && next == last && *last == detail::dot_path())
  484.           {
  485.             temp /= detail::dot_path();
  486.           }
  487.           continue;
  488.         }
  489.       }
  490.  
  491.       temp /= *itr;
  492.     };
  493.  
  494.     if (temp.empty())
  495.       temp /= detail::dot_path();
  496.     return temp;
  497.   }
  498.  
  499. }  // namespace filesystem
  500. }  // namespace mars_boost
  501.  
  502. //--------------------------------------------------------------------------------------//
  503. //                                                                                      //
  504. //                         class path helpers implementation                            //
  505. //                                                                                      //
  506. //--------------------------------------------------------------------------------------//
  507.  
  508. namespace
  509. {
  510.  
  511.   //  is_root_separator  ---------------------------------------------------------------//
  512.  
  513.   bool is_root_separator(const string_type & str, size_type pos)
  514.     // pos is position of the separator
  515.   {
  516.     BOOST_ASSERT_MSG(!str.empty() && is_separator(str[pos]),
  517.       "precondition violation");
  518.  
  519.     // subsequent logic expects pos to be for leftmost slash of a set
  520.     while (pos > 0 && is_separator(str[pos-1]))
  521.       --pos;
  522.  
  523.     //  "/" [...]
  524.     if (pos == 0)  
  525.       return true;
  526.  
  527. # ifdef BOOST_WINDOWS_API
  528.     //  "c:/" [...]
  529.     if (pos == 2 && is_letter(str[0]) && str[1] == colon)  
  530.       return true;
  531. # endif
  532.  
  533.     //  "//" name "/"
  534.     if (pos < 3 || !is_separator(str[0]) || !is_separator(str[1]))
  535.       return false;
  536.  
  537.     return str.find_first_of(separators, 2) == pos;
  538.   }
  539.  
  540.   //  filename_pos  --------------------------------------------------------------------//
  541.  
  542.   size_type filename_pos(const string_type & str,
  543.                           size_type end_pos) // end_pos is past-the-end position
  544.     // return 0 if str itself is filename (or empty)
  545.   {
  546.     // case: "//"
  547.     if (end_pos == 2
  548.       && is_separator(str[0])
  549.       && is_separator(str[1])) return 0;
  550.  
  551.     // case: ends in "/"
  552.     if (end_pos && is_separator(str[end_pos-1]))
  553.       return end_pos-1;
  554.    
  555.     // set pos to start of last element
  556.     size_type pos(str.find_last_of(separators, end_pos-1));
  557.  
  558. #   ifdef BOOST_WINDOWS_API
  559.     if (pos == string_type::npos && end_pos > 1)
  560.       pos = str.find_last_of(colon, end_pos-2);
  561. #   endif
  562.  
  563.     return (pos == string_type::npos // path itself must be a filename (or empty)
  564.       || (pos == 1 && is_separator(str[0]))) // or net
  565.         ? 0 // so filename is entire string
  566.         : pos + 1; // or starts after delimiter
  567.   }
  568.  
  569.   //  root_directory_start  ------------------------------------------------------------//
  570.  
  571.   size_type root_directory_start(const string_type & path, size_type size)
  572.   // return npos if no root_directory found
  573.   {
  574.  
  575. #   ifdef BOOST_WINDOWS_API
  576.     // case "c:/"
  577.     if (size > 2
  578.       && path[1] == colon
  579.       && is_separator(path[2])) return 2;
  580. #   endif
  581.  
  582.     // case "//"
  583.     if (size == 2
  584.       && is_separator(path[0])
  585.       && is_separator(path[1])) return string_type::npos;
  586.  
  587. #   ifdef BOOST_WINDOWS_API
  588.     // case "\\?\"
  589.     if (size > 4
  590.       && is_separator(path[0])
  591.       && is_separator(path[1])
  592.       && path[2] == questionmark
  593.       && is_separator(path[3]))
  594.     {
  595.       string_type::size_type pos(path.find_first_of(separators, 4));
  596.         return pos < size ? pos : string_type::npos;
  597.     }
  598. #   endif
  599.  
  600.     // case "//net {/}"
  601.     if (size > 3
  602.       && is_separator(path[0])
  603.       && is_separator(path[1])
  604.       && !is_separator(path[2]))
  605.     {
  606.       string_type::size_type pos(path.find_first_of(separators, 2));
  607.       return pos < size ? pos : string_type::npos;
  608.     }
  609.    
  610.     // case "/"
  611.     if (size > 0 && is_separator(path[0])) return 0;
  612.  
  613.     return string_type::npos;
  614.   }
  615.  
  616.   //  first_element --------------------------------------------------------------------//
  617.   //   sets pos and len of first element, excluding extra separators
  618.   //   if src.empty(), sets pos,len, to 0,0.
  619.  
  620.   void first_element(
  621.       const string_type & src,
  622.       size_type & element_pos,
  623.       size_type & element_size,
  624.       size_type size
  625. )
  626.   {
  627.     if (size == string_type::npos) size = src.size();
  628.     element_pos = 0;
  629.     element_size = 0;
  630.     if (src.empty()) return;
  631.  
  632.     string_type::size_type cur(0);
  633.    
  634.     // deal with // [network]
  635.     if (size >= 2 && is_separator(src[0])
  636.       && is_separator(src[1])
  637.       && (size == 2
  638.         || !is_separator(src[2])))
  639.     {
  640.       cur += 2;
  641.       element_size += 2;
  642.     }
  643.  
  644.     // leading (not non-network) separator
  645.     else if (is_separator(src[0]))
  646.     {
  647.       ++element_size;
  648.       // bypass extra leading separators
  649.       while (cur+1 < size
  650.         && is_separator(src[cur+1]))
  651.       {
  652.         ++cur;
  653.         ++element_pos;
  654.       }
  655.       return;
  656.     }
  657.  
  658.     // at this point, we have either a plain name, a network name,
  659.     // or (on Windows only) a device name
  660.  
  661.     // find the end
  662.     while (cur < size
  663. #     ifdef BOOST_WINDOWS_API
  664.       && src[cur] != colon
  665. #     endif
  666.       && !is_separator(src[cur]))
  667.     {
  668.       ++cur;
  669.       ++element_size;
  670.     }
  671.  
  672. #   ifdef BOOST_WINDOWS_API
  673.     if (cur == size) return;
  674.     // include device delimiter
  675.     if (src[cur] == colon)
  676.       { ++element_size; }
  677. #   endif
  678.  
  679.     return;
  680.   }
  681.  
  682. }  // unnamed namespace
  683.  
  684.  
  685. namespace mars_boost {} namespace boost = mars_boost; namespace mars_boost
  686. {
  687. namespace filesystem
  688. {
  689.   namespace detail
  690.   {
  691.     BOOST_FILESYSTEM_DECL
  692.       int lex_compare(path::iterator first1, path::iterator last1,
  693.         path::iterator first2, path::iterator last2)
  694.     {
  695.       for (; first1 != last1 && first2 != last2;)
  696.       {
  697.         if (first1->native() < first2->native()) return -1;
  698.         if (first2->native() < first1->native()) return 1;
  699.         BOOST_ASSERT(first2->native() == first1->native());
  700.         ++first1;
  701.         ++first2;
  702.       }
  703.       if (first1 == last1 && first2 == last2)
  704.         return 0;
  705.       return first1 == last1 ? -1 : 1;
  706.     }
  707.  
  708.     BOOST_FILESYSTEM_DECL
  709.     const path&  dot_path()
  710.     {
  711. #   ifdef BOOST_WINDOWS_API
  712.       static const fs::path dot_pth(L".");
  713. #   else
  714.       static const fs::path dot_pth(".");
  715. #   endif
  716.       return dot_pth;
  717.     }
  718.  
  719.     BOOST_FILESYSTEM_DECL
  720.     const path&  dot_dot_path()
  721.     {
  722. #   ifdef BOOST_WINDOWS_API
  723.       static const fs::path dot_dot(L"..");
  724. #   else
  725.       static const fs::path dot_dot("..");
  726. #   endif
  727.       return dot_dot;
  728.     }
  729.   }
  730.  
  731. //--------------------------------------------------------------------------------------//
  732. //                                                                                      //
  733. //                        class path::iterator implementation                           //
  734. //                                                                                      //
  735. //--------------------------------------------------------------------------------------//
  736.  
  737.   path::iterator path::begin() const
  738.   {
  739.     iterator itr;
  740.     itr.m_path_ptr = this;
  741.     size_type element_size;
  742.     first_element(m_pathname, itr.m_pos, element_size);
  743.     itr.m_element = m_pathname.substr(itr.m_pos, element_size);
  744.     if (itr.m_element.m_pathname == preferred_separator_string)
  745.       itr.m_element.m_pathname = separator_string;  // needed for Windows, harmless on POSIX
  746.     return itr;
  747.   }
  748.  
  749.   path::iterator path::end() const
  750.   {
  751.     iterator itr;
  752.     itr.m_path_ptr = this;
  753.     itr.m_pos = m_pathname.size();
  754.     return itr;
  755.   }
  756.  
  757.   void path::m_path_iterator_increment(path::iterator & it)
  758.   {
  759.     BOOST_ASSERT_MSG(it.m_pos < it.m_path_ptr->m_pathname.size(),
  760.       "path::basic_iterator increment past end()");
  761.  
  762.     // increment to position past current element; if current element is implicit dot,
  763.     // this will cause it.m_pos to represent the end iterator
  764.     it.m_pos += it.m_element.m_pathname.size();
  765.  
  766.     // if the end is reached, we are done
  767.     if (it.m_pos == it.m_path_ptr->m_pathname.size())
  768.     {
  769.       it.m_element.clear();  // aids debugging, may release unneeded memory
  770.       return;
  771.     }
  772.  
  773.     // both POSIX and Windows treat paths that begin with exactly two separators specially
  774.     bool was_net(it.m_element.m_pathname.size() > 2
  775.       && is_separator(it.m_element.m_pathname[0])
  776.       && is_separator(it.m_element.m_pathname[1])
  777.       && !is_separator(it.m_element.m_pathname[2]));
  778.  
  779.     // process separator (Windows drive spec is only case not a separator)
  780.     if (is_separator(it.m_path_ptr->m_pathname[it.m_pos]))
  781.     {
  782.       // detect root directory
  783.       if (was_net
  784. #       ifdef BOOST_WINDOWS_API
  785.         // case "c:/"
  786.         || it.m_element.m_pathname[it.m_element.m_pathname.size()-1] == colon
  787. #       endif
  788.          )
  789.       {
  790.         it.m_element.m_pathname = separator;  // generic format; see docs
  791.         return;
  792.       }
  793.  
  794.       // skip separators until it.m_pos points to the start of the next element
  795.       while (it.m_pos != it.m_path_ptr->m_pathname.size()
  796.         && is_separator(it.m_path_ptr->m_pathname[it.m_pos]))
  797.         { ++it.m_pos; }
  798.  
  799.       // detect trailing separator, and treat it as ".", per POSIX spec
  800.       if (it.m_pos == it.m_path_ptr->m_pathname.size()
  801.         && !is_root_separator(it.m_path_ptr->m_pathname, it.m_pos-1))
  802.       {
  803.         --it.m_pos;
  804.         it.m_element = detail::dot_path();
  805.         return;
  806.       }
  807.     }
  808.  
  809.     // get m_element
  810.     size_type end_pos(it.m_path_ptr->m_pathname.find_first_of(separators, it.m_pos));
  811.     if (end_pos == string_type::npos)
  812.       end_pos = it.m_path_ptr->m_pathname.size();
  813.     it.m_element = it.m_path_ptr->m_pathname.substr(it.m_pos, end_pos - it.m_pos);
  814.   }
  815.  
  816.   void path::m_path_iterator_decrement(path::iterator & it)
  817.   {
  818.     BOOST_ASSERT_MSG(it.m_pos, "path::iterator decrement past begin()");
  819.  
  820.     size_type end_pos(it.m_pos);
  821.  
  822.     // if at end and there was a trailing non-root '/', return "."
  823.     if (it.m_pos == it.m_path_ptr->m_pathname.size()
  824.       && it.m_path_ptr->m_pathname.size() > 1
  825.       && is_separator(it.m_path_ptr->m_pathname[it.m_pos-1])
  826.       && !is_root_separator(it.m_path_ptr->m_pathname, it.m_pos-1)
  827.        )
  828.     {
  829.       --it.m_pos;
  830.       it.m_element = detail::dot_path();
  831.       return;
  832.     }
  833.  
  834.     size_type root_dir_pos(root_directory_start(it.m_path_ptr->m_pathname, end_pos));
  835.  
  836.     // skip separators unless root directory
  837.     for (
  838.       ;
  839.       end_pos > 0
  840.       && (end_pos-1) != root_dir_pos
  841.       && is_separator(it.m_path_ptr->m_pathname[end_pos-1])
  842.       ;
  843.       --end_pos) {}
  844.  
  845.     it.m_pos = filename_pos(it.m_path_ptr->m_pathname, end_pos);
  846.     it.m_element = it.m_path_ptr->m_pathname.substr(it.m_pos, end_pos - it.m_pos);
  847.     if (it.m_element.m_pathname == preferred_separator_string) // needed for Windows, harmless on POSIX
  848.       it.m_element.m_pathname = separator_string;    // generic format; see docs
  849.   }
  850.  
  851. }  // namespace filesystem
  852. }  // namespace mars_boost
  853.  
  854. namespace
  855. {
  856.  
  857.   //------------------------------------------------------------------------------------//
  858.   //                                locale helpers                                      //
  859.   //------------------------------------------------------------------------------------//
  860.  
  861.   //  Prior versions of these locale and codecvt implementations tried to take advantage
  862.   //  of static initialization where possible, kept a local copy of the current codecvt
  863.   //  facet (to avoid codecvt() having to call use_facet()), and was not multi-threading
  864.   //  safe (again for efficiency).
  865.   //
  866.   //  This was error prone, and required different implementation techniques depending
  867.   //  on the compiler and also whether static or dynamic linking was used. Furthermore,
  868.   //  users could not easily provide their multi-threading safe wrappers because the
  869.   //  path interface requires the implementation itself to call codecvt() to obtain the
  870.   //  default facet, and the initialization of the static within path_locale() could race.
  871.   //
  872.   //  The code below is portable to all platforms, is much simpler, and hopefully will be
  873.   //  much more robust. Timing tests (on Windows, using a Visual C++ release build)
  874.   //  indicated the current code is roughly 9% slower than the previous code, and that
  875.   //  seems a small price to pay for better code that is easier to use.
  876.  
  877.   std::locale default_locale()
  878.   {
  879. # if defined(BOOST_WINDOWS_API)
  880.     std::locale global_loc = std::locale();
  881.     return std::locale(global_loc, new windows_file_codecvt);
  882. # elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) \
  883.   || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__HAIKU__)
  884.     // "All BSD system functions expect their string parameters to be in UTF-8 encoding
  885.     // and nothing else." See
  886.     // http://developer.apple.com/mac/library/documentation/MacOSX/Conceptual/BPInternational/Articles/FileEncodings.html
  887.     //
  888.     // "The kernel will reject any filename that is not a valid UTF-8 string, and it will
  889.     // even be normalized (to Unicode NFD) before stored on disk, at least when using HFS.
  890.     // The right way to deal with it would be to always convert the filename to UTF-8
  891.     // before trying to open/create a file." See
  892.     // http://lists.apple.com/archives/unix-porting/2007/Sep/msg00023.html
  893.     //
  894.     // "How a file name looks at the API level depends on the API. Current Carbon APIs
  895.     // handle file names as an array of UTF-16 characters; POSIX ones handle them as an
  896.     // array of UTF-8, which is why UTF-8 works well in Terminal. How it's stored on disk
  897.     // depends on the disk format; HFS+ uses UTF-16, but that's not important in most
  898.     // cases." See
  899.     // http://lists.apple.com/archives/applescript-users/2002/Sep/msg00319.html
  900.     //
  901.     // Many thanks to Peter Dimov for digging out the above references!
  902.  
  903.     std::locale global_loc = std::locale();
  904.     return std::locale(global_loc, new mars_boost::filesystem::detail::utf8_codecvt_facet);
  905. # else  // Other POSIX
  906.     // ISO C calls std::locale("") "the locale-specific native environment", and this
  907.     // locale is the default for many POSIX-based operating systems such as Linux.
  908.     return std::locale("");
  909. # endif
  910.   }
  911.  
  912.   std::locale& path_locale()
  913.   // std::locale("") construction, needed on non-Apple POSIX systems, can throw
  914.   // (if environmental variables LC_MESSAGES or LANG are wrong, for example), so
  915.   // path_locale() provides lazy initialization via a local static to ensure that any
  916.   // exceptions occur after main() starts and so can be caught. Furthermore,
  917.   // path_locale() is only called if path::codecvt() or path::imbue() are themselves
  918.   // actually called, ensuring that an exception will only be thrown if std::locale("")
  919.   // is really needed.
  920.   {
  921.     // [locale] paragraph 6: Once a facet reference is obtained from a locale object by
  922.     // calling use_facet<>, that reference remains usable, and the results from member
  923.     // functions of it may be cached and re-used, as long as some locale object refers
  924.     // to that facet.
  925.     static std::locale loc(default_locale());
  926. #ifdef BOOST_FILESYSTEM_DEBUG
  927.     std::cout << "***** path_locale() called" << std::endl;
  928. #endif
  929.     return loc;
  930.   }
  931. }  // unnamed namespace
  932.  
  933. //--------------------------------------------------------------------------------------//
  934. //              path::codecvt() and path::imbue() implementation                        //
  935. //--------------------------------------------------------------------------------------//
  936.  
  937. namespace mars_boost {} namespace boost = mars_boost; namespace mars_boost
  938. {
  939. namespace filesystem
  940. {
  941.   // See comments above
  942.  
  943.   const path::codecvt_type& path::codecvt()
  944.   {
  945. #ifdef BOOST_FILESYSTEM_DEBUG
  946.     std::cout << "***** path::codecvt() called" << std::endl;
  947. #endif
  948.     BOOST_ASSERT_MSG(&path_locale(), "mars_boost::filesystem::path locale initialization error");
  949.  
  950.     return std::use_facet<std::codecvt<wchar_t, char, std::mbstate_t> >(path_locale());
  951.   }
  952.  
  953.   std::locale path::imbue(const std::locale& loc)
  954.   {
  955. #ifdef BOOST_FILESYSTEM_DEBUG
  956.     std::cout << "***** path::imbue() called" << std::endl;
  957. #endif
  958.     std::locale temp(path_locale());
  959.     path_locale() = loc;
  960.     return temp;
  961.   }
  962.  
  963. }  // namespace filesystem
  964. }  // namespace mars_boost
  965.  
downloadpath.cpp Source code - Download mars Source code
Related Source Codes/Software:
Hero - Elegant transition library for iOS & tvOS 2017-06-09
deep-photo-styletransfer - Code and data for paper "Deep Photo Style Transfer... 2017-06-09
mastodon - A GNU Social-compatible microblogging server ... 2017-06-09
plyr - A simple HTML5, YouTube and Vimeo player ... 2017-06-08
prepack - Prepack is a partial evaluator for JavaScript. Pre... 2017-06-08
Public-APIs - 2017-06-09
lottie-ios - An iOS library to natively render After Effects ve... 2017-06-09
Awesome-Hacking - A collection of various awesome lists for hackers,... 2017-06-09
algorithms - Minimal examples of data structures and algorithms... 2017-06-10
lectures - Oxford Deep NLP 2017 course 2017-06-10
CRYENGINE - CRYENGINE is a powerful real-time game development... 2017-06-11
postal - 2017-06-11
reactide - Reactide is the first dedicated IDE for React web ... 2017-06-11
rkt - rkt is a pod-native container engine for Linux. It... 2017-06-11
uWebSockets - Tiny WebSockets https://for... 2017-06-11
realworld - TodoMVC for the RealWorld - Exemplary fullstack Me... 2017-06-11
goreplay - GoReplay is an open-source tool for capturing and ... 2017-06-10
pyenv - Simple Python version management 2017-06-10
redux-saga - An alternative side effect model for Redux apps ... 2017-06-10
angular-starter - 2017-06-10

 Back to top