Boost logo

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 @@
 &nbsp;&nbsp;&nbsp;&nbsp;directory_entry observers<br>
 &nbsp;&nbsp;&nbsp;&nbsp;directory_entry comparisons<br>
 <a href="#Class-directory_iterator">Class directory_iterator</a><br>
-&nbsp;&nbsp;&nbsp;
-<a href="#directory_iterator-constructors">directory_iterator
- constructors</a><br>
+&nbsp;&nbsp;&nbsp; <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&lt;value_type&gt; string_type;
         typedef path_traits::codecvt_type codecvt_type;
 
- // constructors
+ // constructors and destructor
         path();
         path(const path&amp; p);
 
@@ -428,6 +427,8 @@
         template &lt;class Source&gt;
           path(Source const&amp; source);
 
+ ~path();
+
         // assignments
         path&amp; operator=(const path&amp; 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&amp;);
         <a href="#filesystem_error-2-arg">filesystem_error</a>(const std::string&amp; <span style="background-color: #FFFFFF">what_arg</span>, system::error_code ec);
         <a href="#filesystem_error-3-arg">filesystem_error</a>(const std::string&amp; <span style="background-color: #FFFFFF">what_arg</span>, const path&amp; p1, system::error_code ec);
         <a href="#filesystem_error-4-arg">filesystem_error</a>(const std::string&amp; <span style="background-color: #FFFFFF">what_arg</span>, const path&amp; p1, const path&amp; p2, system::error_code ec);
 
+ filesystem_error&amp; filesystem_error(const filesystem_error&amp;);
+ ~filesystem_error();
+
+ filesystem_error&amp; operator=(const filesystem_error&amp;);
+
         const path&amp; path1() const;
         const path&amp; path2() const;
 
@@ -1422,11 +1429,14 @@
       {
       public:
 
- // constructors
+ // constructors and destructor
         directory_entry();
+ directory_entry(const directory_entry&amp;);
         explicit directory_entry(const path_type&amp; 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&amp; operator=(const directory_entry&amp;);
         void assign(const path_type&amp; 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&amp; 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 &quot;end&quot; iterator
+ directory_iterator(const directory_iterator&amp;);
         explicit directory_iterator(const path&amp; p);
         directory_iterator(const path&amp; p, system::error_code&amp; ec);
-
        ~directory_iterator();
 
+ directory_iterator&amp; operator=(const directory_iterator&amp;);
+
+ directory_iterator&amp; operator++();
+ directory_iterator&amp; increment(system::error_code&amp; 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(&quot;.&quot;)</code> rather than <code>directory_iterator(&quot;&quot;)</code>.
 <i>-- end note</i>]</p>
 </blockquote>
+<pre>directory_iterator&amp; <a name="directory_iterator-increment">operator++</a>();
+directory_iterator&amp; increment(system::error_code&amp; 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&amp; dp);
- recursive_directory_iterator(const recursive_directory_iterator&amp; brdi);
- recursive_directory_iterator&amp; operator=(const recursive_directory_iterator&amp; brdi);
+ recursive_directory_iterator(const recursive_directory_iterator&amp;);
+ explicit recursive_directory_iterator(const path&amp; p);
+ recursive_directory_iterator(const path&amp; p, system::error_code&amp; ec);
        ~recursive_directory_iterator();
 
         // observers
         int level() const;
+ bool no_push<code>_request</code>() const;
 
         // modifiers
+ recursive_directory_iterator&amp; operator=(const recursive_directory_iterator&amp;);
+
+ recursive_directory_iterator&amp; operator++();
+ recursive_directory_iterator&amp; increment(system::error_code&amp; 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-&gt;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&nbsp; <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&amp; p<code>);
+</code>recursive_<code>directory_iterator(</code>const path&amp; p, system::error_code&amp; ec<code>);</code></pre>
+<blockquote>
+
+<p><i>Effects:</i>&nbsp; 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(&quot;.&quot;)</code> rather than
+<code>recursive_directory_iterator(&quot;&quot;)</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&amp; <a name="directory_iterator-increment">operator++</a>();
+<code>recursive_</code>directory_iterator&amp; increment(system::error_code&amp; 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)-&gt;is_directory() &amp;&amp; !no_push_requested()</code> then&nbsp; <code>m_level</code>
+is incremented and <code>(*this)-&gt;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&amp;);
+ 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