VideoTools
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
gfiletree.cpp
Go to the documentation of this file.
1 //
2 // Copyright (C) 2017 Graeme Walker
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
16 // ===
17 //
18 // gfiletree.cpp
19 //
20 
21 #include "gdef.h"
22 #include "gfiletree.h"
23 #include "gstrings.h"
24 #include "gdebug.h"
25 #include <algorithm>
26 
28  m_moved(false) ,
29  m_callback(nullptr)
30 {
31 }
32 
33 G::FileTree::FileTree( const G::Path & root , DirectoryTreeCallback * callback ) :
34  m_moved(true) ,
35  m_root(root.collapsed()) ,
36  m_p(m_root,false,callback) ,
37  m_callback(callback)
38 {
39  const DirectoryTree end ;
40  while( m_p != end && (*m_p).m_is_dir )
41  ++m_p ;
42 }
43 
44 void G::FileTree::swap( FileTree & other )
45 {
46  using std::swap ;
47  swap( m_moved , other.m_moved ) ;
48  swap( m_root , other.m_root ) ;
49  swap( m_p , other.m_p ) ;
50  swap( m_callback , other.m_callback ) ;
51 }
52 
53 void G::FileTree::reroot( const G::Path & root )
54 {
55  m_root = root.collapsed() ;
56  m_moved = true ;
57  m_p = DirectoryTree( m_root , false , m_callback ) ;
58  const DirectoryTree end ;
59  while( m_p != end && (*m_p).m_is_dir )
60  ++m_p ;
61 }
62 
64 {
65  return m_root ;
66 }
67 
69 {
70  return m_p == DirectoryTree() ? G::Path() : (*m_p).m_path ;
71 }
72 
74 {
75  if( m_moved )
76  {
77  m_moved = false ;
78  }
79  else
80  {
81  const DirectoryTree end ;
82  if( m_p != end )
83  {
84  ++m_p ;
85  while( m_p != end && (*m_p).m_is_dir )
86  ++m_p ;
87  }
88  }
89  return current() ;
90 }
91 
92 bool G::FileTree::reposition( const G::Path & path )
93 {
94  int rc = reposition( path , 0 ) ;
95  return rc == 0 ;
96 }
97 
98 int G::FileTree::reposition( const G::Path & path , int )
99 {
100  G::Path relative_path = G::Path::difference( m_root , path ) ;
101  if( relative_path == G::Path() )
102  return 1 ; // out-of-tree
103 
104  G::StringArray parts = relative_path.split() ;
105  if( parts.size() == 1U && parts.at(0U) == "." )
106  parts.clear() ;
107 
108  DirectoryTree p( m_root , m_p.reversed() , m_callback ) ;
109  const DirectoryTree end ;
110  size_t i = 0U ; for( ; i < parts.size() ; i++ )
111  {
112  const std::string & part = parts.at(i) ;
113  G_DEBUG( "G::FileTree::reposition: part: [" << part << "]" ) ;
114  if( p != end && (*p).m_is_dir && p.down( part , true ) )
115  ;
116  else
117  break ;
118  }
119 
120  if( p != end && i < parts.size() ) // over-specified
121  ++p ;
122 
123  while( p != end && (*p).m_is_dir )
124  ++p ;
125 
126  if( p == end )
127  return 2 ; // off-the-end
128 
129  m_p = p ;
130  m_moved = true ;
131  return 0 ;
132 }
133 
135 {
136  // use a reversed iterator to get the last position
137  const DirectoryTree end ;
138  bool is_reversed = m_p.reversed() ;
139  DirectoryTree p( m_root , !is_reversed , m_callback ) ;
140  while( p != end && (*p).m_is_dir )
141  ++p ;
142 
143  bool changed = m_p != p ;
144  m_p.swap( p ) ;
145  m_p.reverse( is_reversed ) ;
146  m_moved = true ;
147  return changed ;
148 }
149 
151 {
152  // use a brand new iterator to get the first position
153  const DirectoryTree end ;
154  DirectoryTree p( m_root , m_p.reversed() , m_callback ) ;
155  while( p != end && (*p).m_is_dir )
156  ++p ;
157 
158  bool changed = m_p != p ;
159  m_p.swap( p ) ;
160  m_moved = true ;
161  return changed ;
162 }
163 
164 void G::FileTree::reverse( bool in_reverse )
165 {
166  m_p.reverse( in_reverse ) ;
167 }
168 
170 {
171  return m_p.reversed() ;
172 }
173 
174 bool G::FileTree::moved() const
175 {
176  return m_moved ;
177 }
178 
179 /// \file gfiletree.cpp
A class for walking files in a directory tree, with repositioning.
Definition: gfiletree.h:50
A directory tree iterator for sorted, depth-first traversal of files and directories.
FileTree()
Default contructor for an empty tree.
Definition: gfiletree.cpp:27
std::vector< std::string > StringArray
A std::vector of std::strings.
Definition: gstrings.h:33
void reroot(const G::Path &root)
Resets the root, as if newly constructed.
Definition: gfiletree.cpp:53
bool reposition(const G::Path &path)
Repositions the iterator within the current tree, at or after the given position. ...
Definition: gfiletree.cpp:92
void reverse(bool=true)
Iterate in reverse, and reposition() to at-or-before rather than at-or-after.
Definition: gfiletree.cpp:164
void swap(FileTree &other)
Swaps this and other.
Definition: gfiletree.cpp:44
static Path difference(const Path &p1, const Path &p2)
Returns the relative path from p1 to p2.
Definition: gpath.cpp:483
bool reversed() const
Returns true if currently reverse()d.
Definition: gfiletree.cpp:169
G::Path current() const
Returns the current path.
Definition: gfiletree.cpp:68
StringArray split() const
Spits the path into a list of component parts (ignoring "." parts unless the whole path is "...
Definition: gpath.cpp:382
bool moved() const
Returns true after construction, reroot(), first(), last() or a successful reposition().
Definition: gfiletree.cpp:174
Path collapsed() const
Returns the path with "foo/.." and "." parts removed, so far as is possible without changing the mean...
Definition: gpath.cpp:415
void swap(DirectoryTree &other)
Swaps this and other.
bool first()
Repositions to the root() position, or to the last position if currently reversed().
Definition: gfiletree.cpp:150
bool reversed() const
Returns the current reversal state.
G::Path next()
Moves to the next file in the tree, depth first, and returns the path.
Definition: gfiletree.cpp:73
G::Path root() const
Returns the current root, as passed to the constructor or reroot().
Definition: gfiletree.cpp:63
A callback interface to allow G::DirectoryTree to ignore paths.
A Path object represents a file system path.
Definition: gpath.h:72
bool last()
Repositions to the last position (so that next() will soon go off the end), or to the root() if curre...
Definition: gfiletree.cpp:134