37 return a.m_name < b.m_name ;
41 explicit CompareNames(
bool reverse ) : m_reverse(reverse) {}
44 return m_reverse ? compare_names( b , a ) : compare_names( a , b ) ;
48 template <
typename T,
typename C>
49 bool is__sorted( T p , T end , C cmp )
52 for(
bool first =
true ; p != end ; ++p , first = false )
54 if( !first && !cmp(*prev,*p) )
80 item.m_is_dir = isDir(path) ;
86 m_stack.push_back( Context() ) ;
87 Context & context = m_stack.back() ;
89 context.m_list.push_back( item ) ;
90 context.m_p = context.m_list.begin() ;
91 context.m_end = context.m_list.end() ;
96 G::DirectoryTree::FileList G::DirectoryTree::readFileList()
const
103 G_ASSERT( is__sorted(file_list.begin(),file_list.end(),compare_names) ) ;
104 filter( file_list , m_stack.size() ) ;
110 G_ASSERT( !m_stack.empty() ) ;
113 if( (*m_stack.back().m_p).m_is_dir )
115 file_list = readFileList() ;
117 std::reverse( file_list.begin() , file_list.end() ) ;
120 if( file_list.empty() )
122 while( !m_stack.empty() )
124 ++m_stack.back().m_p ;
125 if( m_stack.back().m_p == m_stack.back().m_end )
133 m_stack.push_back( Context() ) ;
134 Context & context = m_stack.back() ;
135 context.m_list.swap( file_list ) ;
136 context.m_p = context.m_list.begin() ;
137 context.m_end = context.m_list.end() ;
144 if( m_stack.size() != other.m_stack.size() )
146 else if( m_stack.empty() )
149 (*m_stack.back().m_p).m_path == (*other.m_stack.back().m_p).m_path ;
154 return !( *
this == other ) ;
159 G_ASSERT( !m_stack.empty() ) ;
160 return *m_stack.back().m_p ;
163 bool G::DirectoryTree::isDir(
const Path & path )
171 G_ASSERT( !m_stack.empty() ) ;
172 return m_stack.size() - 1U ;
176 m_stack(other.m_stack) ,
177 m_reverse(other.m_reverse) ,
178 m_callback(other.m_callback)
180 Stack::iterator other_p = (
const_cast<DirectoryTree&
>(other)).m_stack.begin() ;
181 for( Stack::iterator this_p = m_stack.begin() ; this_p != m_stack.end() ; ++this_p , ++other_p )
183 (*this_p).m_p = (*this_p).m_list.begin() ;
184 (*this_p).m_end = (*this_p).m_list.end() ;
185 std::advance( (*this_p).m_p , std::distance((*other_p).m_list.begin(),(*other_p).m_p) ) ;
191 m_stack.swap( other.m_stack ) ;
192 std::swap( m_reverse , other.m_reverse ) ;
193 std::swap( m_callback , other.m_callback ) ;
205 typedef std::pair<FileList::iterator,FileList::iterator> Range ;
206 G_ASSERT( !m_stack.empty() ) ;
207 G_ASSERT( (*m_stack.back().m_p).m_is_dir ) ;
209 FileList file_list = readFileList() ;
212 std::reverse( file_list.begin() , file_list.end() ) ;
216 G_ASSERT( is__sorted(file_list.begin(),file_list.end(),CompareNames(m_reverse)) ) ;
217 Range range = std::equal_range( file_list.begin() , file_list.end() , item , CompareNames(m_reverse) ) ;
218 if( at_or_after && range.first == file_list.end() )
220 while( !m_stack.empty() )
222 ++m_stack.back().m_p ;
223 if( m_stack.back().m_p == m_stack.back().m_end )
230 else if( at_or_after || range.first != range.second )
232 m_stack.push_back( Context() ) ;
233 Context & context = m_stack.back() ;
234 context.m_list.swap( file_list ) ;
235 context.m_p = range.first ;
236 context.m_end = context.m_list.end() ;
247 G_ASSERT( !m_stack.empty() ) ;
253 if( m_reverse != in_reverse )
255 m_reverse = in_reverse ;
256 for( Stack::iterator stack_p = m_stack.begin() ; stack_p != m_stack.end() ; ++stack_p )
258 Context & context = *stack_p ;
259 size_t pos = std::distance( context.m_list.begin() , context.m_p ) ;
260 std::reverse( context.m_list.begin() , context.m_list.end() ) ;
261 context.m_p = context.m_list.begin() ;
262 context.m_end = context.m_list.end() ;
263 std::advance( context.m_p , context.m_list.size()-pos-1 ) ;
268 void G::DirectoryTree::filter( FileList & list ,
size_t depth )
const
270 for( FileList::iterator p = list.begin() ; p != list.end() ; )
272 if( ignore(*p,depth) )
273 p = list.erase( p ) ;
279 bool G::DirectoryTree::ignore(
const FileItem & item ,
size_t depth )
const
282 return m_callback->directoryTreeIgnore( item , depth ) ;
294 G::DirectoryTreeCallback::~DirectoryTreeCallback()
void reverse(bool in_reverse=true)
Changes the reversal state, returning the previous value.
DirectoryTree & operator++()
Pre-increment operator. Moves to the next file or directory.
A directory-entry item for G::DirectoryList.
A directory tree iterator for sorted, depth-first traversal of files and directories.
std::string basename() const
Returns the rightmost part of the path, ignoring "." parts.
A class which acquires the process's special privileges on construction and releases them on destruct...
bool operator==(const DirectoryTree &) const
Comparison operator.
void readAll(const Path &dir)
An initialiser that is to be used after default construction.
bool operator!=(const DirectoryTree &) const
Comparison operator.
bool valid(bool for_creating_files=false) const
Returns true if the object represents a valid directory.
An encapsulation of a file system directory that allows for iterating through the set of contained fi...
DirectoryTree()
Default contructor for an off-the-end iterator.
const DirectoryList::Item & operator*() const
Dereference operator yielding a G::DirectoryList::Item.
static bool exists(const Path &file)
Returns true if the file (directory, device etc.) exists.
DirectoryTree & operator=(const DirectoryTree &)
Assignment operator.
void swap(DirectoryTree &other)
Swaps this and other.
bool down(const std::string &name, bool at_or_after=false)
Moves deeper into the directory tree, with a precondition that the iterator currently points to a dir...
bool reversed() const
Returns the current reversal state.
size_t depth() const
Returns the nesting depth compared to the root.
A callback interface to allow G::DirectoryTree to ignore paths.
A Path object represents a file system path.
void up()
Moves up to the parent directory.