diff options
Diffstat (limited to 'boost/filesystem/path.hpp')
-rw-r--r-- | boost/filesystem/path.hpp | 208 |
1 files changed, 160 insertions, 48 deletions
diff --git a/boost/filesystem/path.hpp b/boost/filesystem/path.hpp index 2dd1b00ea5..37f39d0a3b 100644 --- a/boost/filesystem/path.hpp +++ b/boost/filesystem/path.hpp @@ -121,9 +121,10 @@ namespace filesystem // multi-byte character strings which may have embedded nulls. Embedded null // support is required for some Asian languages on Windows. - // [defaults] "const codecvt_type& cvt=codecvt()" default arguments are not used - // because some compilers, such as Microsoft prior to VC++ 10, do not handle defaults - // correctly in templates. + // "const codecvt_type& cvt=codecvt()" default arguments are not used because this + // limits the impact of locale("") initialization failures on POSIX systems to programs + // that actually depend on locale(""). It further ensures that exceptions thrown + // as a result of such failues occur after main() has started, so can be caught. // ----- constructors ----- @@ -136,23 +137,16 @@ namespace filesystem typename boost::enable_if<path_traits::is_pathable< typename boost::decay<Source>::type> >::type* =0) { - path_traits::dispatch(source, m_pathname, codecvt()); + path_traits::dispatch(source, m_pathname); } - // Overloads for the operating system API's native character type. Rationale: - // - Avoids use of codecvt() for native value_type strings. This limits the - // impact of locale("") initialization failures on POSIX systems to programs - // that actually depend on locale(""). It further ensures that exceptions thrown - // as a result of such failues occur after main() has started, so can be caught. - // This is a partial resolution of tickets 4688, 5100, and 5289. - // - A slight optimization for a common use case, particularly on POSIX since - // value_type is char and that is the most common useage. path(const value_type* s) : m_pathname(s) {} - path(const std::basic_string<value_type>& s) : m_pathname(s) {} + path(value_type* s) : m_pathname(s) {} + path(const string_type& s) : m_pathname(s) {} + path(string_type& s) : m_pathname(s) {} template <class Source> path(Source const& source, const codecvt_type& cvt) - // see [defaults] note above explaining why codecvt() default arguments are not used { path_traits::dispatch(source, m_pathname, cvt); } @@ -162,9 +156,10 @@ namespace filesystem { if (begin != end) { + // convert requires contiguous string, so copy std::basic_string<typename std::iterator_traits<InputIterator>::value_type> s(begin, end); - path_traits::convert(s.c_str(), s.c_str()+s.size(), m_pathname, codecvt()); + path_traits::convert(s.c_str(), s.c_str()+s.size(), m_pathname); } } @@ -173,6 +168,7 @@ namespace filesystem { if (begin != end) { + // convert requires contiguous string, so copy std::basic_string<typename std::iterator_traits<InputIterator>::value_type> s(begin, end); path_traits::convert(s.c_str(), s.c_str()+s.size(), m_pathname, cvt); @@ -187,28 +183,27 @@ namespace filesystem return *this; } - path& operator=(const value_type* ptr) // required in case ptr overlaps *this - { - m_pathname = ptr; - return *this; - } - template <class Source> typename boost::enable_if<path_traits::is_pathable< typename boost::decay<Source>::type>, path&>::type operator=(Source const& source) { m_pathname.clear(); - path_traits::dispatch(source, m_pathname, codecvt()); + path_traits::dispatch(source, m_pathname); return *this; } - path& assign(const value_type* ptr, const codecvt_type&) // required in case ptr overlaps *this - { - m_pathname = ptr; - return *this; - } + // value_type overloads + path& operator=(const value_type* ptr) // required in case ptr overlaps *this + {m_pathname = ptr; return *this;} + path& operator=(value_type* ptr) // required in case ptr overlaps *this + {m_pathname = ptr; return *this;} + path& operator=(const string_type& s) {m_pathname = s; return *this;} + path& operator=(string_type& s) {m_pathname = s; return *this;} + + path& assign(const value_type* ptr, const codecvt_type&) // required in case ptr overlaps *this + {m_pathname = ptr; return *this;} template <class Source> path& assign(Source const& source, const codecvt_type& cvt) { @@ -220,7 +215,14 @@ namespace filesystem template <class InputIterator> path& assign(InputIterator begin, InputIterator end) { - return assign(begin, end, codecvt()); + m_pathname.clear(); + if (begin != end) + { + std::basic_string<typename std::iterator_traits<InputIterator>::value_type> + s(begin, end); + path_traits::convert(s.c_str(), s.c_str()+s.size(), m_pathname); + } + return *this; } template <class InputIterator> @@ -238,19 +240,22 @@ namespace filesystem // ----- concatenation ----- - path& operator+=(const path& p) {m_pathname += p.m_pathname; return *this;} - path& operator+=(const string_type& s) {m_pathname += s; return *this;} - path& operator+=(const value_type* ptr) {m_pathname += ptr; return *this;} - path& operator+=(value_type c) {m_pathname += c; return *this;} - template <class Source> typename boost::enable_if<path_traits::is_pathable< typename boost::decay<Source>::type>, path&>::type operator+=(Source const& source) { - return concat(source, codecvt()); + return concat(source); } + // value_type overloads. Same rationale as for constructors above + path& operator+=(const path& p) { m_pathname += p.m_pathname; return *this; } + path& operator+=(const value_type* ptr) { m_pathname += ptr; return *this; } + path& operator+=(value_type* ptr) { m_pathname += ptr; return *this; } + path& operator+=(const string_type& s) { m_pathname += s; return *this; } + path& operator+=(string_type& s) { m_pathname += s; return *this; } + path& operator+=(value_type c) { m_pathname += c; return *this; } + template <class CharT> typename boost::enable_if<is_integral<CharT>, path&>::type operator+=(CharT c) @@ -258,7 +263,14 @@ namespace filesystem CharT tmp[2]; tmp[0] = c; tmp[1] = 0; - return concat(tmp, codecvt()); + return concat(tmp); + } + + template <class Source> + path& concat(Source const& source) + { + path_traits::dispatch(source, m_pathname); + return *this; } template <class Source> @@ -271,7 +283,12 @@ namespace filesystem template <class InputIterator> path& concat(InputIterator begin, InputIterator end) { - return concat(begin, end, codecvt()); + if (begin == end) + return *this; + std::basic_string<typename std::iterator_traits<InputIterator>::value_type> + s(begin, end); + path_traits::convert(s.c_str(), s.c_str()+s.size(), m_pathname); + return *this; } template <class InputIterator> @@ -292,14 +309,26 @@ namespace filesystem path& operator/=(const path& p); - path& operator/=(const value_type* ptr); - template <class Source> typename boost::enable_if<path_traits::is_pathable< typename boost::decay<Source>::type>, path&>::type operator/=(Source const& source) { - return append(source, codecvt()); + return append(source); + } + + path& operator/=(const value_type* ptr); + path& operator/=(value_type* ptr) + { + return this->operator/=(const_cast<const value_type*>(ptr)); + } + path& operator/=(const string_type& s) { return this->operator/=(path(s)); } + path& operator/=(string_type& s) { return this->operator/=(path(s)); } + + path& append(const value_type* ptr) // required in case ptr overlaps *this + { + this->operator/=(ptr); + return *this; } path& append(const value_type* ptr, const codecvt_type&) // required in case ptr overlaps *this @@ -309,13 +338,13 @@ namespace filesystem } template <class Source> + path& append(Source const& source); + + template <class Source> path& append(Source const& source, const codecvt_type& cvt); template <class InputIterator> - path& append(InputIterator begin, InputIterator end) - { - return append(begin, end, codecvt()); - } + path& append(InputIterator begin, InputIterator end); template <class InputIterator> path& append(InputIterator begin, InputIterator end, const codecvt_type& cvt); @@ -364,7 +393,14 @@ namespace filesystem String string(const codecvt_type& cvt) const; # ifdef BOOST_WINDOWS_API - const std::string string() const { return string(codecvt()); } + const std::string string() const + { + std::string tmp; + if (!m_pathname.empty()) + path_traits::convert(&*m_pathname.begin(), &*m_pathname.begin()+m_pathname.size(), + tmp); + return tmp; + } const std::string string(const codecvt_type& cvt) const { std::string tmp; @@ -383,7 +419,14 @@ namespace filesystem const std::string& string() const { return m_pathname; } const std::string& string(const codecvt_type&) const { return m_pathname; } - const std::wstring wstring() const { return wstring(codecvt()); } + const std::wstring wstring() const + { + std::wstring tmp; + if (!m_pathname.empty()) + path_traits::convert(&*m_pathname.begin(), &*m_pathname.begin()+m_pathname.size(), + tmp); + return tmp; + } const std::wstring wstring(const codecvt_type& cvt) const { std::wstring tmp; @@ -404,7 +447,7 @@ namespace filesystem String generic_string(const codecvt_type& cvt) const; # ifdef BOOST_WINDOWS_API - const std::string generic_string() const { return generic_string(codecvt()); } + const std::string generic_string() const; const std::string generic_string(const codecvt_type& cvt) const; const std::wstring generic_wstring() const; const std::wstring generic_wstring(const codecvt_type&) const { return generic_wstring(); }; @@ -413,7 +456,7 @@ namespace filesystem // On POSIX-like systems, the generic format is the same as the native format const std::string& generic_string() const { return m_pathname; } const std::string& generic_string(const codecvt_type&) const { return m_pathname; } - const std::wstring generic_wstring() const { return wstring(codecvt()); } + const std::wstring generic_wstring() const { return wstring(); } const std::wstring generic_wstring(const codecvt_type& cvt) const { return wstring(cvt); } # endif @@ -556,6 +599,10 @@ namespace filesystem BOOST_FILESYSTEM_DECL int lex_compare(path::iterator first1, path::iterator last1, path::iterator first2, path::iterator last2); + BOOST_FILESYSTEM_DECL + const path& dot_path(); + BOOST_FILESYSTEM_DECL + const path& dot_dot_path(); } # ifndef BOOST_FILESYSTEM_NO_DEPRECATED @@ -686,8 +733,22 @@ namespace filesystem //--------------------------------------------------------------------------------------// template <class InputIterator> + path& path::append(InputIterator begin, InputIterator end) + { + if (begin == end) + return *this; + string_type::size_type sep_pos(m_append_separator_if_needed()); + std::basic_string<typename std::iterator_traits<InputIterator>::value_type> + s(begin, end); + path_traits::convert(s.c_str(), s.c_str()+s.size(), m_pathname); + if (sep_pos) + m_erase_redundant_separator(sep_pos); + return *this; + } + + template <class InputIterator> path& path::append(InputIterator begin, InputIterator end, const codecvt_type& cvt) - { + { if (begin == end) return *this; string_type::size_type sep_pos(m_append_separator_if_needed()); @@ -700,6 +761,18 @@ namespace filesystem } template <class Source> + path& path::append(Source const& source) + { + if (path_traits::empty(source)) + return *this; + string_type::size_type sep_pos(m_append_separator_if_needed()); + path_traits::dispatch(source, m_pathname); + if (sep_pos) + m_erase_redundant_separator(sep_pos); + return *this; + } + + template <class Source> path& path::append(Source const& source, const codecvt_type& cvt) { if (path_traits::empty(source)) @@ -747,7 +820,46 @@ namespace filesystem std::wstring path::generic_string<std::wstring>(const codecvt_type& cvt) const { return generic_wstring(cvt); } + //--------------------------------------------------------------------------------------// + // path_traits convert function implementations // + // requiring path::codecvt() be visable // + //--------------------------------------------------------------------------------------// + +namespace path_traits +{ // without codecvt + inline + void convert(const char* from, + const char* from_end, // 0 for null terminated MBCS + std::wstring & to) + { + convert(from, from_end, to, path::codecvt()); + } + + inline + void convert(const wchar_t* from, + const wchar_t* from_end, // 0 for null terminated MBCS + std::string & to) + { + convert(from, from_end, to, path::codecvt()); + } + + inline + void convert(const char* from, + std::wstring & to) + { + BOOST_ASSERT(from); + convert(from, 0, to, path::codecvt()); + } + + inline + void convert(const wchar_t* from, + std::string & to) + { + BOOST_ASSERT(from); + convert(from, 0, to, path::codecvt()); + } +} // namespace path_traits } // namespace filesystem } // namespace boost |