path.h
Go to the documentation of this file.
1 // ===========================================================================
2 // Copyright (c) 2011-2012 University of Pennsylvania
3 // Copyright (c) 2013-2016 Andreas Schuh
4 // All rights reserved.
5 //
6 // See COPYING file for license information or visit
7 // https://cmake-basis.github.io/download.html#license
8 // ===========================================================================
9 
10 /**
11  * @file os/path.h
12  * @brief File/directory path related functions.
13  *
14  * The implementations provided by this module are in particular related to the
15  * manipulation of and interaction with file (and directory) paths. These
16  * implementations are meant to be simple and therefore focus on non-multibyte
17  * path strings only. They were motivated by the os.path module of Python, though,
18  * they are no exact replicates of these functions. The path module which is
19  * part of the BASIS utilities for Python, on the other side, provides the same
20  * extended functionality.
21  */
22 
23 #pragma once
24 #ifndef _BASIS_OS_PATH_H
25 #define _BASIS_OS_PATH_H
26 
27 
28 #include <set>
29 #include <vector>
30 #include <string>
31 
32 
33 /// @addtogroup BasisCxxUtilities
34 /// @{
35 
36 
37 namespace basis { namespace os { namespace path {
38 
39 
40 // ===========================================================================
41 // representation
42 // ===========================================================================
43 
44 /**
45  * @brief Determine if a given character is a path separator.
46  *
47  * @param [in] c Character.
48  *
49  * @returns True if @p c is a path separator on this platform and false otherwise.
50  */
51 bool issep(char c);
52 
53 /**
54  * @brief Normalize path, i.e., remove occurences of "./", duplicate slashes,...
55  *
56  * This function removes single periods enclosed by slashes (or backslashes),
57  * duplicate slashes (or backslashes), and further tries to reduce the
58  * number of parent directory references. Moreover, on Windows, it replaces
59  * slashes with backslashes.
60  *
61  * For example, on Windows, "../bla//.//.\bla\\\\\bla/../.." is convert to "..\bla".
62  * On Unix, it is converted to "..". Note that on Unix, ".\bla\\\\\bla" is a
63  * directory name.
64  *
65  * @param [in] path Path.
66  *
67  * @returns Normalized path.
68  */
69 std::string normpath(const std::string& path);
70 
71 /**
72  * @brief Convert path to Posix (e.g., Unix, Mac OS) representation.
73  *
74  * This function first converts backward slashes to forward slashes and then
75  * performs the same normalization as normpath() does on Posix systems.
76  *
77  * @param [in] path Path.
78  *
79  * @returns Normalized Posix path.
80  *
81  * @sa normpath()
82  * @sa ntpath()
83  */
84 std::string posixpath(const std::string& path);
85 
86 /**
87  * @brief Convert path to Windows representation.
88  *
89  * This function first converts forward slashes to backward slashes and then
90  * performs the same normalization as normpath() does on Windows.
91  *
92  * @param [in] path Path.
93  *
94  * @returns Normalized Windows path.
95  *
96  * @sa normpath)
97  * @sa posixpath()
98  */
99 std::string ntpath(const std::string& path);
100 
101 // ===========================================================================
102 // components
103 // ===========================================================================
104 
105 /**
106  * @brief Split path into two parts.
107  *
108  * This function splits a path into its head and tail. Trailing slashes are
109  * stripped from head unless it is the root. See the following table for an
110  * illustration:
111  @verbatim
112  path | head | tail
113  -------------------------+-------+---------------+-------------
114  "/" | "/" | ""
115  "/usr/bin" | "/usr" | "bin"
116  "/home/user/info.txt" | "/home/user" | "info.txt"
117  "word.doc" | "" | "word.doc"
118  "../word.doc" | ".." | "word.doc"
119  "C:/" | "C:/" | ""
120  "C:" | "C:" | ""
121  "C:/WINDOWS/regedit.exe" | "C:/WINDOWS" | "regedit.exe"
122  "d:\data" | "d:/" | "data"
123  "/usr/local/" | "/usr/local" | ""
124  @endverbatim
125  * In all cases, join(head, tail) returns a path to the same location as path
126  * (but the strings may differ).
127  *
128  * @param [in] path Path.
129  * @param [out] head Head part of path.
130  * @param [out] tail Tail part of path.
131  *
132  * @sa splitdrive()
133  * @sa splitext()
134  * @sa dirname()
135  * @sa basename()
136  */
137 void split(const std::string& path, std::string& head, std::string& tail);
138 
139 /**
140  * @brief Split path into two parts.
141  *
142  * @returns Tuple of (head, tail), i.e., returns always a vector of size 2.
143  *
144  * @sa split(const std::string&, std::string&, std::string&)
145  */
146 std::vector<std::string> split(const std::string& path);
147 
148 /**
149  * @brief Get drive specification of Windows path.
150  *
151  * @param [in] path Path.
152  * @param [out] drive Drive on Windows if @p path specifies a drive or empty
153  * string otherwise.
154  * @param [out] tail Remaining path without drive specification.
155  */
156 void splitdrive(const std::string& path, std::string& drive, std::string& tail);
157 
158 /**
159  * @brief Get drive specification of Windows path.
160  *
161  * @param [in] path Path.
162  *
163  * @returns Tuple of (drive, tail), i.e., returns always a vector of size 2.
164  */
165 std::vector<std::string> splitdrive(const std::string& path);
166 
167 /**
168  * @brief Get file name extension.
169  *
170  * @param [in] path Path.
171  * @param [out] head Remaining path without extension.
172  * @param [out] ext Extension (including leading dot).
173  * @param [in] exts Set of recognized extensions. Note that the given set
174  * can contain extensions with dots (.) as part of the
175  * extension, e.g., ".nii.gz". If NULL is given, the part
176  * after the last dot (including the dot) is considered to
177  * be the file name extension. Otherwise, the longest extension
178  * from the given set which is equal to the end of the file
179  * path is returned. If no specified extension matched, an
180  * empty string is returned as extension.
181  * @param [in] icase Whether to ignore the case of the extensions.
182  */
183 void splitext(const std::string& path, std::string& head, std::string& ext,
184  const std::set<std::string>* exts = NULL, bool icase = false);
185 
186 /**
187  * @brief Get file name extension.
188  *
189  * @param [in] path Path.
190  * @param [in] exts Set of recognized extensions.
191  *
192  * @sa splitext(const std::string&, std::string&, std::string&, const std::set<std::string>*)
193  */
194 std::vector<std::string> splitext(const std::string& path, const std::set<std::string>* exts = NULL);
195 
196 /**
197  * @brief Get file directory.
198  *
199  * @param [in] path Path.
200  *
201  * @returns The head part returned by split().
202  *
203  * @sa split()
204  */
205 std::string dirname(const std::string& path);
206 
207 /**
208  * @brief Get file name.
209  *
210  * @param [in] path Path.
211  *
212  * @returns The tail part returned by split(), i.e., the file/directory name.
213  *
214  * @sa split()
215  */
216 std::string basename(const std::string& path);
217 
218 /**
219  * @brief Test whether a given path has an extension.
220  *
221  * @param [in] path Path.
222  * @param [in] exts Set of recognized extensions or NULL.
223  *
224  * @returns Whether the given path has a file name extension. If @p exts is not
225  * NULL, this function returns true only if the file name ends in one
226  * of the specified extensions (including dot if required). Otherwise,
227  * it only checks if the path has a dot (.) in the file name.
228  */
229 bool hasext(const std::string& path, const std::set<std::string>* exts = NULL);
230 
231 // ===========================================================================
232 // conversion
233 // ===========================================================================
234 
235 /**
236  * @brief Test whether a given path is absolute.
237  *
238  * @param path [in] Absolute or relative path.
239  *
240  * @return Whether the given path is absolute.
241  */
242 bool isabs(const std::string& path);
243 
244 /**
245  * @brief Make path absolute.
246  *
247  * @param [in] path Absolute or relative path.
248  *
249  * @return Absolute path. If @p path is already absolute, it is returned
250  * unchanged. Otherwise, it is made absolute using the current
251  * working directory.
252  */
253 std::string abspath(const std::string& path);
254 
255 /**
256  * @brief Make path relative.
257  *
258  * @param [in] path Absolute or relative path.
259  * @param [in] base Base path used to make absolute path relative.
260  * Defaults to current working directory if no path is
261  * given. If a relative path is given as base path, it
262  * is made absolute using the current working directory.
263  *
264  * @return Path relative to @p base.
265  *
266  * @throws std::invalid_argument on Windows, if @p path and @p base are paths
267  * on different drives.
268  */
269 std::string relpath(const std::string& path, const std::string& base = std::string());
270 
271 /**
272  * @brief Get canonical file path.
273  *
274  * This function resolves symbolic links and returns a normalized path.
275  *
276  * @param [in] path Path.
277  *
278  * @return Canonical file path.
279  */
280 std::string realpath(const std::string& path);
281 
282 /**
283  * @brief Join two paths, e.g., base path and relative path.
284  *
285  * This function joins two paths. If the second path is an absolute path,
286  * this normalized absolute path is returned. Otherwise, the base path is
287  * prepended to the relative path and the resulting relative or absolute
288  * path returned after normalizing it.
289  *
290  * @param [in] base Base path.
291  * @param [in] path Relative or absolute path.
292  *
293  * @return Joined path.
294  */
295 std::string join(const std::string& base, const std::string& path);
296 
297 // ===========================================================================
298 // file status
299 // ===========================================================================
300 
301 /**
302  * @brief Test the existance of a file or directory.
303  *
304  * @param [in] path File or directory path.
305  *
306  * @return Whether the given file or directory exists.
307  */
308 bool exists(const std::string path);
309 
310 /**
311  * @brief Test whether a given path is the path of an existent file.
312  *
313  * @note This function follows symbolic links.
314  *
315  * @param [in] path File path.
316  *
317  * @return Whether the given path is an existent file.
318  */
319 bool isfile(const std::string path);
320 
321 /**
322  * @brief Test whether a given path is the path of an existent directory.
323  *
324  * @note This function follows symbolic links.
325  *
326  * @param [in] path Directory path.
327  *
328  * @return Whether the given path is an existent directory.
329  */
330 bool isdir(const std::string path);
331 
332 /**
333  * @brief Whether a given path is a symbolic link.
334  *
335  * @param [in] path Path.
336  *
337  * @return Whether the given path denotes a symbolic link.
338  *
339  * @throw std::invalid_argument if the given path is not valid.
340  *
341  * @sa isvalid()
342  */
343 bool islink(const std::string& path);
344 
345 
346 } // namespace path
347 
348 } // namespace os
349 
350 } // namespace basis
351 
352 
353 /// @}
354 // Doxygen group
355 
356 #endif // _BASIS_OS_PATH_H
std::string ntpath(const std::string &path)
Convert path to Windows representation.
Definition: path.cxx:145
std::string normpath(const std::string &path)
Normalize path, i.e., remove occurences of "./", duplicate slashes,...
Definition: path.cxx:81
std::string realpath(const std::string &path)
Get canonical file path.
Definition: path.cxx:386
std::string join(const std::string &base, const std::string &path)
Join two paths, e.g., base path and relative path.
Definition: path.cxx:432
bool hasext(const std::string &path, const std::set< std::string > *exts=NULL)
Test whether a given path has an extension.
Definition: path.cxx:281
bool isabs(const std::string &path)
Test whether a given path is absolute.
Definition: path.cxx:292
Definition: basis.h:34
void splitdrive(const std::string &path, std::string &drive, std::string &tail)
Get drive specification of Windows path.
Definition: path.cxx:188
bool issep(char c)
Determine if a given character is a path separator.
Definition: path.cxx:57
bool exists(const std::string path)
Test the existance of a file or directory.
Definition: path.cxx:476
bool isfile(const std::string path)
Test whether a given path is the path of an existent file.
Definition: path.cxx:448
std::string basename(const std::string &path)
Get file name.
Definition: path.cxx:273
std::string abspath(const std::string &path)
Make path absolute.
Definition: path.cxx:302
void split(const std::string &path, std::string &head, std::string &tail)
Split path into two parts.
Definition: path.cxx:164
std::string relpath(const std::string &path, const std::string &base=std::string())
Make path relative.
Definition: path.cxx:308
bool islink(const std::string &path)
Whether a given path is a symbolic link.
Definition: path.cxx:489
void splitext(const std::string &path, std::string &head, std::string &ext, const std::set< std::string > *exts=NULL, bool icase=false)
Get file name extension.
Definition: path.cxx:212
std::string dirname(const std::string &path)
Get file directory.
Definition: path.cxx:265
bool isdir(const std::string path)
Test whether a given path is the path of an existent directory.
Definition: path.cxx:462
std::string posixpath(const std::string &path)
Convert path to Posix (e.g., Unix, Mac OS) representation.
Definition: path.cxx:130