E-MailRelay

gpath.h
Go to the documentation of this file.
1//
2// Copyright (C) 2001-2021 Graeme Walker <graeme_walker@users.sourceforge.net>
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/// \file gpath.h
19///
20
21#ifndef G_PATH_H
22#define G_PATH_H
23
24#include "gdef.h"
25#include "gstrings.h"
26#include <string>
27#include <iostream>
28#include <initializer_list>
29
30 namespace G
31{
32 class Path ;
33 class PathImp ;
34}
35
36//| \class G::Path
37/// A Path object represents a file system path. The class is concerned with
38/// path syntax, not file system i/o.
39///
40/// A full path is made up of a root, a set of directories, and a filename. The
41/// posix root is just a forward slash, but on Windows the root can be complex,
42/// possibly including non-splitting separator characters. The filename may have
43/// an extension part, which is to the right of the right-most dot.
44///
45/// The path separator is used between directories and filename, but only
46/// between the root and the first directory if the root does not itself end in
47/// a separator character.
48///
49/// A windows drive-letter root may end with a separator character or not; if
50/// there is no separator character at the end of the drive-letter root then
51/// the path is relative to the drive's current working directory.
52///
53/// Path components of "." are ignored by simple(), basename(), and dirname().
54/// Path components of ".." are retained but can be eliminated if they are
55/// collapsed(). Path components of "." are eliminated by split(), except
56/// in the degenerate case.
57///
58/// This class is agnostic on the choice of UTF-8 or eight-bit characters since
59/// the delimiters are all seven-bit ascii.
60///
61/// Both posix and windows behaviours are available at run-time; the default
62/// behaviour is the native behaviour, but this can be overridden, typically
63/// for testing purposes.
64///
65/// The posix path separator character is the forward-slash; on Windows it is a
66/// back-slash, but with all forward-slashes converted to back-slashes
67/// immediately on input.
68///
69/// \see G::File, G::Directory
70///
71 class G::Path
72{
73 public:
74 Path() ;
75 ///< Default constructor for a zero-length path.
76 ///< Postcondition: empty()
77
78 Path( const std::string & path ) ;
79 ///< Implicit constructor from a string.
80
81 Path( const char * path ) ;
82 ///< Implicit constructor from a c-style string.
83
84 Path( const Path & path , const std::string & tail ) ;
85 ///< Constructor with an implicit pathAppend().
86
87 Path( const Path & path , const std::string & tail_1 , const std::string & tail_2 ) ;
88 ///< Constructor with two implicit pathAppend()s.
89
90 Path( const Path & path , const std::string & tail_1 , const std::string & tail_2 , const std::string & tail_3 ) ;
91 ///< Constructor with three implicit pathAppend()s.
92
93 Path( std::initializer_list<std::string> ) ;
94 ///< Constructor with implicit pathAppend()s. (Recall that this
95 ///< overload will be strongly preferred when using curly-brace
96 ///< initialisation.)
97
98 std::size_t size() const noexcept ;
99 ///< Returns the length of the path string.
100
101 bool empty() const noexcept ;
102 ///< Returns true if size() is zero.
103
104 std::string str() const ;
105 ///< Returns the path string.
106
107 const char * cstr() const noexcept ;
108 ///< Returns the path string.
109
110 bool simple() const ;
111 ///< Returns true if the path has a single component (ignoring "." parts),
112 ///< ie. the dirname() is empty.
113
114 std::string basename() const ;
115 ///< Returns the rightmost part of the path, ignoring "." parts.
116 ///< For a directory path this may be "..", but see also collapsed().
117
118 Path dirname() const ;
119 ///< Returns the path without the rightmost part, ignoring "." parts.
120 ///< For simple() paths the empty path is returned.
121
122 std::string extension() const ;
123 ///< Returns the path's basename extension, ie. anything
124 ///< after the rightmost dot. Returns the zero-length
125 ///< string if there is none.
126
127 Path withExtension( const std::string & ext ) const ;
128 ///< Returns the path with the new basename extension.
129 ///< Any previous extension is replaced. The extension
130 ///< should not normally have a leading dot and it
131 ///< should not be the empty string.
132
133 Path withoutExtension() const ;
134 ///< Returns a path without the basename extension, if any.
135 ///< As a special case, a basename() that starts with a dot
136 ///< is replaced by a single dot. Prefer withExtension()
137 ///< where appropriate to avoid this.
138
139 bool isAbsolute() const ;
140 ///< Returns !isRelative().
141
142 bool isRelative() const ;
143 ///< Returns true if the path is a relative path or empty().
144
145 void pathAppend( const std::string & tail ) ;
146 ///< Appends a filename or a relative path to this path.
147
148 StringArray split() const ;
149 ///< Spits the path into a list of component parts (ignoring "." parts
150 ///< unless the whole path is ".").
151
152 static Path join( const StringArray & parts ) ;
153 ///< Builds a path from a set of parts. Note that part boundaries
154 ///< are not necessarily preserved once they have been join()ed
155 ///< into a path.
156
157 static Path join( const Path & p1 , const Path & p2 ) ;
158 ///< Joins two paths together. The second should be a relative path.
159
160 static Path difference( const Path & p1 , const Path & p2 ) ;
161 ///< Returns the relative path from p1 to p2. Returns the empty
162 ///< path if p2 is not under p1. Returns "." if p1 and p2 are the
163 ///< same. Input paths are collapsed(). Empty input paths are
164 ///< treated as ".".
165
166 Path collapsed() const ;
167 ///< Returns the path with "foo/.." and "." parts removed, so far
168 ///< as is possible without changing the meaning of the path.
169 ///< Parts like "../foo" at the beginning of the path, or immediately
170 ///< following the root, are not removed.
171
172 static Path nullDevice() ;
173 ///< Returns the path of the "/dev/null" special file, or equivalent.
174
175 void swap( Path & other ) noexcept ;
176 ///< Swaps this with other.
177
178 bool operator==( const Path & path ) const ;
179 ///< Comparison operator.
180
181 bool operator!=( const Path & path ) const ;
182 ///< Comparison operator.
183
184 static void setPosixStyle() ;
185 ///< Sets posix mode for testing purposes.
186
187 static void setWindowsStyle() ;
188 ///< Sets windows mode for testing purposes.
189
190 static bool less( const Path & a , const Path & b ) ;
191 ///< Compares two paths, with simple eight-bit lexicographical
192 ///< comparisons of each path component. This is slightly different
193 ///< from a lexicographical comparison of the compete strings
194 ///< (eg. "a/b" compared to "a./b"), and it is not suitable for
195 ///< UTF-8 paths.
196
197private:
198 friend class G::PathImp ;
199 std::string m_str ;
200} ;
201
202inline
203 bool G::Path::empty() const noexcept
204{
205 return m_str.empty() ;
206}
207
208 inline
209std::size_t G::Path::size() const noexcept
210{
211 return m_str.size() ;
212}
213
214 inline
215std::string G::Path::str() const
216{
217 return m_str ;
218}
219
220 inline
221 const char * G::Path::cstr() const noexcept
222{
223 return m_str.c_str() ;
224}
225
226 namespace G
227{
228 inline
229 std::ostream & operator<<( std::ostream & stream , const Path & path )
230 {
231 return stream << path.str() ;
232 }
233
234 inline
235 Path & operator+=( Path & p , const std::string & str )
236 {
237 p.pathAppend( str ) ;
238 return p ;
239 }
240
241 inline
242 Path operator+( const Path & p , const std::string & str )
243 {
244 return Path( p , str ) ;
245 }
246
247 inline
248 void swap( Path & p1 , Path & p2 ) noexcept
249 {
250 p1.swap( p2 ) ;
251 }
252}
253
254#endif
G::PathImp
A private implementation class used by G::Path providing a set of static methods.
Definition: gpath.cpp:36
G::Path
A Path object represents a file system path.
Definition: gpath.h:72
G::Path::swap
void swap(Path &other) noexcept
Swaps this with other.
Definition: gpath.cpp:472
G::Path::less
static bool less(const Path &a, const Path &b)
Compares two paths, with simple eight-bit lexicographical comparisons of each path component.
Definition: gpath.cpp:483
G::Path::isRelative
bool isRelative() const
Returns true if the path is a relative path or empty().
Definition: gpath.cpp:323
G::Path::join
static Path join(const StringArray &parts)
Builds a path from a set of parts.
Definition: gpath.cpp:408
G::Path::cstr
const char * cstr() const noexcept
Returns the path string.
Definition: gpath.h:221
G::Path::basename
std::string basename() const
Returns the rightmost part of the path, ignoring "." parts.
Definition: gpath.cpp:328
G::Path::withoutExtension
Path withoutExtension() const
Returns a path without the basename extension, if any.
Definition: gpath.cpp:346
G::Path::isAbsolute
bool isAbsolute() const
Returns !isRelative().
Definition: gpath.cpp:318
G::Path::dirname
Path dirname() const
Returns the path without the rightmost part, ignoring "." parts.
Definition: gpath.cpp:336
G::Path::extension
std::string extension() const
Returns the path's basename extension, ie.
Definition: gpath.cpp:391
G::Path::simple
bool simple() const
Returns true if the path has a single component (ignoring "." parts), ie.
Definition: gpath.cpp:313
G::Path::nullDevice
static Path nullDevice()
Returns the path of the "/dev/null" special file, or equivalent.
Definition: gpath.cpp:308
G::Path::pathAppend
void pathAppend(const std::string &tail)
Appends a filename or a relative path to this path.
Definition: gpath.cpp:375
G::Path::withExtension
Path withExtension(const std::string &ext) const
Returns the path with the new basename extension.
Definition: gpath.cpp:364
G::Path::collapsed
Path collapsed() const
Returns the path with "foo/.." and "." parts removed, so far as is possible without changing the mean...
Definition: gpath.cpp:433
G::Path::setPosixStyle
static void setPosixStyle()
Sets posix mode for testing purposes.
Definition: gpath.cpp:247
G::Path::size
std::size_t size() const noexcept
Returns the length of the path string.
Definition: gpath.h:209
G::Path::str
std::string str() const
Returns the path string.
Definition: gpath.h:215
G::Path::setWindowsStyle
static void setWindowsStyle()
Sets windows mode for testing purposes.
Definition: gpath.cpp:252
G::Path::split
StringArray split() const
Spits the path into a list of component parts (ignoring "." parts unless the whole path is "....
Definition: gpath.cpp:400
G::Path::empty
bool empty() const noexcept
Returns true if size() is zero.
Definition: gpath.h:203
G::Path::Path
Path()
Default constructor for a zero-length path.
G::Path::difference
static Path difference(const Path &p1, const Path &p2)
Returns the relative path from p1 to p2.
Definition: gpath.cpp:493
gstrings.h
G
Low-level classes.
Definition: galign.h:28
G::StringArray
std::vector< std::string > StringArray
A std::vector of std::strings.
Definition: gstrings.h:31