/src/poco/Foundation/include/Poco/Path.h
Line | Count | Source (jump to first uncovered line) |
1 | | // |
2 | | // Path.h |
3 | | // |
4 | | // Library: Foundation |
5 | | // Package: Filesystem |
6 | | // Module: Path |
7 | | // |
8 | | // Definition of the Path class. |
9 | | // |
10 | | // Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. |
11 | | // and Contributors. |
12 | | // |
13 | | // SPDX-License-Identifier: BSL-1.0 |
14 | | // |
15 | | |
16 | | |
17 | | #ifndef Foundation_Path_INCLUDED |
18 | | #define Foundation_Path_INCLUDED |
19 | | |
20 | | |
21 | | #include "Poco/Foundation.h" |
22 | | #include <vector> |
23 | | |
24 | | |
25 | | namespace Poco { |
26 | | |
27 | | |
28 | | class Foundation_API Path |
29 | | /// This class represents filesystem paths in a |
30 | | /// platform-independent manner. |
31 | | /// Unix, Windows and OpenVMS all use a different |
32 | | /// syntax for filesystem paths. |
33 | | /// This class can work with all three formats. |
34 | | /// A path is made up of an optional node name |
35 | | /// (only Windows and OpenVMS), an optional |
36 | | /// device name (also only Windows and OpenVMS), |
37 | | /// a list of directory names and an optional |
38 | | /// filename. |
39 | | { |
40 | | public: |
41 | | enum Style |
42 | | { |
43 | | PATH_UNIX, /// Unix-style path |
44 | | PATH_URI = PATH_UNIX, /// URI-style path, same as Unix-style |
45 | | PATH_WINDOWS, /// Windows-style path |
46 | | PATH_VMS, /// VMS-style path |
47 | | PATH_NATIVE, /// The current platform's native style |
48 | | PATH_GUESS /// Guess the style by examining the path |
49 | | }; |
50 | | |
51 | | using StringVec = std::vector<std::string>; |
52 | | |
53 | | Path(); |
54 | | /// Creates an empty relative path. |
55 | | |
56 | | Path(bool absolute); |
57 | | /// Creates an empty absolute or relative path. |
58 | | |
59 | | Path(const char* path); |
60 | | /// Creates a path from a string. |
61 | | |
62 | | Path(const char* path, Style style); |
63 | | /// Creates a path from a string. |
64 | | |
65 | | Path(const std::string& path); |
66 | | /// Creates a path from a string. |
67 | | |
68 | | Path(const std::string& path, Style style); |
69 | | /// Creates a path from a string. |
70 | | |
71 | | Path(const Path& path); |
72 | | /// Copy constructor |
73 | | |
74 | | Path(Path&& path) noexcept; |
75 | | /// Move constructor. |
76 | | |
77 | | Path(const Path& parent, const std::string& fileName); |
78 | | /// Creates a path from a parent path and a filename. |
79 | | /// The parent path is expected to reference a directory. |
80 | | |
81 | | Path(const Path& parent, const char* fileName); |
82 | | /// Creates a path from a parent path and a filename. |
83 | | /// The parent path is expected to reference a directory. |
84 | | |
85 | | Path(const Path& parent, const Path& relative); |
86 | | /// Creates a path from a parent path and a relative path. |
87 | | /// The parent path is expected to reference a directory. |
88 | | /// The relative path is appended to the parent path. |
89 | | |
90 | | ~Path(); |
91 | | /// Destroys the Path. |
92 | | |
93 | | Path& operator = (const Path& path); |
94 | | /// Assignment operator. |
95 | | |
96 | | Path& operator = (Path&& path) noexcept; |
97 | | /// Move assignment. |
98 | | |
99 | | Path& operator = (const std::string& path); |
100 | | /// Assigns a string containing a path in native format. |
101 | | |
102 | | Path& operator = (const char* path); |
103 | | /// Assigns a string containing a path in native format. |
104 | | |
105 | | void swap(Path& path) noexcept; |
106 | | /// Swaps the path with another one. |
107 | | |
108 | | Path& assign(const std::string& path); |
109 | | /// Assigns a string containing a path in native format. |
110 | | |
111 | | Path& assign(const std::string& path, Style style); |
112 | | /// Assigns a string containing a path. |
113 | | |
114 | | Path& assign(const Path& path); |
115 | | /// Assigns the given path. |
116 | | |
117 | | Path& assign(const char* path); |
118 | | /// Assigns a string containing a path. |
119 | | |
120 | | std::string toString() const; |
121 | | /// Returns a string containing the path in native format. |
122 | | |
123 | | std::string toString(Style style) const; |
124 | | /// Returns a string containing the path in the given format. |
125 | | |
126 | | Path& parse(const std::string& path); |
127 | | /// Same as assign(). |
128 | | |
129 | | Path& parse(const std::string& path, Style style); |
130 | | /// Assigns a string containing a path. |
131 | | |
132 | | bool tryParse(const std::string& path); |
133 | | /// Tries to interpret the given string as a path |
134 | | /// in native format. |
135 | | /// If the path is syntactically valid, assigns the |
136 | | /// path and returns true. Otherwise leaves the |
137 | | /// object unchanged and returns false. |
138 | | |
139 | | bool tryParse(const std::string& path, Style style); |
140 | | /// Tries to interpret the given string as a path, |
141 | | /// according to the given style. |
142 | | /// If the path is syntactically valid, assigns the |
143 | | /// path and returns true. Otherwise leaves the |
144 | | /// object unchanged and returns false. |
145 | | |
146 | | Path& parseDirectory(const std::string& path); |
147 | | /// The resulting path always refers to a directory and |
148 | | /// the filename part is empty. |
149 | | |
150 | | Path& parseDirectory(const std::string& path, Style style); |
151 | | /// The resulting path always refers to a directory and |
152 | | /// the filename part is empty. |
153 | | |
154 | | Path& makeDirectory(); |
155 | | /// If the path contains a filename, the filename is appended |
156 | | /// to the directory list and cleared. Thus the resulting path |
157 | | /// always refers to a directory. |
158 | | |
159 | | Path& makeFile(); |
160 | | /// If the path contains no filename, the last directory |
161 | | /// becomes the filename. |
162 | | |
163 | | Path& makeParent(); |
164 | | /// Makes the path refer to its parent. |
165 | | |
166 | | Path& makeAbsolute(); |
167 | | /// Makes the path absolute if it is relative. |
168 | | /// The current working directory is taken as base directory. |
169 | | |
170 | | Path& makeAbsolute(const Path& base); |
171 | | /// Makes the path absolute if it is relative. |
172 | | /// The given path is taken as base. |
173 | | |
174 | | Path& append(const Path& path); |
175 | | /// Appends the given path. |
176 | | |
177 | | Path& resolve(const Path& path); |
178 | | /// Resolves the given path against the current one. |
179 | | /// |
180 | | /// If the given path is absolute, it replaces the current one. |
181 | | /// Otherwise, the relative path is appended to the current path. |
182 | | |
183 | | bool isAbsolute() const; |
184 | | /// Returns true iff the path is absolute. |
185 | | |
186 | | bool isRelative() const; |
187 | | /// Returns true iff the path is relative. |
188 | | |
189 | | bool isDirectory() const; |
190 | | /// Returns true iff the path references a directory |
191 | | /// (the filename part is empty). |
192 | | |
193 | | bool isFile() const; |
194 | | /// Returns true iff the path references a file |
195 | | /// (the filename part is not empty). |
196 | | |
197 | | Path& setNode(const std::string& node); |
198 | | /// Sets the node name. |
199 | | /// Setting a non-empty node automatically makes |
200 | | /// the path an absolute one. |
201 | | |
202 | | const std::string& getNode() const; |
203 | | /// Returns the node name. |
204 | | |
205 | | Path& setDevice(const std::string& device); |
206 | | /// Sets the device name. |
207 | | /// Setting a non-empty device automatically makes |
208 | | /// the path an absolute one. |
209 | | |
210 | | const std::string& getDevice() const; |
211 | | /// Returns the device name. |
212 | | |
213 | | int depth() const; |
214 | | /// Returns the number of directories in the directory list. |
215 | | |
216 | | const std::string& directory(int n) const; |
217 | | /// Returns the n'th directory in the directory list. |
218 | | /// If n == depth(), returns the filename. |
219 | | |
220 | | const std::string& operator [] (int n) const; |
221 | | /// Returns the n'th directory in the directory list. |
222 | | /// If n == depth(), returns the filename. |
223 | | |
224 | | Path& pushDirectory(const std::string& dir); |
225 | | /// Adds a directory to the directory list. |
226 | | |
227 | | Path& popDirectory(); |
228 | | /// Removes the last directory from the directory list. |
229 | | |
230 | | Path& popFrontDirectory(); |
231 | | /// Removes the first directory from the directory list. |
232 | | |
233 | | Path& setFileName(const std::string& name); |
234 | | /// Sets the filename. |
235 | | |
236 | | const std::string& getFileName() const; |
237 | | /// Returns the filename. |
238 | | |
239 | | Path& setBaseName(const std::string& name); |
240 | | /// Sets the basename part of the filename and |
241 | | /// does not change the extension. |
242 | | |
243 | | std::string getBaseName() const; |
244 | | /// Returns the basename (the filename sans |
245 | | /// extension) of the path. |
246 | | |
247 | | Path& setExtension(const std::string& extension); |
248 | | /// Sets the filename extension. |
249 | | |
250 | | std::string getExtension() const; |
251 | | /// Returns the filename extension. |
252 | | |
253 | | const std::string& version() const; |
254 | | /// Returns the file version. VMS only. |
255 | | |
256 | | Path& clear(); |
257 | | /// Clears all components. |
258 | | |
259 | | Path parent() const; |
260 | | /// Returns a path referring to the path's |
261 | | /// directory. |
262 | | |
263 | | Path absolute() const; |
264 | | /// Returns an absolute variant of the path, |
265 | | /// taking the current working directory as base. |
266 | | |
267 | | Path absolute(const Path& base) const; |
268 | | /// Returns an absolute variant of the path, |
269 | | /// taking the given path as base. |
270 | | |
271 | | static Path forDirectory(const std::string& path); |
272 | | /// Creates a path referring to a directory. |
273 | | |
274 | | static Path forDirectory(const std::string& path, Style style); |
275 | | /// Creates a path referring to a directory. |
276 | | |
277 | | static char separator(); |
278 | | /// Returns the platform's path name separator, which separates |
279 | | /// the components (names) in a path. |
280 | | /// |
281 | | /// On Unix systems, this is the slash '/'. On Windows systems, |
282 | | /// this is the backslash '\'. On OpenVMS systems, this is the |
283 | | /// period '.'. |
284 | | |
285 | | static char pathSeparator(); |
286 | | /// Returns the platform's path separator, which separates |
287 | | /// single paths in a list of paths. |
288 | | /// |
289 | | /// On Unix systems, this is the colon ':'. On Windows systems, |
290 | | /// this is the semicolon ';'. On OpenVMS systems, this is the |
291 | | /// comma ','. |
292 | | |
293 | | static std::string addDirectorySeparator(const std::string& path); |
294 | | /// Adds a separator to the end of a string to create the correct syntax for a path. |
295 | | /// If the source path already has a trailing separator, no separator will be added. |
296 | | /// |
297 | | /// On Unix systems, this is the slash '/'. On Windows systems, |
298 | | /// this is the backslash '\'. On OpenVMS systems, this is the |
299 | | /// period '.'. |
300 | | |
301 | | static std::string addDirectorySeparator(const std::string& path, Style style); |
302 | | /// Adds a separator to the end of a string to create the correct syntax for a path. |
303 | | /// If the source path already has a trailing separator, no separator will be added. |
304 | | /// |
305 | | /// On Unix systems, this is the slash '/'. On Windows systems, |
306 | | /// this is the backslash '\'. On OpenVMS systems, this is the |
307 | | /// period '.'. |
308 | | |
309 | | static std::string self(); |
310 | | /// Return path to the executable file, empty string if failed. |
311 | | /// The path is absolute one. |
312 | | |
313 | | static std::string current(); |
314 | | /// Returns the current working directory. |
315 | | |
316 | | static std::string home(); |
317 | | /// Returns the user's home directory. |
318 | | |
319 | | static std::string configHome(); |
320 | | /// Returns the user's config directory. |
321 | | /// |
322 | | /// On Unix systems, this is the '~/.config/'. On Windows systems, |
323 | | /// this is '%APPDATA%' (typically C:\Users\user\AppData\Roaming). |
324 | | |
325 | | static std::string dataHome(); |
326 | | /// Returns the user's data directory. |
327 | | /// |
328 | | /// On Unix systems, this is the '~/.local/share/'. On Windows systems, |
329 | | /// this is '%LOCALAPPDATA%' (typically C:\Users\user\AppData\Local). |
330 | | |
331 | | static std::string tempHome(); |
332 | | /// Returns the user's temp directory. |
333 | | /// |
334 | | /// On Unix systems, this is the '~/.local/temp/'. |
335 | | |
336 | | static std::string cacheHome(); |
337 | | /// Returns the user's cache directory. |
338 | | /// |
339 | | /// On Unix systems, this is the '~/.cache/'. On Windows systems, |
340 | | /// this is the same as tempHome(). |
341 | | |
342 | | static std::string temp(); |
343 | | /// Returns the temporary directory. |
344 | | |
345 | | static std::string config(); |
346 | | /// Returns the systemwide config directory. |
347 | | /// |
348 | | /// On Unix systems, this is the '/etc/'. |
349 | | |
350 | | static std::string null(); |
351 | | /// Returns the name of the null device. |
352 | | |
353 | | static std::string expand(const std::string& path); |
354 | | /// Expands all environment variables contained in the path. |
355 | | /// |
356 | | /// On Unix, a tilde as first character in the path is |
357 | | /// replaced with the path to user's home directory. |
358 | | |
359 | | static void listRoots(std::vector<std::string>& roots); |
360 | | /// Fills the vector with all filesystem roots available on the |
361 | | /// system. On Unix, there is exactly one root, "/". |
362 | | /// On Windows, the roots are the drive letters. |
363 | | /// On OpenVMS, the roots are the mounted disks. |
364 | | |
365 | | static bool find(StringVec::const_iterator it, StringVec::const_iterator end, const std::string& name, Path& path); |
366 | | /// Searches the file with the given name in the locations (paths) specified |
367 | | /// by it and end. A relative path may be given in name. |
368 | | /// |
369 | | /// If the file is found in one of the locations, the complete |
370 | | /// path of the file is stored in the path given as argument and true is returned. |
371 | | /// Otherwise false is returned and the path argument remains unchanged. |
372 | | |
373 | | static bool find(const std::string& pathList, const std::string& name, Path& path); |
374 | | /// Searches the file with the given name in the locations (paths) specified |
375 | | /// in pathList. The paths in pathList must be delimited by the platform's |
376 | | /// path separator (see pathSeparator()). A relative path may be given in name. |
377 | | /// |
378 | | /// If the file is found in one of the locations, the complete |
379 | | /// path of the file is stored in the path given as argument and true is returned. |
380 | | /// Otherwise false is returned and the path argument remains unchanged. |
381 | | |
382 | | static std::string transcode(const std::string& path); |
383 | | /// On Windows, this function converts a string (usually containing a path) |
384 | | /// encoded in UTF-8 into a string encoded in the current Windows code page. |
385 | | /// |
386 | | /// This function should be used for every string passed as a file name to |
387 | | /// a string stream or fopen(). |
388 | | /// |
389 | | /// On all other platforms, or if POCO has not been compiled with Windows UTF-8 |
390 | | /// support, this function returns the string unchanged. |
391 | | |
392 | | protected: |
393 | | void parseUnix(const std::string& path); |
394 | | void parseWindows(const std::string& path); |
395 | | void parseVMS(const std::string& path); |
396 | | void parseGuess(const std::string& path); |
397 | | std::string buildUnix() const; |
398 | | std::string buildWindows() const; |
399 | | std::string buildVMS() const; |
400 | | |
401 | | private: |
402 | | std::string _node; |
403 | | std::string _device; |
404 | | std::string _name; |
405 | | std::string _version; |
406 | | StringVec _dirs; |
407 | | bool _absolute; |
408 | | }; |
409 | | |
410 | | |
411 | | // |
412 | | // inlines |
413 | | // |
414 | | inline bool Path::isAbsolute() const |
415 | 2.83k | { |
416 | 2.83k | return _absolute; |
417 | 2.83k | } |
418 | | |
419 | | |
420 | | inline bool Path::isRelative() const |
421 | 0 | { |
422 | 0 | return !_absolute; |
423 | 0 | } |
424 | | |
425 | | |
426 | | inline bool Path::isDirectory() const |
427 | 0 | { |
428 | 0 | return _name.empty(); |
429 | 0 | } |
430 | | |
431 | | |
432 | | inline bool Path::isFile() const |
433 | 0 | { |
434 | 0 | return !_name.empty(); |
435 | 0 | } |
436 | | |
437 | | |
438 | | inline Path& Path::parse(const std::string& path) |
439 | 2.83k | { |
440 | 2.83k | return assign(path); |
441 | 2.83k | } |
442 | | |
443 | | |
444 | | inline Path& Path::parse(const std::string& path, Style style) |
445 | 50.4k | { |
446 | 50.4k | return assign(path, style); |
447 | 50.4k | } |
448 | | |
449 | | |
450 | | inline const std::string& Path::getNode() const |
451 | 0 | { |
452 | 0 | return _node; |
453 | 0 | } |
454 | | |
455 | | |
456 | | inline const std::string& Path::getDevice() const |
457 | 0 | { |
458 | 0 | return _device; |
459 | 0 | } |
460 | | |
461 | | |
462 | | inline const std::string& Path::getFileName() const |
463 | 0 | { |
464 | 0 | return _name; |
465 | 0 | } |
466 | | |
467 | | |
468 | | inline int Path::depth() const |
469 | 1.05M | { |
470 | 1.05M | return int(_dirs.size()); |
471 | 1.05M | } |
472 | | |
473 | | |
474 | | inline const std::string& Path::version() const |
475 | 0 | { |
476 | 0 | return _version; |
477 | 0 | } |
478 | | |
479 | | |
480 | | inline Path Path::forDirectory(const std::string& path) |
481 | 0 | { |
482 | 0 | Path p; |
483 | 0 | return p.parseDirectory(path); |
484 | 0 | } |
485 | | |
486 | | |
487 | | inline Path Path::forDirectory(const std::string& path, Style style) |
488 | 0 | { |
489 | 0 | Path p; |
490 | 0 | return p.parseDirectory(path, style); |
491 | 0 | } |
492 | | |
493 | | |
494 | | inline char Path::separator() |
495 | 0 | { |
496 | | #if defined(POCO_OS_FAMILY_VMS) |
497 | | return '.'; |
498 | | #elif defined(POCO_OS_FAMILY_WINDOWS) |
499 | | return '\\'; |
500 | | #else |
501 | 0 | return '/'; |
502 | 0 | #endif |
503 | 0 | } |
504 | | |
505 | | |
506 | | inline char Path::pathSeparator() |
507 | 0 | { |
508 | | #if defined(POCO_OS_FAMILY_VMS) |
509 | | return ','; |
510 | | #elif defined(POCO_OS_FAMILY_WINDOWS) |
511 | | return ';'; |
512 | | #else |
513 | 0 | return ':'; |
514 | 0 | #endif |
515 | 0 | } |
516 | | |
517 | | |
518 | | inline void swap(Path& p1, Path& p2) noexcept |
519 | 0 | { |
520 | 0 | p1.swap(p2); |
521 | 0 | } |
522 | | |
523 | | |
524 | | } // namespace Poco |
525 | | |
526 | | |
527 | | #endif // Foundation_Path_INCLUDED |