summaryrefslogtreecommitdiff
path: root/boost/filesystem
diff options
context:
space:
mode:
authorChanho Park <chanho61.park@samsung.com>2014-12-11 09:55:56 (GMT)
committerChanho Park <chanho61.park@samsung.com>2014-12-11 09:55:56 (GMT)
commit08c1e93fa36a49f49325a07fe91ff92c964c2b6c (patch)
tree7a7053ceb8874b28ec4b868d4c49b500008a102e /boost/filesystem
parentbb4dd8289b351fae6b55e303f189127a394a1edd (diff)
downloadboost-08c1e93fa36a49f49325a07fe91ff92c964c2b6c.zip
boost-08c1e93fa36a49f49325a07fe91ff92c964c2b6c.tar.gz
boost-08c1e93fa36a49f49325a07fe91ff92c964c2b6c.tar.bz2
Imported Upstream version 1.57.0upstream/1.57.0
Diffstat (limited to 'boost/filesystem')
-rw-r--r--boost/filesystem/operations.hpp409
-rw-r--r--boost/filesystem/path.hpp208
-rw-r--r--boost/filesystem/path_traits.hpp201
3 files changed, 588 insertions, 230 deletions
diff --git a/boost/filesystem/operations.hpp b/boost/filesystem/operations.hpp
index dc01b7d..d677084 100644
--- a/boost/filesystem/operations.hpp
+++ b/boost/filesystem/operations.hpp
@@ -33,8 +33,9 @@
#include <boost/type_traits/is_same.hpp>
#include <boost/iterator.hpp>
#include <boost/cstdint.hpp>
+#include <boost/range/mutable_iterator.hpp>
+#include <boost/range/const_iterator.hpp>
#include <boost/assert.hpp>
-
#include <string>
#include <utility> // for pair
#include <ctime>
@@ -54,6 +55,116 @@ namespace boost
namespace filesystem
{
+ //--------------------------------------------------------------------------------------//
+ // //
+ // class filesystem_error //
+ // //
+ //--------------------------------------------------------------------------------------//
+
+ class BOOST_SYMBOL_VISIBLE filesystem_error : public system::system_error
+ {
+ // see http://www.boost.org/more/error_handling.html for design rationale
+
+ // all functions are inline to avoid issues with crossing dll boundaries
+
+ // functions previously throw() are now BOOST_NOEXCEPT_OR_NOTHROW
+ // functions previously without throw() are now BOOST_NOEXCEPT
+
+ public:
+ // compiler generates copy constructor and copy assignment
+
+ filesystem_error(
+ const std::string & what_arg, system::error_code ec) BOOST_NOEXCEPT
+ : system::system_error(ec, what_arg)
+ {
+ try
+ {
+ m_imp_ptr.reset(new m_imp);
+ }
+ catch (...) { m_imp_ptr.reset(); }
+ }
+
+ filesystem_error(
+ const std::string & what_arg, const path& path1_arg,
+ system::error_code ec) BOOST_NOEXCEPT
+ : system::system_error(ec, what_arg)
+ {
+ try
+ {
+ m_imp_ptr.reset(new m_imp);
+ m_imp_ptr->m_path1 = path1_arg;
+ }
+ catch (...) { m_imp_ptr.reset(); }
+ }
+
+ filesystem_error(
+ const std::string & what_arg, const path& path1_arg,
+ const path& path2_arg, system::error_code ec) BOOST_NOEXCEPT
+ : system::system_error(ec, what_arg)
+ {
+ try
+ {
+ m_imp_ptr.reset(new m_imp);
+ m_imp_ptr->m_path1 = path1_arg;
+ m_imp_ptr->m_path2 = path2_arg;
+ }
+ catch (...) { m_imp_ptr.reset(); }
+ }
+
+ ~filesystem_error() BOOST_NOEXCEPT_OR_NOTHROW{}
+
+ const path& path1() const BOOST_NOEXCEPT
+ {
+ static const path empty_path;
+ return m_imp_ptr.get() ? m_imp_ptr->m_path1 : empty_path;
+ }
+ const path& path2() const BOOST_NOEXCEPT
+ {
+ static const path empty_path;
+ return m_imp_ptr.get() ? m_imp_ptr->m_path2 : empty_path;
+ }
+
+ const char* what() const BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ if (!m_imp_ptr.get())
+ return system::system_error::what();
+
+ try
+ {
+ if (m_imp_ptr->m_what.empty())
+ {
+ m_imp_ptr->m_what = system::system_error::what();
+ if (!m_imp_ptr->m_path1.empty())
+ {
+ m_imp_ptr->m_what += ": \"";
+ m_imp_ptr->m_what += m_imp_ptr->m_path1.string();
+ m_imp_ptr->m_what += "\"";
+ }
+ if (!m_imp_ptr->m_path2.empty())
+ {
+ m_imp_ptr->m_what += ", \"";
+ m_imp_ptr->m_what += m_imp_ptr->m_path2.string();
+ m_imp_ptr->m_what += "\"";
+ }
+ }
+ return m_imp_ptr->m_what.c_str();
+ }
+ catch (...)
+ {
+ return system::system_error::what();
+ }
+ }
+
+ private:
+ struct m_imp
+ {
+ path m_path1; // may be empty()
+ path m_path2; // may be empty()
+ std::string m_what; // not built until needed
+ };
+ boost::shared_ptr<m_imp> m_imp_ptr;
+ };
+
//--------------------------------------------------------------------------------------//
// file_type //
//--------------------------------------------------------------------------------------//
@@ -108,7 +219,7 @@ namespace boost
others_exe = 01, // S_IXOTH, Execute/search permission, others
others_all = 07, // S_IRWXO, Read, write, execute/search by others
- all_all = owner_all|group_all|others_all, // 0777
+ all_all = 0777, // owner_all|group_all|others_all
// other POSIX bits
@@ -121,7 +232,7 @@ namespace boost
// (SVID-v4.2) On directories: restricted deletion flag
// Also see http://en.wikipedia.org/wiki/Sticky_bit
- perms_mask = all_all|set_uid_on_exe|set_gid_on_exe|sticky_bit, // 07777
+ perms_mask = 07777, // all_all|set_uid_on_exe|set_gid_on_exe|sticky_bit
perms_not_known = 0xFFFF, // present when directory_entry cache not loaded
@@ -191,7 +302,7 @@ namespace boost
};
BOOST_SCOPED_ENUM_START(copy_option)
- {none, fail_if_exists = none, overwrite_if_exists};
+ {none=0, fail_if_exists = none, overwrite_if_exists};
BOOST_SCOPED_ENUM_END
//--------------------------------------------------------------------------------------//
@@ -200,6 +311,11 @@ namespace boost
namespace detail
{
+ // We cannot pass a BOOST_SCOPED_ENUM to a compled function because it will result
+ // in an undefined reference if the library is compled with -std=c++0x but the use
+ // is compiled in C++03 mode, or visa versa. See tickets 6124, 6779, 10038.
+ enum copy_option {none=0, fail_if_exists = none, overwrite_if_exists};
+
BOOST_FILESYSTEM_DECL
file_status status(const path&p, system::error_code* ec=0);
BOOST_FILESYSTEM_DECL
@@ -215,9 +331,8 @@ namespace boost
BOOST_FILESYSTEM_DECL
void copy_directory(const path& from, const path& to, system::error_code* ec=0);
BOOST_FILESYSTEM_DECL
- void copy_file(const path& from, const path& to,
- BOOST_SCOPED_ENUM(copy_option) option, // See ticket #2925
- system::error_code* ec=0);
+ void copy_file(const path& from, const path& to, // See ticket #2925
+ detail::copy_option option, system::error_code* ec=0);
BOOST_FILESYSTEM_DECL
void copy_symlink(const path& existing_symlink, const path& new_symlink, system::error_code* ec=0);
BOOST_FILESYSTEM_DECL
@@ -378,19 +493,28 @@ namespace boost
inline
void copy_file(const path& from, const path& to, // See ticket #2925
BOOST_SCOPED_ENUM(copy_option) option)
- {detail::copy_file(from, to, option);}
+ {
+ detail::copy_file(from, to, static_cast<detail::copy_option>(option));
+ }
inline
void copy_file(const path& from, const path& to)
- {detail::copy_file(from, to, copy_option::fail_if_exists);}
+ {
+ detail::copy_file(from, to, detail::fail_if_exists);
+ }
inline
void copy_file(const path& from, const path& to, // See ticket #2925
BOOST_SCOPED_ENUM(copy_option) option, system::error_code& ec)
- {detail::copy_file(from, to, option, &ec);}
+ {
+ detail::copy_file(from, to, static_cast<detail::copy_option>(option), &ec);
+ }
inline
void copy_file(const path& from, const path& to, system::error_code& ec)
- {detail::copy_file(from, to, copy_option::fail_if_exists, &ec);}
+ {
+ detail::copy_file(from, to, detail::fail_if_exists, &ec);
+ }
inline
- void copy_symlink(const path& existing_symlink, const path& new_symlink) {detail::copy_symlink(existing_symlink, new_symlink);}
+ void copy_symlink(const path& existing_symlink,
+ const path& new_symlink) {detail::copy_symlink(existing_symlink, new_symlink);}
inline
void copy_symlink(const path& existing_symlink, const path& new_symlink, system::error_code& ec)
@@ -721,6 +845,37 @@ namespace detail
{ return m_imp == rhs.m_imp; }
};
+ // enable C++11 range-base for statement use ---------------------------------------//
+
+ // begin() and end() are only used by a range-based for statement in the context of
+ // auto - thus the top-level const is stripped - so returning const is harmless and
+ // emphasizes begin() is just a pass through.
+ inline
+ const directory_iterator& begin(const directory_iterator& iter) {return iter;}
+ inline
+ directory_iterator end(const directory_iterator&) {return directory_iterator();}
+
+ // enable BOOST_FOREACH ------------------------------------------------------------//
+
+ inline
+ directory_iterator& range_begin(directory_iterator& iter) {return iter;}
+ inline
+ directory_iterator range_begin(const directory_iterator& iter) {return iter;}
+ inline
+ directory_iterator range_end(const directory_iterator&) {return directory_iterator();}
+ } // namespace filesystem
+
+ // namespace boost template specializations
+ template<>
+ struct range_mutable_iterator<boost::filesystem::directory_iterator>
+ { typedef boost::filesystem::directory_iterator type; };
+ template<>
+ struct range_const_iterator <boost::filesystem::directory_iterator>
+ { typedef boost::filesystem::directory_iterator type; };
+
+namespace filesystem
+{
+
//--------------------------------------------------------------------------------------//
// //
// recursive_directory_iterator helpers //
@@ -751,6 +906,8 @@ namespace detail
void increment(system::error_code* ec); // ec == 0 means throw on error
+ bool push_directory(system::error_code& ec) BOOST_NOEXCEPT;
+
void pop();
};
@@ -760,9 +917,14 @@ namespace detail
// clients of struct 'boost::filesystem::detail::recur_dir_itr_imp'
inline
- void recur_dir_itr_imp::increment(system::error_code* ec)
- // ec == 0 means throw on error
+ bool recur_dir_itr_imp::push_directory(system::error_code& ec) BOOST_NOEXCEPT
+ // Returns: true if push occurs, otherwise false. Always returns false on error.
{
+ ec.clear();
+
+ // Discover if the iterator is for a directory that needs to be recursed into,
+ // taking symlinks and options into account.
+
if ((m_options & symlink_option::_detail_no_push) == symlink_option::_detail_no_push)
m_options &= ~symlink_option::_detail_no_push;
@@ -775,40 +937,78 @@ namespace detail
// && is_directory(m_stack.top()->status())) ...
// The predicate code has since been rewritten to pass error_code arguments,
// per ticket #5653.
- bool or_pred = (m_options & symlink_option::recurse) == symlink_option::recurse
- || (ec == 0 ? !is_symlink(m_stack.top()->symlink_status())
- : !is_symlink(m_stack.top()->symlink_status(*ec)));
- if (ec != 0 && *ec)
- return;
- bool and_pred = or_pred && (ec == 0 ? is_directory(m_stack.top()->status())
- : is_directory(m_stack.top()->status(*ec)));
- if (ec != 0 && *ec)
- return;
-
- if (and_pred)
+
+ file_status symlink_stat;
+
+ if ((m_options & symlink_option::recurse) != symlink_option::recurse)
{
- if (ec == 0)
- m_stack.push(directory_iterator(m_stack.top()->path()));
- else
- {
- m_stack.push(directory_iterator(m_stack.top()->path(), *ec));
- if (*ec)
- return;
- }
- if (m_stack.top() != directory_iterator())
+ symlink_stat = m_stack.top()->symlink_status(ec);
+ if (ec)
+ return false;
+ }
+
+ if ((m_options & symlink_option::recurse) == symlink_option::recurse
+ || !is_symlink(symlink_stat))
+ {
+ file_status stat = m_stack.top()->status(ec);
+ if (ec || !is_directory(stat))
+ return false;
+
+ directory_iterator next(m_stack.top()->path(), ec);
+ if (!ec && next != directory_iterator())
{
+ m_stack.push(next);
++m_level;
- return;
+ return true;
}
- m_stack.pop();
}
}
+ return false;
+ }
+
+ inline
+ void recur_dir_itr_imp::increment(system::error_code* ec)
+ // ec == 0 means throw on error
+ //
+ // Invariant: On return, the top of the iterator stack is the next valid (possibly
+ // end) iterator, regardless of whether or not an error is reported, and regardless of
+ // whether any error is reported by exception or error code. In other words, progress
+ // is always made so a loop on the iterator will always eventually terminate
+ // regardless of errors.
+ {
+ system::error_code ec_push_directory;
+ // if various conditions are met, push a directory_iterator into the iterator stack
+ if (push_directory(ec_push_directory))
+ {
+ if (ec)
+ ec->clear();
+ return;
+ }
+
+ // Do the actual increment operation on the top iterator in the iterator
+ // stack, popping the stack if necessary, until either the stack is empty or a
+ // non-end iterator is reached.
while (!m_stack.empty() && ++m_stack.top() == directory_iterator())
{
m_stack.pop();
--m_level;
}
+
+ // report errors if any
+ if (ec_push_directory)
+ {
+ if (ec)
+ *ec = ec_push_directory;
+ else
+ {
+ BOOST_FILESYSTEM_THROW(filesystem_error(
+ "filesystem::recursive_directory_iterator directory error",
+ ec_push_directory));
+ }
+ }
+ else if (ec)
+ ec->clear();
}
inline
@@ -967,116 +1167,45 @@ namespace detail
};
-# if !defined(BOOST_FILESYSTEM_NO_DEPRECATED)
- typedef recursive_directory_iterator wrecursive_directory_iterator;
-# endif
+ // enable C++11 range-base for statement use ---------------------------------------//
-//--------------------------------------------------------------------------------------//
-// //
-// class filesystem_error //
-// //
-//--------------------------------------------------------------------------------------//
-
- class BOOST_SYMBOL_VISIBLE filesystem_error : public system::system_error
- {
- // see http://www.boost.org/more/error_handling.html for design rationale
-
- // all functions are inline to avoid issues with crossing dll boundaries
-
- public:
- // compiler generates copy constructor and copy assignment
-
- filesystem_error(
- const std::string & what_arg, system::error_code ec)
- : system::system_error(ec, what_arg)
- {
- try
- {
- m_imp_ptr.reset(new m_imp);
- }
- catch (...) { m_imp_ptr.reset(); }
- }
-
- filesystem_error(
- const std::string & what_arg, const path& path1_arg,
- system::error_code ec)
- : system::system_error(ec, what_arg)
- {
- try
- {
- m_imp_ptr.reset(new m_imp);
- m_imp_ptr->m_path1 = path1_arg;
- }
- catch (...) { m_imp_ptr.reset(); }
- }
-
- filesystem_error(
- const std::string & what_arg, const path& path1_arg,
- const path& path2_arg, system::error_code ec)
- : system::system_error(ec, what_arg)
- {
- try
- {
- m_imp_ptr.reset(new m_imp);
- m_imp_ptr->m_path1 = path1_arg;
- m_imp_ptr->m_path2 = path2_arg;
- }
- catch (...) { m_imp_ptr.reset(); }
- }
+ // begin() and end() are only used by a range-based for statement in the context of
+ // auto - thus the top-level const is stripped - so returning const is harmless and
+ // emphasizes begin() is just a pass through.
+ inline
+ const recursive_directory_iterator& begin(const recursive_directory_iterator& iter)
+ {return iter;}
+ inline
+ recursive_directory_iterator end(const recursive_directory_iterator&)
+ {return recursive_directory_iterator();}
- ~filesystem_error() throw() {}
+ // enable BOOST_FOREACH ------------------------------------------------------------//
- const path& path1() const
- {
- static const path empty_path;
- return m_imp_ptr.get() ? m_imp_ptr->m_path1 : empty_path ;
- }
- const path& path2() const
- {
- static const path empty_path;
- return m_imp_ptr.get() ? m_imp_ptr->m_path2 : empty_path ;
- }
+ inline
+ recursive_directory_iterator& range_begin(recursive_directory_iterator& iter)
+ {return iter;}
+ inline
+ recursive_directory_iterator range_begin(const recursive_directory_iterator& iter)
+ {return iter;}
+ inline
+ recursive_directory_iterator range_end(const recursive_directory_iterator&)
+ {return recursive_directory_iterator();}
+ } // namespace filesystem
- const char* what() const throw()
- {
- if (!m_imp_ptr.get())
- return system::system_error::what();
+ // namespace boost template specializations
+ template<>
+ struct range_mutable_iterator<boost::filesystem::recursive_directory_iterator>
+ { typedef boost::filesystem::recursive_directory_iterator type; };
+ template<>
+ struct range_const_iterator <boost::filesystem::recursive_directory_iterator>
+ { typedef boost::filesystem::recursive_directory_iterator type; };
- try
- {
- if (m_imp_ptr->m_what.empty())
- {
- m_imp_ptr->m_what = system::system_error::what();
- if (!m_imp_ptr->m_path1.empty())
- {
- m_imp_ptr->m_what += ": \"";
- m_imp_ptr->m_what += m_imp_ptr->m_path1.string();
- m_imp_ptr->m_what += "\"";
- }
- if (!m_imp_ptr->m_path2.empty())
- {
- m_imp_ptr->m_what += ", \"";
- m_imp_ptr->m_what += m_imp_ptr->m_path2.string();
- m_imp_ptr->m_what += "\"";
- }
- }
- return m_imp_ptr->m_what.c_str();
- }
- catch (...)
- {
- return system::system_error::what();
- }
- }
+namespace filesystem
+{
- private:
- struct m_imp
- {
- path m_path1; // may be empty()
- path m_path2; // may be empty()
- std::string m_what; // not built until needed
- };
- boost::shared_ptr<m_imp> m_imp_ptr;
- };
+# if !defined(BOOST_FILESYSTEM_NO_DEPRECATED)
+ typedef recursive_directory_iterator wrecursive_directory_iterator;
+# endif
// test helper -----------------------------------------------------------------------//
diff --git a/boost/filesystem/path.hpp b/boost/filesystem/path.hpp
index 2dd1b00..37f39d0 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
diff --git a/boost/filesystem/path_traits.hpp b/boost/filesystem/path_traits.hpp
index a6a2505..5441692 100644
--- a/boost/filesystem/path_traits.hpp
+++ b/boost/filesystem/path_traits.hpp
@@ -91,43 +91,65 @@ namespace path_traits {
// value types differ ---------------------------------------------------------------//
//
// A from_end argument of 0 is less efficient than a known end, so use only if needed
-
- BOOST_FILESYSTEM_DECL
- void convert(const char* from,
- const char* from_end, // 0 for null terminated MBCS
- std::wstring & to,
- const codecvt_type& cvt);
+
+ // with codecvt
BOOST_FILESYSTEM_DECL
- void convert(const wchar_t* from,
- const wchar_t* from_end, // 0 for null terminated MBCS
- std::string & to,
- const codecvt_type& cvt);
+ void convert(const char* from,
+ const char* from_end, // 0 for null terminated MBCS
+ std::wstring & to,
+ const codecvt_type& cvt);
- inline
- void convert(const char* from,
- std::wstring & to,
- const codecvt_type& cvt)
+ BOOST_FILESYSTEM_DECL
+ void convert(const wchar_t* from,
+ const wchar_t* from_end, // 0 for null terminated MBCS
+ std::string & to,
+ const codecvt_type& cvt);
+
+ inline
+ void convert(const char* from,
+ std::wstring & to,
+ const codecvt_type& cvt)
{
BOOST_ASSERT(from);
convert(from, 0, to, cvt);
}
- inline
- void convert(const wchar_t* from,
- std::string & to,
- const codecvt_type& cvt)
+ inline
+ void convert(const wchar_t* from,
+ std::string & to,
+ const codecvt_type& cvt)
{
BOOST_ASSERT(from);
convert(from, 0, to, cvt);
}
+ // without codecvt
+
+ inline
+ void convert(const char* from,
+ const char* from_end, // 0 for null terminated MBCS
+ std::wstring & to);
+
+ inline
+ void convert(const wchar_t* from,
+ const wchar_t* from_end, // 0 for null terminated MBCS
+ std::string & to);
+
+ inline
+ void convert(const char* from,
+ std::wstring & to);
+
+ inline
+ void convert(const wchar_t* from,
+ std::string & to);
+
// value types same -----------------------------------------------------------------//
- // char
+ // char with codecvt
- inline
- void convert(const char* from, const char* from_end, std::string & to,
+ inline
+ void convert(const char* from, const char* from_end, std::string & to,
const codecvt_type&)
{
BOOST_ASSERT(from);
@@ -135,19 +157,19 @@ namespace path_traits {
to.append(from, from_end);
}
- inline
- void convert(const char* from,
- std::string & to,
- const codecvt_type&)
+ inline
+ void convert(const char* from,
+ std::string & to,
+ const codecvt_type&)
{
BOOST_ASSERT(from);
to += from;
}
- // wchar_t
+ // wchar_t with codecvt
- inline
- void convert(const wchar_t* from, const wchar_t* from_end, std::wstring & to,
+ inline
+ void convert(const wchar_t* from, const wchar_t* from_end, std::wstring & to,
const codecvt_type&)
{
BOOST_ASSERT(from);
@@ -155,10 +177,44 @@ namespace path_traits {
to.append(from, from_end);
}
- inline
- void convert(const wchar_t* from,
- std::wstring & to,
- const codecvt_type&)
+ inline
+ void convert(const wchar_t* from,
+ std::wstring & to,
+ const codecvt_type&)
+ {
+ BOOST_ASSERT(from);
+ to += from;
+ }
+
+ // char without codecvt
+
+ inline
+ void convert(const char* from, const char* from_end, std::string & to)
+ {
+ BOOST_ASSERT(from);
+ BOOST_ASSERT(from_end);
+ to.append(from, from_end);
+ }
+
+ inline
+ void convert(const char* from, std::string & to)
+ {
+ BOOST_ASSERT(from);
+ to += from;
+ }
+
+ // wchar_t without codecvt
+
+ inline
+ void convert(const wchar_t* from, const wchar_t* from_end, std::wstring & to)
+ {
+ BOOST_ASSERT(from);
+ BOOST_ASSERT(from_end);
+ to.append(from, from_end);
+ }
+
+ inline
+ void convert(const wchar_t* from, std::wstring & to)
{
BOOST_ASSERT(from);
to += from;
@@ -166,7 +222,7 @@ namespace path_traits {
// Source dispatch -----------------------------------------------------------------//
- // contiguous containers
+ // contiguous containers with codecvt
template <class U> inline
void dispatch(const std::string& c, U& to, const codecvt_type& cvt)
{
@@ -192,12 +248,38 @@ namespace path_traits {
convert(&*c.begin(), &*c.begin() + c.size(), to, cvt);
}
- // non-contiguous containers
+ // contiguous containers without codecvt
+ template <class U> inline
+ void dispatch(const std::string& c, U& to)
+ {
+ if (c.size())
+ convert(&*c.begin(), &*c.begin() + c.size(), to);
+ }
+ template <class U> inline
+ void dispatch(const std::wstring& c, U& to)
+ {
+ if (c.size())
+ convert(&*c.begin(), &*c.begin() + c.size(), to);
+ }
+ template <class U> inline
+ void dispatch(const std::vector<char>& c, U& to)
+ {
+ if (c.size())
+ convert(&*c.begin(), &*c.begin() + c.size(), to);
+ }
+ template <class U> inline
+ void dispatch(const std::vector<wchar_t>& c, U& to)
+ {
+ if (c.size())
+ convert(&*c.begin(), &*c.begin() + c.size(), to);
+ }
+
+ // non-contiguous containers with codecvt
template <class Container, class U> inline
// disable_if aids broken compilers (IBM, old GCC, etc.) and is harmless for
// conforming compilers. Replace by plain "void" at some future date (2012?)
typename boost::disable_if<boost::is_array<Container>, void>::type
- dispatch(const Container & c, U& to, const codecvt_type& cvt)
+ dispatch(const Container & c, U& to, const codecvt_type& cvt)
{
if (c.size())
{
@@ -208,24 +290,59 @@ namespace path_traits {
// c_str
template <class T, class U> inline
- void dispatch(T * const & c_str, U& to, const codecvt_type& cvt)
+ void dispatch(T * const & c_str, U& to, const codecvt_type& cvt)
{
-// std::cout << "dispatch() const T *\n";
+ // std::cout << "dispatch() const T *\n";
BOOST_ASSERT(c_str);
convert(c_str, to, cvt);
}
-
+
+ // Note: there is no dispatch on C-style arrays because the array may
+ // contain a string smaller than the array size.
+
+ BOOST_FILESYSTEM_DECL
+ void dispatch(const directory_entry & de,
+# ifdef BOOST_WINDOWS_API
+ std::wstring & to,
+# else
+ std::string & to,
+# endif
+ const codecvt_type&);
+
+ // non-contiguous containers without codecvt
+ template <class Container, class U> inline
+ // disable_if aids broken compilers (IBM, old GCC, etc.) and is harmless for
+ // conforming compilers. Replace by plain "void" at some future date (2012?)
+ typename boost::disable_if<boost::is_array<Container>, void>::type
+ dispatch(const Container & c, U& to)
+ {
+ if (c.size())
+ {
+ std::basic_string<typename Container::value_type> s(c.begin(), c.end());
+ convert(s.c_str(), s.c_str()+s.size(), to);
+ }
+ }
+
+ // c_str
+ template <class T, class U> inline
+ void dispatch(T * const & c_str, U& to)
+ {
+ // std::cout << "dispatch() const T *\n";
+ BOOST_ASSERT(c_str);
+ convert(c_str, to);
+ }
+
// Note: there is no dispatch on C-style arrays because the array may
// contain a string smaller than the array size.
BOOST_FILESYSTEM_DECL
- void dispatch(const directory_entry & de,
+ void dispatch(const directory_entry & de,
# ifdef BOOST_WINDOWS_API
- std::wstring & to,
+ std::wstring & to
# else
- std::string & to,
+ std::string & to
# endif
- const codecvt_type&);
+ );
}}} // namespace boost::filesystem::path_traits