BASIS  r3148
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