mirror of
https://github.com/boostorg/filesystem.git
synced 2026-01-30 07:52:08 +00:00
directory_iterator simplification
[SVN r16424]
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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 --------------------------------------------------------//
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user