From 52bb7cd2583d67557a211acc9bfa4e3c2eb84fc3 Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Tue, 26 Nov 2002 15:51:18 +0000 Subject: [PATCH] directory_iterator simplification [SVN r16424] --- include/boost/filesystem/operations.hpp | 85 ++++++++-------- include/boost/filesystem/path.hpp | 8 +- src/operations_posix_windows.cpp | 127 ++++++++++++------------ 3 files changed, 107 insertions(+), 113 deletions(-) diff --git a/include/boost/filesystem/operations.hpp b/include/boost/filesystem/operations.hpp index 8f35060..dc23182 100644 --- a/include/boost/filesystem/operations.hpp +++ b/include/boost/filesystem/operations.hpp @@ -23,8 +23,8 @@ #include #include -#include -#include +#include +#include #include @@ -66,61 +66,58 @@ namespace boost void copy_file( const path & from_file_ph, const path & to_file_ph ); - const path & initial_directory(); + const path & initial_path(); + path current_path(); -// directory_iterator details ----------------------------------------------// +// details -----------------------------------------------------------------// namespace detail { - const char * implementation_name(); - - class directory_iterator_imp; - - struct directory_iterator_internals - { - typedef boost::shared_ptr< detail::directory_iterator_imp > dii_ptr; - dii_ptr imp; - - const path & deref() const; - void inc(); - }; - - struct dii_policies : public default_iterator_policies - { - - template - typename IteratorAdaptor::reference - dereference(const IteratorAdaptor& x) const - { return x.base().deref(); } - - template - void increment(IteratorAdaptor& x) - { x.base().inc(); } - - template - bool equal(const IteratorAdaptor1& x, const IteratorAdaptor2& y) const - { return x.base().imp == y.base().imp; } - }; + const char * implementation_name(); // helps testing to know name } // directory_iterator ------------------------------------------------------// class directory_iterator - : public boost::iterator_adaptor< - // because directory_iterator is an InputIterator, shallow copy- - // semantics are required, and shared_ptr provides that. - detail::directory_iterator_internals, - detail::dii_policies, - path, const path &, const path *, - std::input_iterator_tag, std::ptrdiff_t > + : public boost::iterator< std::input_iterator_tag, + path, std::ptrdiff_t, const path *, const path & > { + private: + typedef directory_iterator self; public: directory_iterator(); // creates the "end" iterator - explicit directory_iterator( const path & system_specific_directory_string ); + explicit directory_iterator( const path & p ); - // workaround iterator_adaptor / compiler interactions - const boost::filesystem::path * operator->() const - { return &base().deref(); } + reference operator*() const { return m_deref(); } + pointer operator->() const { return &m_deref(); } + self & operator++() { m_inc(); return *this; } + + friend bool operator==( const self & x, const self & y ) + { return x.m_imp == y.m_imp; } + friend bool operator!=( const self & x, const self & y ) + { return !(x.m_imp == y.m_imp); } + + struct path_proxy // allows *i++ to work, as required by std + { + path pv; + explicit path_proxy( const path & p ) : pv(p) {} + path operator*() const { return pv; } + }; + + path_proxy operator++(int) + { + path_proxy pp( m_deref() ); + ++*this; + return pp; + } + + private: + class dir_itr_imp; + // shared_ptr provides shallow-copy semantics required for InputIterators + typedef boost::shared_ptr< dir_itr_imp > m_imp_ptr; + m_imp_ptr m_imp; + reference m_deref() const; + void m_inc(); }; } // namespace filesystem diff --git a/include/boost/filesystem/path.hpp b/include/boost/filesystem/path.hpp index 61fb1fc..2d4271a 100644 --- a/include/boost/filesystem/path.hpp +++ b/include/boost/filesystem/path.hpp @@ -67,10 +67,6 @@ namespace boost const path operator /( const path & rhs ) const { return path( *this ) /= rhs; } - // composition functions: - path & make_absolute(); - path & make_absolute( const path & root_source ); - // decomposition functions: path root_path() const; std::string system_specific_root() const; @@ -138,10 +134,10 @@ namespace boost // path non-member functions ---------------------------------------------// - inline const path operator / ( const char * lhs, const path & rhs ) + inline path operator / ( const char * lhs, const path & rhs ) { return path( lhs ) /= rhs; } - inline const path operator / ( const std::string & lhs, const path & rhs ) + inline path operator / ( const std::string & lhs, const path & rhs ) { return path( lhs ) /= rhs; } // error checking --------------------------------------------------------// diff --git a/src/operations_posix_windows.cpp b/src/operations_posix_windows.cpp index c985a4c..08472bc 100644 --- a/src/operations_posix_windows.cpp +++ b/src/operations_posix_windows.cpp @@ -27,6 +27,7 @@ #include #include #include +#include //#include namespace fs = boost::filesystem; @@ -177,22 +178,22 @@ namespace boost const char * implementation_name() { return "Windows"; } #endif -// directory_iterator_imp --------------------------------------------------// - - class directory_iterator_imp - { - public: - path entry_path; - BOOST_HANDLE handle; - - ~directory_iterator_imp() - { - if ( handle != BOOST_INVALID_HANDLE_VALUE ) find_close( handle ); - } - }; - } // namespace detail +// dir_itr_imp -------------------------------------------------------------// + + class directory_iterator::dir_itr_imp + { + public: + path entry_path; + BOOST_HANDLE handle; + + ~dir_itr_imp() + { + if ( handle != BOOST_INVALID_HANDLE_VALUE ) find_close( handle ); + } + }; + // directory_iterator implementation ---------------------------------------// // default ctor creates the "end" iterator (by letting base default to 0) @@ -200,22 +201,22 @@ namespace boost directory_iterator::directory_iterator( const path & dir_path ) { - base().imp.reset( new detail::directory_iterator_imp ); + m_imp.reset( new dir_itr_imp ); BOOST_SYSTEM_DIRECTORY_TYPE scratch; const char * name; if ( dir_path.is_null() ) - base().imp->handle = BOOST_INVALID_HANDLE_VALUE; + m_imp->handle = BOOST_INVALID_HANDLE_VALUE; else name = find_first_file( dir_path.system_specific_directory_string().c_str(), - base().imp->handle, scratch ); // sets handle + m_imp->handle, scratch ); // sets handle - if ( base().imp->handle != BOOST_INVALID_HANDLE_VALUE ) + if ( m_imp->handle != BOOST_INVALID_HANDLE_VALUE ) { - base().imp->entry_path = dir_path; - base().imp->entry_path.m_path_append( name, path::nocheck ); - while ( base().imp.get() - && ( base().imp->entry_path.leaf() == "." - || base().imp->entry_path.leaf() == ".." ) ) + m_imp->entry_path = dir_path; + m_imp->entry_path.m_path_append( name, path::nocheck ); + while ( m_imp.get() + && ( m_imp->entry_path.leaf() == "." + || m_imp->entry_path.leaf() == ".." ) ) { operator++(); } } else @@ -226,28 +227,26 @@ namespace boost } } - namespace detail + path const & directory_iterator::m_deref() const { - path const & directory_iterator_internals::deref() const + assert( m_imp.get() ); // fails if dereference end iterator + return m_imp->entry_path; + } + + void directory_iterator::m_inc() + { + assert( m_imp.get() ); // fails on increment end iterator + assert( m_imp->handle != BOOST_INVALID_HANDLE_VALUE ); // reality check + + BOOST_SYSTEM_DIRECTORY_TYPE scratch; + const char * name; + if ( (name = find_next_file( m_imp->handle, scratch )) != 0 ) { - assert( imp.get() ); // fails if dereference end iterator - return imp->entry_path; + m_imp->entry_path.m_replace_leaf( name ); } - - void directory_iterator_internals::inc() + else { - assert( imp.get() ); // fails on increment end iterator - assert( imp->handle != BOOST_INVALID_HANDLE_VALUE ); // imp reality check - - BOOST_SYSTEM_DIRECTORY_TYPE scratch; - const char * name; - if ( (name = find_next_file( imp->handle, scratch )) != 0 ) - { - imp->entry_path.m_replace_leaf( name ); - } - else { - imp.reset(); // make base() the end iterator - } + m_imp.reset(); // make base() the end iterator } } @@ -401,29 +400,31 @@ namespace boost + ", " + to_file_ph.system_specific_file_string().c_str(), system_error ); } - const path & initial_directory() + path current_path() { - static path init_dir; - if ( init_dir.is_null() ) - { -# ifdef BOOST_POSIX - long path_max = ::pathconf( ".", _PC_PATH_MAX ); - if ( path_max == -1 ) - throw filesystem_error( "initial_directory()" ); - boost::scoped_array - buf( new char[static_cast(path_max)] ); - if ( ::getcwd( buf.get(), static_cast(path_max) ) == 0 ) -# else - DWORD sz; - if ( (sz = ::GetCurrentDirectoryA( 0, static_cast(0) )) == 0 ) - throw filesystem_error( "initial_directory()" ); - boost::scoped_array buf( new char[sz] ); - if ( ::GetCurrentDirectoryA( sz, buf.get() ) == 0 ) -# endif - { throw filesystem_error( "initial_directory()", system_error ); } - init_dir = path( buf.get(), system_specific ); - } - return init_dir; +# ifdef BOOST_POSIX + long path_max = ::pathconf( ".", _PC_PATH_MAX ); + if ( path_max == -1 ) + throw filesystem_error( "initial_path()" ); + boost::scoped_array + buf( new char[static_cast(path_max)] ); + if ( ::getcwd( buf.get(), static_cast(path_max) ) == 0 ) +# else + DWORD sz; + if ( (sz = ::GetCurrentDirectoryA( 0, static_cast(0) )) == 0 ) + throw filesystem_error( "initial_path()" ); + boost::scoped_array buf( new char[sz] ); + if ( ::GetCurrentDirectoryA( sz, buf.get() ) == 0 ) +# endif + { throw filesystem_error( "initial_path()", system_error ); } + return path( buf.get(), system_specific ); + } + + const path & initial_path() + { + static path init_path; + if ( init_path.is_null() ) init_path = current_path(); + return init_path; } } // namespace filesystem