summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '3rdParty/Boost/src/boost/filesystem/operations.hpp')
-rw-r--r--3rdParty/Boost/src/boost/filesystem/operations.hpp378
1 files changed, 247 insertions, 131 deletions
diff --git a/3rdParty/Boost/src/boost/filesystem/operations.hpp b/3rdParty/Boost/src/boost/filesystem/operations.hpp
index dc01b7d..9005b3e 100644
--- a/3rdParty/Boost/src/boost/filesystem/operations.hpp
+++ b/3rdParty/Boost/src/boost/filesystem/operations.hpp
@@ -1,159 +1,270 @@
// boost/filesystem/operations.hpp ---------------------------------------------------//
// Copyright Beman Dawes 2002-2009
// Copyright Jan Langer 2002
// Copyright Dietmar Kuehl 2001
// Copyright Vladimir Prus 2002
// 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
//--------------------------------------------------------------------------------------//
#ifndef BOOST_FILESYSTEM3_OPERATIONS_HPP
#define BOOST_FILESYSTEM3_OPERATIONS_HPP
#include <boost/config.hpp>
# if defined( BOOST_NO_STD_WSTRING )
# error Configuration not supported: Boost.Filesystem V3 and later requires std::wstring support
# endif
#include <boost/filesystem/config.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/detail/scoped_enum_emulation.hpp>
#include <boost/detail/bitmask.hpp>
#include <boost/system/error_code.hpp>
#include <boost/system/system_error.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/utility/enable_if.hpp>
#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>
#include <vector>
#include <stack>
#ifdef BOOST_WINDOWS_API
# include <fstream>
#endif
#include <boost/config/abi_prefix.hpp> // must be the last #include
//--------------------------------------------------------------------------------------//
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 //
//--------------------------------------------------------------------------------------//
enum file_type
{
status_error,
# ifndef BOOST_FILESYSTEM_NO_DEPRECATED
status_unknown = status_error,
# endif
file_not_found,
regular_file,
directory_file,
// the following may not apply to some operating systems or file systems
symlink_file,
block_file,
character_file,
fifo_file,
socket_file,
reparse_file, // Windows: FILE_ATTRIBUTE_REPARSE_POINT that is not a symlink
type_unknown, // file does exist, but isn't one of the above types or
// we don't have strong enough permission to find its type
_detail_directory_symlink // internal use only; never exposed to users
};
//--------------------------------------------------------------------------------------//
// perms //
//--------------------------------------------------------------------------------------//
enum perms
{
no_perms = 0, // file_not_found is no_perms rather than perms_not_known
// POSIX equivalent macros given in comments.
// Values are from POSIX and are given in octal per the POSIX standard.
// permission bits
owner_read = 0400, // S_IRUSR, Read permission, owner
owner_write = 0200, // S_IWUSR, Write permission, owner
owner_exe = 0100, // S_IXUSR, Execute/search permission, owner
owner_all = 0700, // S_IRWXU, Read, write, execute/search by owner
group_read = 040, // S_IRGRP, Read permission, group
group_write = 020, // S_IWGRP, Write permission, group
group_exe = 010, // S_IXGRP, Execute/search permission, group
group_all = 070, // S_IRWXG, Read, write, execute/search by group
others_read = 04, // S_IROTH, Read permission, others
others_write = 02, // S_IWOTH, Write permission, others
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
set_uid_on_exe = 04000, // S_ISUID, Set-user-ID on execution
set_gid_on_exe = 02000, // S_ISGID, Set-group-ID on execution
sticky_bit = 01000, // S_ISVTX,
// (POSIX XSI) On directories, restricted deletion flag
// (V7) 'sticky bit': save swapped text even after use
// (SunOS) On non-directories: don't cache this file
// (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
// options for permissions() function
add_perms = 0x1000, // adds the given permission bits to the current bits
remove_perms = 0x2000, // removes the given permission bits from the current bits;
// choose add_perms or remove_perms, not both; if neither add_perms
// nor remove_perms is given, replace the current bits with
// the given bits.
symlink_perms = 0x4000 // on POSIX, don't resolve symlinks; implied on Windows
};
BOOST_BITMASK(perms)
//--------------------------------------------------------------------------------------//
// file_status //
//--------------------------------------------------------------------------------------//
class BOOST_FILESYSTEM_DECL file_status
{
public:
file_status() : m_value(status_error), m_perms(perms_not_known) {}
explicit file_status(file_type v, perms prms = perms_not_known)
: m_value(v), m_perms(prms) {}
// observers
file_type type() const { return m_value; }
perms permissions() const { return m_perms; }
// modifiers
void type(file_type v) { m_value = v; }
void permissions(perms prms) { m_perms = prms; }
@@ -689,158 +800,234 @@ namespace detail
directory_iterator& increment(system::error_code& ec)
{
detail::directory_iterator_increment(*this, &ec);
return *this;
}
private:
friend struct detail::dir_itr_imp;
friend BOOST_FILESYSTEM_DECL void detail::directory_iterator_construct(directory_iterator& it,
const path& p, system::error_code* ec);
friend BOOST_FILESYSTEM_DECL void detail::directory_iterator_increment(directory_iterator& it,
system::error_code* ec);
// shared_ptr provides shallow-copy semantics required for InputIterators.
// m_imp.get()==0 indicates the end iterator.
boost::shared_ptr< detail::dir_itr_imp > m_imp;
friend class boost::iterator_core_access;
boost::iterator_facade<
directory_iterator,
directory_entry,
boost::single_pass_traversal_tag >::reference dereference() const
{
BOOST_ASSERT_MSG(m_imp.get(), "attempt to dereference end iterator");
return m_imp->dir_entry;
}
void increment() { detail::directory_iterator_increment(*this, 0); }
bool equal(const directory_iterator& rhs) const
{ 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 //
// //
//--------------------------------------------------------------------------------------//
BOOST_SCOPED_ENUM_START(symlink_option)
{
none,
no_recurse = none, // don't follow directory symlinks (default behavior)
recurse, // follow directory symlinks
_detail_no_push = recurse << 1 // internal use only
};
BOOST_SCOPED_ENUM_END
BOOST_BITMASK(BOOST_SCOPED_ENUM(symlink_option))
namespace detail
{
struct recur_dir_itr_imp
{
typedef directory_iterator element_type;
std::stack< element_type, std::vector< element_type > > m_stack;
int m_level;
BOOST_SCOPED_ENUM(symlink_option) m_options;
recur_dir_itr_imp() : m_level(0), m_options(symlink_option::none) {}
void increment(system::error_code* ec); // ec == 0 means throw on error
+ bool push_directory(system::error_code& ec) BOOST_NOEXCEPT;
+
void pop();
};
// Implementation is inline to avoid dynamic linking difficulties with m_stack:
// Microsoft warning C4251, m_stack needs to have dll-interface to be used by
// 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;
else
{
// Logic for following predicate was contributed by Daniel Aarno to handle cyclic
// symlinks correctly and efficiently, fixing ticket #5652.
// if (((m_options & symlink_option::recurse) == symlink_option::recurse
// || !is_symlink(m_stack.top()->symlink_status()))
// && 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
void recur_dir_itr_imp::pop()
{
BOOST_ASSERT_MSG(m_level > 0,
"pop() on recursive_directory_iterator with level < 1");
do
{
m_stack.pop();
--m_level;
}
while (!m_stack.empty() && ++m_stack.top() == directory_iterator());
}
} // namespace detail
//--------------------------------------------------------------------------------------//
// //
// recursive_directory_iterator //
// //
//--------------------------------------------------------------------------------------//
class recursive_directory_iterator
: public boost::iterator_facade<
recursive_directory_iterator,
directory_entry,
boost::single_pass_traversal_tag >
{
public:
recursive_directory_iterator(){} // creates the "end" iterator
explicit recursive_directory_iterator(const path& dir_path,
BOOST_SCOPED_ENUM(symlink_option) opt = symlink_option::none)
@@ -935,162 +1122,91 @@ namespace detail
}
private:
// shared_ptr provides shallow-copy semantics required for InputIterators.
// m_imp.get()==0 indicates the end iterator.
boost::shared_ptr< detail::recur_dir_itr_imp > m_imp;
friend class boost::iterator_core_access;
boost::iterator_facade<
recursive_directory_iterator,
directory_entry,
boost::single_pass_traversal_tag >::reference
dereference() const
{
BOOST_ASSERT_MSG(m_imp.get(),
"dereference of end recursive_directory_iterator");
return *m_imp->m_stack.top();
}
void increment()
{
BOOST_ASSERT_MSG(m_imp.get(),
"increment of end recursive_directory_iterator");
m_imp->increment(0);
if (m_imp->m_stack.empty())
m_imp.reset(); // done, so make end iterator
}
bool equal(const recursive_directory_iterator& rhs) const
{ return m_imp == rhs.m_imp; }
};
-# 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 -----------------------------------------------------------------------//
// Not part of the documented interface since false positives are possible;
// there is no law that says that an OS that has large stat.st_size
// actually supports large file sizes.
namespace detail
{
BOOST_FILESYSTEM_DECL bool possible_large_file_size_support();
}
} // namespace filesystem
} // namespace boost
#include <boost/config/abi_suffix.hpp> // pops abi_prefix.hpp pragmas
#endif // BOOST_FILESYSTEM3_OPERATIONS_HPP