|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r57868 - in sandbox/filesystem-v3: boost/filesystem libs/filesystem/doc libs/filesystem/example libs/filesystem/src libs/filesystem/test
From: bdawes_at_[hidden]
Date: 2009-11-23 11:48:53
Author: bemandawes
Date: 2009-11-23 11:48:52 EST (Mon, 23 Nov 2009)
New Revision: 57868
URL: http://svn.boost.org/trac/boost/changeset/57868
Log:
Refactor recursive_directory_iterator, and apply error reporting idiom.
Text files modified:
sandbox/filesystem-v3/boost/filesystem/convenience.hpp | 156 ----------------------------
sandbox/filesystem-v3/boost/filesystem/operations.hpp | 218 +++++++++++++++++++++++++++++++++++++--
sandbox/filesystem-v3/libs/filesystem/doc/reference.html | 172 +++++++++++++++++++++++++------
sandbox/filesystem-v3/libs/filesystem/example/error_demo.cpp | 72 ++++++++++--
sandbox/filesystem-v3/libs/filesystem/src/operations.cpp | 29 +++--
sandbox/filesystem-v3/libs/filesystem/test/operations_test.cpp | 15 ++
6 files changed, 433 insertions(+), 229 deletions(-)
Modified: sandbox/filesystem-v3/boost/filesystem/convenience.hpp
==============================================================================
--- sandbox/filesystem-v3/boost/filesystem/convenience.hpp (original)
+++ sandbox/filesystem-v3/boost/filesystem/convenience.hpp 2009-11-23 11:48:52 EST (Mon, 23 Nov 2009)
@@ -15,8 +15,6 @@
#include <boost/filesystem/operations.hpp>
#include <boost/system/error_code.hpp>
-#include <vector>
-#include <stack>
#include <boost/config/abi_prefix.hpp> // must be the last #include
@@ -47,160 +45,6 @@
# endif
- // basic_recursive_directory_iterator helpers --------------------------//
-
- 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;
- bool m_no_push;
- bool m_no_throw;
-
- recur_dir_itr_imp() : m_level(0), m_no_push(false), m_no_throw(false) {}
- };
-
- } // 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 )
- : m_imp( new detail::recur_dir_itr_imp )
- {
- m_imp->m_stack.push( directory_iterator( dir_path ) );
- if ( m_imp->m_stack.top () == directory_iterator() )
- { m_imp.reset (); }
- }
-
- recursive_directory_iterator( const path & dir_path,
- system::error_code & ec )
- : m_imp( new detail::recur_dir_itr_imp )
- {
- m_imp->m_no_throw = true;
- m_imp->m_stack.push( directory_iterator( dir_path, ec ) );
- if ( m_imp->m_stack.top () == directory_iterator() )
- { m_imp.reset (); }
- }
-
- int level() const { return m_imp->m_level; }
-
- void pop();
- void no_push()
- {
- BOOST_ASSERT( m_imp.get() && "no_push() on end recursive_directory_iterator" );
- m_imp->m_no_push = true;
- }
-
- file_status status() const
- {
- BOOST_ASSERT( m_imp.get()
- && "status() on end recursive_directory_iterator" );
- return m_imp->m_stack.top()->status();
- }
-
- file_status symlink_status() const
- {
- BOOST_ASSERT( m_imp.get()
- && "symlink_status() on end recursive_directory_iterator" );
- return m_imp->m_stack.top()->symlink_status();
- }
-
- 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( m_imp.get() && "dereference end recursive_directory_iterator" );
- return *m_imp->m_stack.top();
- }
-
- void increment();
-
- bool equal( const recursive_directory_iterator & rhs ) const
- { return m_imp == rhs.m_imp; }
-
- };
-
-# if !defined(BOOST_FILESYSTEM_NARROW_ONLY) && !defined(BOOST_FILESYSTEM_NO_DEPRECATED)
- typedef recursive_directory_iterator wrecursive_directory_iterator;
-# endif
-
- // basic_recursive_directory_iterator implementation -------------------//
-
- // increment
- inline void recursive_directory_iterator::increment()
- {
- BOOST_ASSERT( m_imp.get() && "increment end recursive_directory_iterator" );
-
- static const directory_iterator end_itr;
-
- if ( m_imp->m_no_push )
- { m_imp->m_no_push = false; }
- else if ( is_directory( m_imp->m_stack.top()->status() ) )
- {
- system::error_code ec;
- m_imp->m_stack.push(
- m_imp->m_no_throw
- ? directory_iterator( m_imp->m_stack.top()->path(), ec )
- : directory_iterator( m_imp->m_stack.top()->path() ) );
- if ( m_imp->m_stack.top() != end_itr )
- {
- ++m_imp->m_level;
- return;
- }
- m_imp->m_stack.pop();
- }
-
- while ( !m_imp->m_stack.empty()
- && ++m_imp->m_stack.top() == end_itr )
- {
- m_imp->m_stack.pop();
- --m_imp->m_level;
- }
-
- if ( m_imp->m_stack.empty() ) m_imp.reset(); // done, so make end iterator
- }
-
- // pop
- inline void recursive_directory_iterator::pop()
- {
- BOOST_ASSERT( m_imp.get() && "pop end recursive_directory_iterator" );
- BOOST_ASSERT( m_imp->m_level > 0 && "pop recursive_directory_iterator with level < 1" );
-
- static const directory_iterator end_itr;
-
- do
- {
- m_imp->m_stack.pop();
- --m_imp->m_level;
- }
- while ( !m_imp->m_stack.empty()
- && ++m_imp->m_stack.top() == end_itr );
-
- if ( m_imp->m_stack.empty() ) m_imp.reset(); // done, so make end iterator
- }
-
} // namespace filesystem
} // namespace boost
Modified: sandbox/filesystem-v3/boost/filesystem/operations.hpp
==============================================================================
--- sandbox/filesystem-v3/boost/filesystem/operations.hpp (original)
+++ sandbox/filesystem-v3/boost/filesystem/operations.hpp 2009-11-23 11:48:52 EST (Mon, 23 Nov 2009)
@@ -46,6 +46,8 @@
#include <string>
#include <utility> // for pair
#include <ctime>
+#include <vector>
+#include <stack>
#ifdef BOOST_WINDOWS_API
# include <fstream>
@@ -543,13 +545,13 @@
# endif
);
- struct BOOST_FILESYSTEM_DECL dir_itr_imp
+ struct dir_itr_imp
{
directory_entry dir_entry;
- void * handle;
+ void* handle;
# ifdef BOOST_POSIX_API
- void * buffer; // see dir_itr_increment implementation
+ void* buffer; // see dir_itr_increment implementation
# endif
dir_itr_imp() : handle(0)
@@ -569,9 +571,10 @@
};
// see path::iterator: comment below
- BOOST_FILESYSTEM_DECL void directory_iterator_construct(directory_iterator & it,
- const path& p, system::error_code * ec);
- BOOST_FILESYSTEM_DECL void directory_iterator_increment(directory_iterator & it);
+ BOOST_FILESYSTEM_DECL void directory_iterator_construct(directory_iterator& it,
+ const path& p, system::error_code* ec);
+ BOOST_FILESYSTEM_DECL void directory_iterator_increment(directory_iterator& it,
+ system::error_code* ec);
} // namespace detail
@@ -600,13 +603,20 @@
: m_imp(new detail::dir_itr_imp)
{ detail::directory_iterator_construct(*this, p, &ec); }
- ~directory_iterator() {} // never throws
+ ~directory_iterator() {} // never throws
+
+ directory_iterator& increment(system::error_code& ec)
+ {
+ detail::directory_iterator_increment(*this, &ec);
+ return *this;
+ }
private:
friend struct detail::dir_itr_imp;
- friend void detail::directory_iterator_construct(directory_iterator & it,
- const path& p, system::error_code * ec);
- friend void detail::directory_iterator_increment(directory_iterator & it);
+ friend void detail::directory_iterator_construct(directory_iterator& it,
+ const path& p, system::error_code* ec);
+ friend 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.
@@ -623,14 +633,198 @@
return m_imp->dir_entry;
}
- void increment() { detail::directory_iterator_increment(*this); }
+ void increment() { detail::directory_iterator_increment(*this, 0); }
- bool equal(const directory_iterator & rhs) const
+ bool equal(const directory_iterator& rhs) const
{ return m_imp == rhs.m_imp; }
};
//--------------------------------------------------------------------------------------//
// //
+// recursive_directory_iterator helpers //
+// //
+//--------------------------------------------------------------------------------------//
+
+ 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;
+ bool m_no_push_request;
+
+ recur_dir_itr_imp() : m_level(0), m_no_push_request(false) {}
+
+ void increment(system::error_code* ec); // ec == 0 means throw on error
+
+ 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
+ {
+ if (m_no_push_request)
+ { m_no_push_request = false; }
+ else if (is_directory(m_stack.top()->status()))
+ {
+ 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())
+ {
+ ++m_level;
+ return;
+ }
+ m_stack.pop();
+ }
+
+ while (!m_stack.empty() && ++m_stack.top() == directory_iterator())
+ {
+ m_stack.pop();
+ --m_level;
+ }
+ }
+
+ inline
+ void recur_dir_itr_imp::pop()
+ {
+ BOOST_ASSERT(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)
+ : m_imp(new detail::recur_dir_itr_imp)
+ {
+ m_imp->m_stack.push(directory_iterator(dir_path));
+ if (m_imp->m_stack.top() == directory_iterator())
+ { m_imp.reset (); }
+ }
+
+ recursive_directory_iterator(const path& dir_path,
+ system::error_code & ec)
+ : m_imp(new detail::recur_dir_itr_imp)
+ {
+ m_imp->m_stack.push(directory_iterator(dir_path, ec));
+ if (m_imp->m_stack.top() == directory_iterator())
+ { m_imp.reset (); }
+ }
+
+ recursive_directory_iterator& increment(system::error_code* ec)
+ {
+ BOOST_ASSERT(m_imp.get() && "increment() on end recursive_directory_iterator");
+ m_imp->increment(ec);
+ return *this;
+ }
+
+ int level() const
+ {
+ BOOST_ASSERT(m_imp.get() && "level() on end recursive_directory_iterator");
+ return m_imp->m_level;
+ }
+
+ bool no_push_request() const
+ {
+ BOOST_ASSERT(m_imp.get() && "no_push_request() on end recursive_directory_iterator");
+ return m_imp->m_no_push_request;
+ }
+
+ void pop()
+ {
+ BOOST_ASSERT(m_imp.get() && "pop() on end recursive_directory_iterator");
+ m_imp->pop();
+ if (m_imp->m_stack.empty()) m_imp.reset(); // done, so make end iterator
+ }
+
+ void no_push()
+ {
+ BOOST_ASSERT(m_imp.get() && "no_push() on end recursive_directory_iterator");
+ m_imp->m_no_push_request = true;
+ }
+
+ file_status status() const
+ {
+ BOOST_ASSERT(m_imp.get()
+ && "status() on end recursive_directory_iterator");
+ return m_imp->m_stack.top()->status();
+ }
+
+ file_status symlink_status() const
+ {
+ BOOST_ASSERT(m_imp.get()
+ && "symlink_status() on end recursive_directory_iterator");
+ return m_imp->m_stack.top()->symlink_status();
+ }
+
+ 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(m_imp.get() && "dereference of end recursive_directory_iterator");
+ return *m_imp->m_stack.top();
+ }
+
+ void increment()
+ {
+ BOOST_ASSERT(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
+
+//--------------------------------------------------------------------------------------//
+// //
// class filesystem_error //
// //
//--------------------------------------------------------------------------------------//
Modified: sandbox/filesystem-v3/libs/filesystem/doc/reference.html
==============================================================================
--- sandbox/filesystem-v3/libs/filesystem/doc/reference.html (original)
+++ sandbox/filesystem-v3/libs/filesystem/doc/reference.html 2009-11-23 11:48:52 EST (Mon, 23 Nov 2009)
@@ -74,9 +74,8 @@
directory_entry observers<br>
directory_entry comparisons<br>
<a href="#Class-directory_iterator">Class directory_iterator</a><br>
-
-<a href="#directory_iterator-constructors">directory_iterator
- constructors</a><br>
+ <a href="#directory_iterator-members">directory_iterator
+ members</a><br>
<a href="#Class-recursive_directory_iterator">Class recursive_directory_iterator</a><br>
<a href="#file_status">Class
file_status</a><br>
@@ -418,7 +417,7 @@
typedef std::basic_string<value_type> string_type;
typedef path_traits::codecvt_type codecvt_type;
- // constructors
+ // constructors and destructor
path();
path(const path& p);
@@ -428,6 +427,8 @@
template <class Source>
path(Source const& source);
+ ~path();
+
// assignments
path& operator=(const path& p);
@@ -1291,11 +1292,17 @@
class basic_filesystem_error : public <span style="background-color: #FFFFFF">system</span>_error
{
public:
-
+ filesystem_error();
+ filesystem_error(const filesystem_error&);
<a href="#filesystem_error-2-arg">filesystem_error</a>(const std::string& <span style="background-color: #FFFFFF">what_arg</span>, system::error_code ec);
<a href="#filesystem_error-3-arg">filesystem_error</a>(const std::string& <span style="background-color: #FFFFFF">what_arg</span>, const path& p1, system::error_code ec);
<a href="#filesystem_error-4-arg">filesystem_error</a>(const std::string& <span style="background-color: #FFFFFF">what_arg</span>, const path& p1, const path& p2, system::error_code ec);
+ filesystem_error& filesystem_error(const filesystem_error&);
+ ~filesystem_error();
+
+ filesystem_error& operator=(const filesystem_error&);
+
const path& path1() const;
const path& path2() const;
@@ -1422,11 +1429,14 @@
{
public:
- // constructors
+ // constructors and destructor
directory_entry();
+ directory_entry(const directory_entry&);
explicit directory_entry(const path_type& p, <span style="background-color: #FFFFFF">file_status</span> st=file_status(), <span style="background-color: #FFFFFF">file_status</span> symlink_st=file_status());
+ ~directory_entry();
// modifiers
+ directory_entry& operator=(const directory_entry&);
void assign(const path_type& p, <span style="background-color: #FFFFFF">file_status</span> st=file_status(), <span style="background-color: #FFFFFF">file_status</span> symlink_st=file_status());
void replace_filename(const string_type& s, <span style="background-color: #FFFFFF">file_status</span> st=file_status(), <span style="background-color: #FFFFFF">file_status</span> symlink_st=file_status());
@@ -1598,15 +1608,21 @@
public:
typedef Path path_type;
- // constructors
+ // member functions
+
directory_iterator(); // creates the "end" iterator
+ directory_iterator(const directory_iterator&);
explicit directory_iterator(const path& p);
directory_iterator(const path& p, system::error_code& ec);
-
~directory_iterator();
+ directory_iterator& operator=(const directory_iterator&);
+
+ directory_iterator& operator++();
+ directory_iterator& increment(system::error_code& ec);
+
// other members as required by
- // C++ Std, 24.1.1 Input iterators [lib.input.iterators]
+ // C++ Std, 24.1.1 Input iterators [input.iterators]
};
} // namespace filesystem
@@ -1667,7 +1683,7 @@
<a href="http://www.opengroup.org/onlinepubs/000095399/functions/readdir_r.html">readdir_r()</a></code>. <i>
--end note</i>]</p>
</blockquote>
-<h4><a name="directory_iterator-constructors"><code>directory_iterator</code> constructors</a></h4>
+<h4><a name="directory_iterator-members"><code>directory_iterator</code> members</a></h4>
<p><code>directory_iterator();</code></p>
@@ -1684,16 +1700,29 @@
<blockquote>
<p><i>Effects:</i> Constructs a iterator representing the first
-entry in the directory <code>p</code> resolves to, if any, otherwise, the end iterator.</p>
+entry in the directory <code>p</code> resolves to, if any; otherwise, the end iterator.</p>
<p><i>Throws:</i> As specified in
<a href="file:///C:/boost/filesystem-v3-sandbox/libs/filesystem/doc/reference.html#Error-reporting">
Error reporting</a>.</p>
-<p>[<i>Note:</i> To iterate over the current directory, write <code>
+<p>[<i>Note:</i> To iterate over the current directory, use <code>
directory_iterator(".")</code> rather than <code>directory_iterator("")</code>.
<i>-- end note</i>]</p>
</blockquote>
+<pre>directory_iterator& <a name="directory_iterator-increment">operator++</a>();
+directory_iterator& increment(system::error_code& ec);</pre>
+<blockquote>
+
+<p><i>Effects:</i> As specified by the C++ Standard, 24.1.1 Input iterators [input.iterators]</p>
+
+<p><i>Returns:</i> <code>*this</code>.</p>
+
+<p><i>Throws:</i> As specified in
+ <a href="file:///C:/boost/filesystem-v3-sandbox/libs/filesystem/doc/reference.html#Error-reporting">
+ Error reporting</a>.</p>
+
+</blockquote>
<h3><a name="Class-recursive_directory_iterator">Class <code>recursive_directory_iterator</code></a></h3>
<p>Objects of type <code>directory_iterator</code> provide standard library
compliant iteration over the contents of a directory, including recursion into
@@ -1707,17 +1736,23 @@
{
public:
- // constructors
+ // constructors and destructor
recursive_directory_iterator();
- explicit recursive_directory_iterator(const path& dp);
- recursive_directory_iterator(const recursive_directory_iterator& brdi);
- recursive_directory_iterator& operator=(const recursive_directory_iterator& brdi);
+ recursive_directory_iterator(const recursive_directory_iterator&);
+ explicit recursive_directory_iterator(const path& p);
+ recursive_directory_iterator(const path& p, system::error_code& ec);
~recursive_directory_iterator();
// observers
int level() const;
+ bool no_push<code>_request</code>() const;
// modifiers
+ recursive_directory_iterator& operator=(const recursive_directory_iterator&);
+
+ recursive_directory_iterator& operator++();
+ recursive_directory_iterator& increment(system::error_code& ec);
+
void pop();
void no_push();
@@ -1725,7 +1760,8 @@
// C++ Std, 24.1.2 Input iterators [input.iterators]
private:
- int m_level; // for exposition only
+ int m_level; <b><i> // for exposition only</i></b>
+ bool m_no_<code>push_request</code>; <b><i>// for exposition only</i></b>
};
} // namespace filesystem
@@ -1733,23 +1769,87 @@
<p>The behavior of a <code>recursive_directory_iterator</code> is the same
as a <code>directory_iterator</code> unless otherwise specified.</p>
<ul>
- <li>When an iterator is constructed, <code>m_level</code> is set to 0;</li>
- <li>When an iterator <code>it</code> is incremented, if <code>it->is_directory()</code>
- is true and <code>no_push()</code> had not been called subsequent to
- the most recent increment operation (or construction, if no increment has
- occurred), then <code>m_level</code> is incremented, the
- directory is visited, and its contents recursively iterated over.</li>
<li>When an iterator reaches the end of the directory currently being iterated
over, or when <code>pop()</code> is called, <code>m_level</code> is
decremented, and iteration continues with the parent directory, until the
directory specified in the constructor argument is reached.</li>
- <li><code>level()</code> returns <code>m_level</code>.</li>
- <li><code>level()</code>, <code>pop()</code>, and <code>no_push()</code> all
- require that the iterator not be the end iterator.</li>
</ul>
<blockquote>
<p>[<i>Note:</i> One of the uses of <code>no_push()</code> is to prevent
- unwanted recursion into symlinked directories. This may be necessary to
+ unwanted recursion into a directory symlink. This may be necessary to
+ prevent loops on some operating systems. <i>--end note</i>]</p>
+</blockquote>
+<pre>recursive_directory_iterator();</pre>
+<blockquote>
+
+<p><i>Effects:</i> Constructs the end iterator.</p>
+
+<p><i>Throws:</i> Nothing.</p>
+
+</blockquote>
+
+<pre><code>explicit </code>recursive_<code>directory_iterator(</code>const path& p<code>);
+</code>recursive_<code>directory_iterator(</code>const path& p, system::error_code& ec<code>);</code></pre>
+<blockquote>
+
+<p><i>Effects:</i> Constructs a iterator representing the first
+entry in the directory <code>p</code> resolves to, if any; otherwise, the end iterator.</p>
+
+<p><i>Postconditions: </i>Unless the end iterator was constructed,<i> </i><code>
+level() == 0</code>, <code>no_push_request() == false</code>.</p>
+
+<p><i>Throws:</i> As specified in
+ <a href="file:///C:/boost/filesystem-v3-sandbox/libs/filesystem/doc/reference.html#Error-reporting">
+ Error reporting</a>.</p>
+
+<p>[<i>Note:</i> To iterate over the current directory, use <code>recursive_directory_iterator(".")</code> rather than
+<code>recursive_directory_iterator("")</code>.
+<i>-- end note</i>]</p>
+</blockquote>
+<pre>int level() const;</pre>
+<blockquote>
+ <p><i>Requires:</i> <code>*this != recursive_directory_iterator()</code>.</p>
+ <p><i>Returns:</i> <code>m_level</code>.</p>
+ <p><i>Throws:</i> Nothing.</p>
+</blockquote>
+<pre>bool <code>no_push_request</code>() const;</pre>
+<blockquote>
+ <p><i>Requires:</i> <code>*this != recursive_directory_iterator()</code>.</p>
+ <p><i>Returns:</i> <code>m_no_push_request</code>.</p>
+ <p><i>Throws:</i> Nothing.</p>
+</blockquote>
+<pre><code>recursive_</code>directory_iterator& <a name="directory_iterator-increment">operator++</a>();
+<code>recursive_</code>directory_iterator& increment(system::error_code& ec);</pre>
+<blockquote>
+
+<p><i>Effects:</i> As specified by the C++ Standard, 24.1.1 Input iterators [input.iterators],
+except that if <code>(*this)->is_directory() && !no_push_requested()</code> then <code>m_level</code>
+is incremented and <code>(*this)->path()</code> is recursively iterated into.</p>
+
+<p><i>Postconditions:</i> <code>no_push_request() == false</code>.</p>
+
+<p><i>Returns:</i> <code>*this</code>.</p>
+
+<p><i>Throws:</i> As specified in
+ <a href="file:///C:/boost/filesystem-v3-sandbox/libs/filesystem/doc/reference.html#Error-reporting">
+ Error reporting</a>.</p>
+
+</blockquote>
+<pre>void pop();</pre>
+<blockquote>
+ <p><i>Requires:</i> <code>*this != recursive_directory_iterator()</code>.</p>
+ <p><i>Effects:</i> If <code>level() == 0</code>, set <code>*this</code> to <code>recursive_directory_iterator()</code>.
+ Otherwise, <code>--m_level</code>, cease iteration of the directory currently being
+ iterated over, and continue iteration over the parent directory.</p>
+ <p><i>Throws:</i> Nothing.</p>
+</blockquote>
+<pre>void no_push();</pre>
+<blockquote>
+ <p><i>Requires:</i> <code>*this != recursive_directory_iterator()</code>.</p>
+<p><i>Postconditions:</i> <code>no_push_request() == true</code>.</p>
+ <p><i>Throws:</i> Nothing.</p>
+ <p>[<i>Note:</i> One of the uses of <code>no_push()</code> is to prevent
+ unwanted recursion into a directory symlink. This may be necessary to
prevent loops on some operating systems. <i>--end note</i>]</p>
</blockquote>
<h3><a name="file_status">Class file_status</a></h3>
@@ -1760,10 +1860,13 @@
class file_status
{
public:
- explicit file_status( file_type v = status_error );
+ file_status();
+ file_status(const file_status&);
+ explicit file_status(file_type v=status_error);
+ ~file_status();
<a href="#file_type">file_type</a> type() const;
- void type( file_type v );
+ void type(file_type v);
};
} // namespace filesystem
} // namespace boost</pre>
@@ -1774,15 +1877,16 @@
additional status information. <i>--end note]</i></p>
</blockquote>
<h4>Members</h4>
-<pre>explicit file_status( file_type v = status_error );</pre>
+<pre>explicit file_status(file_type v=status_error);</pre>
<blockquote>
<p><i>Effects:</i> Stores <code>v</code>.</p>
+ <p><i>Throws:</i> Nothing.</p>
</blockquote>
<pre>file_type type() const;</pre>
<blockquote>
<p><i>Returns: </i>The stored file_type
.</p>
</blockquote>
-<pre>void type( file_type v );</pre>
+<pre>void type(file_type v);</pre>
<blockquote>
<p><i>Effects:</i> Stores <code>v</code>, replacing the previously stored
value.</p>
@@ -3131,9 +3235,11 @@
Witt were particularly helpful in refining the library.</p>
<p>The create_directories, extension, basename, and replace_extension functions
were developed by Vladimir Prus.</p>
-<p>Howard Hinnant and John Maddock reviewed a draft of the proposal, and
+<p>Howard Hinnant and John Maddock reviewed a draft of the version 2 proposal, and
identified a number of mistakes or weaknesses, resulting in a more polished
final document.</p>
+<p>Peter Dimov suggested a single class path, with member templates to adapt to
+multiple string types. His idea became the basis for the version 3 path design.</p>
<h2><a name="References">References</a></h2>
<table border="0" cellpadding="5" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" width="100%">
<tr>
@@ -3159,7 +3265,7 @@
<p>Distributed under the Boost Software License, Version 1.0. See
<a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a></p>
<p>Revised
-<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B %Y" startspan -->11 November 2009<!--webbot bot="Timestamp" endspan i-checksum="40583" --></p>
+<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B %Y" startspan -->23 November 2009<!--webbot bot="Timestamp" endspan i-checksum="40588" --></p>
</body>
Modified: sandbox/filesystem-v3/libs/filesystem/example/error_demo.cpp
==============================================================================
--- sandbox/filesystem-v3/libs/filesystem/example/error_demo.cpp (original)
+++ sandbox/filesystem-v3/libs/filesystem/example/error_demo.cpp 2009-11-23 11:48:52 EST (Mon, 23 Nov 2009)
@@ -37,7 +37,7 @@
void report_filesystem_error(const system_error& ex)
{
- cout << " Threw filesystem_error exception:\n"
+ cout << " threw filesystem_error exception:\n"
<< " ex.code().value() is " << ex.code().value() << '\n'
<< " ex.code().category().name() is " << ex.code().category().name() << '\n'
<< " ex.what() is " << ex.what() << '\n'
@@ -46,7 +46,7 @@
void report_status(fs::file_status s)
{
- cout << "file_status::type() is ";
+ cout << " file_status::type() is ";
switch (s.type())
{
case fs::status_error:
@@ -97,25 +97,26 @@
error_code ec;
- // construct path - no error_code
+ //// construct path - no error_code
- try { path p1(argv[1]); }
- catch (const system_error& ex)
- {
- cout << "construct path without error_code";
- report_system_error(ex);
- }
+ //try { path p1(argv[1]); }
+ //catch (const system_error& ex)
+ //{
+ // cout << "construct path without error_code";
+ // report_system_error(ex);
+ //}
- // construct path - with error_code
+ //// construct path - with error_code
+ path p (argv[1]);
- path p(argv[1]);
+ fs::file_status s;
+ bool b (false);
+ fs::directory_iterator di;
// get status - no error_code
- fs::file_status s;
-
- cout << "status(argv[1]);\n";
+ cout << "\nstatus(\"" << p.native_string() << "\");\n";
threw_exception = false;
try { s = fs::status(p); }
@@ -130,14 +131,55 @@
// get status - with error_code
- cout << "status(argv[1], ec);\n";
+ cout << "\nstatus(\"" << p.native_string() << "\", ec);\n";
s = fs::status(p, ec);
report_status(s);
report_error_code(ec);
// query existence - no error_code
+ cout << "\nexists(\"" << p.native_string() << "\");\n";
+ threw_exception = false;
+
+ try { b = fs::exists(p); }
+ catch (const system_error& ex)
+ {
+ report_filesystem_error(ex);
+ threw_exception = true;
+ }
+ if (!threw_exception)
+ {
+ cout << " Did not throw exception\n"
+ << " Returns: " << (b ? "true" : "false") << '\n';
+ }
+
// query existence - with error_code
+ // directory_iterator - no error_code
+
+ cout << "\ndirectory_iterator(\"" << p.native_string() << "\");\n";
+ threw_exception = false;
+
+ try { di = fs::directory_iterator(p); }
+ catch (const system_error& ex)
+ {
+ report_filesystem_error(ex);
+ threw_exception = true;
+ }
+ if (!threw_exception)
+ {
+ cout << " Did not throw exception\n"
+ << (di == fs::directory_iterator() ? " Equal" : " Not equal")
+ << " to the end iterator\n";
+ }
+
+ // directory_iterator - with error_code
+
+ cout << "\ndirectory_iterator(\"" << p.native_string() << "\", ec);\n";
+ di = fs::directory_iterator(p, ec);
+ cout << (di == fs::directory_iterator() ? " Equal" : " Not equal")
+ << " to the end iterator\n";
+ report_error_code(ec);
+
return 0;
}
Modified: sandbox/filesystem-v3/libs/filesystem/src/operations.cpp
==============================================================================
--- sandbox/filesystem-v3/libs/filesystem/src/operations.cpp (original)
+++ sandbox/filesystem-v3/libs/filesystem/src/operations.cpp 2009-11-23 11:48:52 EST (Mon, 23 Nov 2009)
@@ -177,6 +177,8 @@
const char dot = '.';
# endif
+ boost::filesystem::directory_iterator end_dir_itr;
+
const std::size_t buf_size(128);
const error_code ok;
@@ -270,8 +272,7 @@
bool is_empty_directory(const path& p)
{
- static const fs::directory_iterator end_itr;
- return fs::directory_iterator(p)== end_itr;
+ return fs::directory_iterator(p)== end_dir_itr;
}
bool remove_directory(const path& p) // true if succeeds
@@ -306,14 +307,13 @@
boost::uintmax_t remove_all_aux(const path& p, fs::file_status sym_stat,
error_code* ec)
{
- static const fs::directory_iterator end_itr;
boost::uintmax_t count = 1;
if (!fs::is_symlink(sym_stat)// don't recurse symbolic links
&& fs::is_directory(sym_stat))
{
for (fs::directory_iterator itr(p);
- itr != end_itr; ++itr)
+ itr != end_dir_itr; ++itr)
{
fs::file_status tmp_sym_stat = fs::symlink_status(itr->path(), *ec);
if (ec != 0 && ec)
@@ -1658,7 +1658,7 @@
# endif
}
- void directory_iterator_construct(directory_iterator & it,
+ void directory_iterator_construct(directory_iterator& it,
const path& p, system::error_code* ec)
{
if (error(p.empty(), not_found_error, p, ec,
@@ -1693,30 +1693,36 @@
}
}
- void directory_iterator_increment(directory_iterator & it)
+ void directory_iterator_increment(directory_iterator& it,
+ system::error_code* ec)
{
BOOST_ASSERT(it.m_imp.get() && "attempt to increment end iterator");
BOOST_ASSERT(it.m_imp->handle != 0 && "internal program error");
path::string_type filename;
file_status file_stat, symlink_file_stat;
- system::error_code ec;
+ system::error_code temp_ec;
for (;;)
{
- ec = dir_itr_increment(it.m_imp->handle,
+ temp_ec = dir_itr_increment(it.m_imp->handle,
#if defined(BOOST_POSIX_API)
it.m_imp->buffer,
#endif
filename, file_stat, symlink_file_stat);
- if (ec)
+ if (temp_ec)
{
it.m_imp.reset();
- error(true, it.m_imp->dir_entry.path().parent_path(),
- &ec, "boost::filesystem::directory_iterator::operator++");
+ if (ec == 0)
+ throw_exception(
+ filesystem_error("boost::filesystem::directory_iterator::operator++",
+ it.m_imp->dir_entry.path().parent_path(),
+ error_code(BOOST_ERRNO, system_category)));
+ ec->assign(BOOST_ERRNO, system_category);
return;
}
+ else if (ec != 0) ec->clear();
if (it.m_imp->handle == 0){ it.m_imp.reset(); return; } // eof, make end
if (!(filename[0] == dot // !(dot or dot-dot)
@@ -1730,7 +1736,6 @@
}
}
}
-
} // namespace detail
} // namespace filesystem
} // namespace boost
Modified: sandbox/filesystem-v3/libs/filesystem/test/operations_test.cpp
==============================================================================
--- sandbox/filesystem-v3/libs/filesystem/test/operations_test.cpp (original)
+++ sandbox/filesystem-v3/libs/filesystem/test/operations_test.cpp 2009-11-23 11:48:52 EST (Mon, 23 Nov 2009)
@@ -292,11 +292,21 @@
catch (const fs::filesystem_error &) { dir_itr_exception = true; }
BOOST_TEST(dir_itr_exception);
+ error_code ec;
+
+ BOOST_TEST(!ec);
+ fs::directory_iterator it("", ec);
+ BOOST_TEST(ec);
+
dir_itr_exception = false;
try { fs::directory_iterator it("nosuchdirectory"); }
catch (const fs::filesystem_error &) { dir_itr_exception = true; }
BOOST_TEST(dir_itr_exception);
+ ec.clear();
+ fs::directory_iterator it2("nosuchdirectory", ec);
+ BOOST_TEST(ec);
+
dir_itr_exception = false;
try
{
@@ -353,7 +363,10 @@
}
BOOST_TEST(++dir_itr == fs::directory_iterator());
BOOST_TEST(dir_itr2 != fs::directory_iterator());
- BOOST_TEST(++dir_itr2 == fs::directory_iterator());
+ ec.clear();
+ dir_itr2.increment(ec);
+ BOOST_TEST(!ec);
+ BOOST_TEST(dir_itr2 == fs::directory_iterator());
}
{ // *i++ must work to meet the standard's InputIterator requirements
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk