path.h
Go to the documentation of this file.
00001 /** 00002 * @file os/path.h 00003 * @brief File/directory path related functions. 00004 * 00005 * The implementations provided by this module are in particular related to the 00006 * manipulation of and interaction with file (and directory) paths. These 00007 * implementations are meant to be simple and therefore focus on non-multibyte 00008 * path strings only. They were motivated by the os.path module of Python, though, 00009 * they are no exact replicates of these functions. The path module which is 00010 * part of the BASIS utilities for Python, on the other side, provides the same 00011 * extended functionality. 00012 * 00013 * Copyright (c) 2011, 2012 University of Pennsylvania. All rights reserved.<br /> 00014 * See https://www.cbica.upenn.edu/sbia/software/license.html or COPYING file. 00015 * 00016 * Contact: SBIA Group <sbia-software at uphs.upenn.edu> 00017 */ 00018 00019 #pragma once 00020 #ifndef _BASIS_OS_PATH_H 00021 #define _BASIS_OS_PATH_H 00022 00023 00024 #include <set> 00025 #include <vector> 00026 #include <string> 00027 00028 00029 /// @addtogroup BasisCxxUtilities 00030 /// @{ 00031 00032 00033 namespace basis { namespace os { namespace path { 00034 00035 00036 // =========================================================================== 00037 // representation 00038 // =========================================================================== 00039 00040 /** 00041 * @brief Determine if a given character is a path separator. 00042 * 00043 * @param [in] c Character. 00044 * 00045 * @returns True if @p c is a path separator on this platform and false otherwise. 00046 */ 00047 bool issep(char c); 00048 00049 /** 00050 * @brief Normalize path, i.e., remove occurences of "./", duplicate slashes,... 00051 * 00052 * This function removes single periods enclosed by slashes (or backslashes), 00053 * duplicate slashes (or backslashes), and further tries to reduce the 00054 * number of parent directory references. Moreover, on Windows, it replaces 00055 * slashes with backslashes. 00056 * 00057 * For example, on Windows, "../bla//.//.\bla\\\\\bla/../.." is convert to "..\bla". 00058 * On Unix, it is converted to "..". Note that on Unix, ".\bla\\\\\bla" is a 00059 * directory name. 00060 * 00061 * @param [in] path Path. 00062 * 00063 * @returns Normalized path. 00064 */ 00065 std::string normpath(const std::string& path); 00066 00067 /** 00068 * @brief Convert path to Posix (e.g., Unix, Mac OS) representation. 00069 * 00070 * This function first converts backward slashes to forward slashes and then 00071 * performs the same normalization as normpath() does on Posix systems. 00072 * 00073 * @param [in] path Path. 00074 * 00075 * @returns Normalized Posix path. 00076 * 00077 * @sa normpath() 00078 * @sa ntpath() 00079 */ 00080 std::string posixpath(const std::string& path); 00081 00082 /** 00083 * @brief Convert path to Windows representation. 00084 * 00085 * This function first converts forward slashes to backward slashes and then 00086 * performs the same normalization as normpath() does on Windows. 00087 * 00088 * @param [in] path Path. 00089 * 00090 * @returns Normalized Windows path. 00091 * 00092 * @sa normpath) 00093 * @sa posixpath() 00094 */ 00095 std::string ntpath(const std::string& path); 00096 00097 // =========================================================================== 00098 // components 00099 // =========================================================================== 00100 00101 /** 00102 * @brief Split path into two parts. 00103 * 00104 * This function splits a path into its head and tail. Trailing slashes are 00105 * stripped from head unless it is the root. See the following table for an 00106 * illustration: 00107 @verbatim 00108 path | head | tail 00109 -------------------------+-------+---------------+------------- 00110 "/" | "/" | "" 00111 "/usr/bin" | "/usr" | "bin" 00112 "/home/user/info.txt" | "/home/user" | "info.txt" 00113 "word.doc" | "" | "word.doc" 00114 "../word.doc" | ".." | "word.doc" 00115 "C:/" | "C:/" | "" 00116 "C:" | "C:" | "" 00117 "C:/WINDOWS/regedit.exe" | "C:/WINDOWS" | "regedit.exe" 00118 "d:\data" | "d:/" | "data" 00119 "/usr/local/" | "/usr/local" | "" 00120 @endverbatim 00121 * In all cases, join(head, tail) returns a path to the same location as path 00122 * (but the strings may differ). 00123 * 00124 * @param [in] path Path. 00125 * @param [out] head Head part of path. 00126 * @param [out] tail Tail part of path. 00127 * 00128 * @sa splitdrive() 00129 * @sa splitext() 00130 * @sa dirname() 00131 * @sa basename() 00132 */ 00133 void split(const std::string& path, std::string& head, std::string& tail); 00134 00135 /** 00136 * @brief Split path into two parts. 00137 * 00138 * @returns Tuple of (head, tail), i.e., returns always a vector of size 2. 00139 * 00140 * @sa split(const std::string&, std::string&, std::string&) 00141 */ 00142 std::vector<std::string> split(const std::string& path); 00143 00144 /** 00145 * @brief Get drive specification of Windows path. 00146 * 00147 * @param [in] path Path. 00148 * @param [out] drive Drive on Windows if @p path specifies a drive or empty 00149 * string otherwise. 00150 * @param [out] tail Remaining path without drive specification. 00151 */ 00152 void splitdrive(const std::string& path, std::string& drive, std::string& tail); 00153 00154 /** 00155 * @brief Get drive specification of Windows path. 00156 * 00157 * @param [in] path Path. 00158 * 00159 * @returns Tuple of (drive, tail), i.e., returns always a vector of size 2. 00160 */ 00161 std::vector<std::string> splitdrive(const std::string& path); 00162 00163 /** 00164 * @brief Get file name extension. 00165 * 00166 * @param [in] path Path. 00167 * @param [out] head Remaining path without extension. 00168 * @param [out] ext Extension (including leading dot). 00169 * @param [in] exts Set of recognized extensions. Note that the given set 00170 * can contain extensions with dots (.) as part of the 00171 * extension, e.g., ".nii.gz". If NULL is given, the part 00172 * after the last dot (including the dot) is considered to 00173 * be the file name extension. Otherwise, the longest extension 00174 * from the given set which is equal to the end of the file 00175 * path is returned. If no specified extension matched, an 00176 * empty string is returned as extension. 00177 * @param [in] icase Whether to ignore the case of the extensions. 00178 */ 00179 void splitext(const std::string& path, std::string& head, std::string& ext, 00180 const std::set<std::string>* exts = NULL, bool icase = false); 00181 00182 /** 00183 * @brief Get file name extension. 00184 * 00185 * @param [in] path Path. 00186 * @param [in] exts Set of recognized extensions. 00187 * 00188 * @sa splitext(const std::string&, std::string&, std::string&, const std::set<std::string>*) 00189 */ 00190 std::vector<std::string> splitext(const std::string& path, const std::set<std::string>* exts = NULL); 00191 00192 /** 00193 * @brief Get file directory. 00194 * 00195 * @param [in] path Path. 00196 * 00197 * @returns The head part returned by split(). 00198 * 00199 * @sa split() 00200 */ 00201 std::string dirname(const std::string& path); 00202 00203 /** 00204 * @brief Get file name. 00205 * 00206 * @param [in] path Path. 00207 * 00208 * @returns The tail part returned by split(), i.e., the file/directory name. 00209 * 00210 * @sa split() 00211 */ 00212 std::string basename(const std::string& path); 00213 00214 /** 00215 * @brief Test whether a given path has an extension. 00216 * 00217 * @param [in] path Path. 00218 * @param [in] exts Set of recognized extensions or NULL. 00219 * 00220 * @returns Whether the given path has a file name extension. If @p exts is not 00221 * NULL, this function returns true only if the file name ends in one 00222 * of the specified extensions (including dot if required). Otherwise, 00223 * it only checks if the path has a dot (.) in the file name. 00224 */ 00225 bool hasext(const std::string& path, const std::set<std::string>* exts = NULL); 00226 00227 // =========================================================================== 00228 // conversion 00229 // =========================================================================== 00230 00231 /** 00232 * @brief Test whether a given path is absolute. 00233 * 00234 * @param path [in] Absolute or relative path. 00235 * 00236 * @return Whether the given path is absolute. 00237 */ 00238 bool isabs(const std::string& path); 00239 00240 /** 00241 * @brief Make path absolute. 00242 * 00243 * @param [in] path Absolute or relative path. 00244 * 00245 * @return Absolute path. If @p path is already absolute, it is returned 00246 * unchanged. Otherwise, it is made absolute using the current 00247 * working directory. 00248 */ 00249 std::string abspath(const std::string& path); 00250 00251 /** 00252 * @brief Make path relative. 00253 * 00254 * @param [in] path Absolute or relative path. 00255 * @param [in] base Base path used to make absolute path relative. 00256 * Defaults to current working directory if no path is 00257 * given. If a relative path is given as base path, it 00258 * is made absolute using the current working directory. 00259 * 00260 * @return Path relative to @p base. 00261 * 00262 * @throws std::invalid_argument on Windows, if @p path and @p base are paths 00263 * on different drives. 00264 */ 00265 std::string relpath(const std::string& path, const std::string& base = std::string()); 00266 00267 /** 00268 * @brief Get canonical file path. 00269 * 00270 * This function resolves symbolic links and returns a normalized path. 00271 * 00272 * @param [in] path Path. 00273 * 00274 * @return Canonical file path. 00275 */ 00276 std::string realpath(const std::string& path); 00277 00278 /** 00279 * @brief Join two paths, e.g., base path and relative path. 00280 * 00281 * This function joins two paths. If the second path is an absolute path, 00282 * this normalized absolute path is returned. Otherwise, the base path is 00283 * prepended to the relative path and the resulting relative or absolute 00284 * path returned after normalizing it. 00285 * 00286 * @param [in] base Base path. 00287 * @param [in] path Relative or absolute path. 00288 * 00289 * @return Joined path. 00290 */ 00291 std::string join(const std::string& base, const std::string& path); 00292 00293 // =========================================================================== 00294 // file status 00295 // =========================================================================== 00296 00297 /** 00298 * @brief Test the existance of a file or directory. 00299 * 00300 * @param [in] path File or directory path. 00301 * 00302 * @return Whether the given file or directory exists. 00303 */ 00304 bool exists(const std::string path); 00305 00306 /** 00307 * @brief Test whether a given path is the path of an existent file. 00308 * 00309 * @note This function follows symbolic links. 00310 * 00311 * @param [in] path File path. 00312 * 00313 * @return Whether the given path is an existent file. 00314 */ 00315 bool isfile(const std::string path); 00316 00317 /** 00318 * @brief Test whether a given path is the path of an existent directory. 00319 * 00320 * @note This function follows symbolic links. 00321 * 00322 * @param [in] path Directory path. 00323 * 00324 * @return Whether the given path is an existent directory. 00325 */ 00326 bool isdir(const std::string path); 00327 00328 /** 00329 * @brief Whether a given path is a symbolic link. 00330 * 00331 * @param [in] path Path. 00332 * 00333 * @return Whether the given path denotes a symbolic link. 00334 * 00335 * @throw std::invalid_argument if the given path is not valid. 00336 * 00337 * @sa isvalid() 00338 */ 00339 bool islink(const std::string& path); 00340 00341 00342 } // namespace path 00343 00344 } // namespace os 00345 00346 } // namespace basis 00347 00348 00349 /// @} 00350 // Doxygen group 00351 00352 #endif // _BASIS_OS_PATH_H