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 	typedef std::vector<std::string> StringVec;
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);
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 current();
294 		/// Returns the current working directory.
295 
296 	static std::string home();
297 		/// Returns the user's home directory.
298 
299 	static std::string configHome();
300 		/// Returns the user's config directory.
301 		///
302 		/// On Unix systems, this is the '~/.config/'. On Windows systems,
303 		/// this is '%APPDATA%'.
304 
305 	static std::string dataHome();
306 		/// Returns the user's data directory.
307 		///
308 		/// On Unix systems, this is the '~/.local/share/'. On Windows systems,
309 		/// this is '%APPDATA%'.
310 
311 	static std::string tempHome();
312 		/// Returns the user's temp directory.
313 		///
314 		/// On Unix systems, this is the '~/.local/temp/'.
315 
316 	static std::string cacheHome();
317 		/// Returns the user's cache directory.
318 		///
319 		/// On Unix systems, this is the '~/.cache/'. On Windows systems,
320 		/// this is '%APPDATA%'.
321 
322 	static std::string temp();
323 		/// Returns the temporary directory.
324 
325 	static std::string config();
326 		/// Returns the systemwide config directory.
327 		///
328 		/// On Unix systems, this is the '/etc/'.
329 
330 	static std::string null();
331 		/// Returns the name of the null device.
332 
333 	static std::string expand(const std::string& path);
334 		/// Expands all environment variables contained in the path.
335 		///
336 		/// On Unix, a tilde as first character in the path is
337 		/// replaced with the path to user's home directory.
338 
339 	static void listRoots(std::vector<std::string>& roots);
340 		/// Fills the vector with all filesystem roots available on the
341 		/// system. On Unix, there is exactly one root, "/".
342 		/// On Windows, the roots are the drive letters.
343 		/// On OpenVMS, the roots are the mounted disks.
344 
345 	static bool find(StringVec::const_iterator it, StringVec::const_iterator end, const std::string& name, Path& path);
346 		/// Searches the file with the given name in the locations (paths) specified
347 		/// by it and end. A relative path may be given in name.
348 		///
349 		/// If the file is found in one of the locations, the complete
350 		/// path of the file is stored in the path given as argument and true is returned.
351 		/// Otherwise false is returned and the path argument remains unchanged.
352 
353 	static bool find(const std::string& pathList, const std::string& name, Path& path);
354 		/// Searches the file with the given name in the locations (paths) specified
355 		/// in pathList. The paths in pathList must be delimited by the platform's
356 		/// path separator (see pathSeparator()). A relative path may be given in name.
357 		///
358 		/// If the file is found in one of the locations, the complete
359 		/// path of the file is stored in the path given as argument and true is returned.
360 		/// Otherwise false is returned and the path argument remains unchanged.
361 
362 	static std::string transcode(const std::string& path);
363 		/// On Windows, this function converts a string (usually containing a path)
364 		/// encoded in UTF-8 into a string encoded in the current Windows code page.
365 		///
366 		/// This function should be used for every string passed as a file name to
367 		/// a string stream or fopen().
368 		///
369 		/// On all other platforms, or if POCO has not been compiled with Windows UTF-8
370 		/// support, this function returns the string unchanged.
371 
372 protected:
373 	void parseUnix(const std::string& path);
374 	void parseWindows(const std::string& path);
375 	void parseVMS(const std::string& path);
376 	void parseGuess(const std::string& path);
377 	std::string buildUnix() const;
378 	std::string buildWindows() const;
379 	std::string buildVMS() const;
380 
381 private:
382 	std::string _node;
383 	std::string _device;
384 	std::string _name;
385 	std::string _version;
386 	StringVec   _dirs;
387 	bool        _absolute;
388 };
389 
390 
391 //
392 // inlines
393 //
isAbsolute()394 inline bool Path::isAbsolute() const
395 {
396 	return _absolute;
397 }
398 
399 
isRelative()400 inline bool Path::isRelative() const
401 {
402 	return !_absolute;
403 }
404 
405 
isDirectory()406 inline bool Path::isDirectory() const
407 {
408 	return _name.empty();
409 }
410 
411 
isFile()412 inline bool Path::isFile() const
413 {
414 	return !_name.empty();
415 }
416 
417 
parse(const std::string & path)418 inline Path& Path::parse(const std::string& path)
419 {
420 	return assign(path);
421 }
422 
423 
parse(const std::string & path,Style style)424 inline Path& Path::parse(const std::string& path, Style style)
425 {
426 	return assign(path, style);
427 }
428 
429 
getNode()430 inline const std::string& Path::getNode() const
431 {
432 	return _node;
433 }
434 
435 
getDevice()436 inline const std::string& Path::getDevice() const
437 {
438 	return _device;
439 }
440 
441 
getFileName()442 inline const std::string& Path::getFileName() const
443 {
444 	return _name;
445 }
446 
447 
depth()448 inline int Path::depth() const
449 {
450 	return int(_dirs.size());
451 }
452 
453 
version()454 inline const std::string& Path::version() const
455 {
456 	return _version;
457 }
458 
459 
forDirectory(const std::string & path)460 inline Path Path::forDirectory(const std::string& path)
461 {
462 	Path p;
463 	return p.parseDirectory(path);
464 }
465 
466 
forDirectory(const std::string & path,Style style)467 inline Path Path::forDirectory(const std::string& path, Style style)
468 {
469 	Path p;
470 	return p.parseDirectory(path, style);
471 }
472 
473 
separator()474 inline char Path::separator()
475 {
476 #if defined(POCO_OS_FAMILY_VMS)
477 	return '.';
478 #elif defined(POCO_OS_FAMILY_WINDOWS)
479 	return '\\';
480 #else
481 	return '/';
482 #endif
483 }
484 
485 
pathSeparator()486 inline char Path::pathSeparator()
487 {
488 #if defined(POCO_OS_FAMILY_VMS)
489 	return ',';
490 #elif defined(POCO_OS_FAMILY_WINDOWS)
491 	return ';';
492 #else
493 	return ':';
494 #endif
495 }
496 
497 
swap(Path & p1,Path & p2)498 inline void swap(Path& p1, Path& p2)
499 {
500 	p1.swap(p2);
501 }
502 
503 
504 } // namespace Poco
505 
506 
507 #endif // Foundation_Path_INCLUDED
508