directory_iterator simplification

[SVN r16424]
This commit is contained in:
Beman Dawes
2002-11-26 15:51:18 +00:00
parent ecdecd6353
commit 52bb7cd258
3 changed files with 107 additions and 113 deletions

View File

@@ -23,8 +23,8 @@
#include <boost/config.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/smart_ptr.hpp>
#include <boost/iterator_adaptors.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/iterator.hpp>
#include <string>
@@ -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 <class IteratorAdaptor>
typename IteratorAdaptor::reference
dereference(const IteratorAdaptor& x) const
{ return x.base().deref(); }
template <class IteratorAdaptor>
void increment(IteratorAdaptor& x)
{ x.base().inc(); }
template <class IteratorAdaptor1, class IteratorAdaptor2>
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

View File

@@ -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 --------------------------------------------------------//

View File

@@ -27,6 +27,7 @@
#include <boost/config.hpp>
#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/exception.hpp>
#include <boost/scoped_array.hpp>
//#include <iostream>
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<char>
buf( new char[static_cast<std::size_t>(path_max)] );
if ( ::getcwd( buf.get(), static_cast<std::size_t>(path_max) ) == 0 )
# else
DWORD sz;
if ( (sz = ::GetCurrentDirectoryA( 0, static_cast<char*>(0) )) == 0 )
throw filesystem_error( "initial_directory()" );
boost::scoped_array<char> 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<char>
buf( new char[static_cast<std::size_t>(path_max)] );
if ( ::getcwd( buf.get(), static_cast<std::size_t>(path_max) ) == 0 )
# else
DWORD sz;
if ( (sz = ::GetCurrentDirectoryA( 0, static_cast<char*>(0) )) == 0 )
throw filesystem_error( "initial_path()" );
boost::scoped_array<char> 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