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