Forked from
Core Modules / dune-common
6026 commits behind the upstream repository.
-
Jorrit Fahlke authored
[[Imported from SVN: r6039]]
Jorrit Fahlke authored[[Imported from SVN: r6039]]
path.hh 8.11 KiB
// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
// vi: set et ts=4 sw=2 sts=2:
#ifndef DUNE_COMMON_PATH_HH
#define DUNE_COMMON_PATH_HH
#include <string>
namespace Dune {
/**
* @addtogroup Path Filesystem Paths
* @ingroup Common
* @{
*/
/**
* @file
* @author Jö Fahlke <jorrit@jorrit.de>
* @brief Utilites for handling filesystem paths
*/
//! concatenate two paths
/**
* \param base The base path.
* \param p The path to concatenate onto base.
*
* If p is an absolute path, return p. Otherwise return the
* string-concatenation of base and path, possibly with a '/' inbetween, if
* necessary.
*
* Some examples:
* <table>
* <tr><th> base </th><th> p </th><th> result </th></tr>
* <tr><td> anything </td><td> "/abs/path" </td><td> "/abs/path" </td></tr>
* <tr><td> "a" </td><td> "b" </td><td> "a/b" </td></tr>
* <tr><td> "/a" </td><td> "b" </td><td> "/a/b" </td></tr>
* <tr><td> "a/" </td><td> "b" </td><td> "a/b" </td></tr>
* <tr><td> "a" </td><td> "b/" </td><td> "a/b/" </td></tr>
* <tr><td> ".." </td><td> "b" </td><td> "../b" </td></tr>
* <tr><td> "a" </td><td> ".." </td><td> "a/.." </td></tr>
* <tr><td> "." </td><td> "b" </td><td> "./b" </td></tr>
* <tr><td> "a" </td><td> "." </td><td> "a/." </td></tr>
* <tr><td> "" </td><td> "b" </td><td> "b" </td></tr>
* <tr><td> "a" </td><td> "" </td><td> "a" </td></tr>
* <tr><td> "" </td><td> "" </td><td> "" </td></tr>
* </table>
*
* If both base and p are sanitized as per processPath(), and if p does not
* contain any leading "../", then the result will also be sanitized.
*/
std::string concatPaths(const std::string& base, const std::string& p);
//! sanitize a path for further processing
/**
* Sanitize the path as far as possible to make further processing easier.
* The resulting path has the following properties:
* <ul>
* <li> The path is a series of components, each followed by a single '/'.
* <li> An absolute path starts with an empty component followed by a '/',
* so its first charachter will be '/'. This is the only case where an
* empty component can occur.
* <li> The path does not contain any component ".". Any such component in
* the input is removed.
* <li> A ".." component may only occur in the following case: A relative
* path may contain a series of ".." in the beginning. Any other
* occurances of ".." int eh input is collapsed with a preceding
* component or simply removed if it is at the beginning of an absolute
* path.
* </ul>
*
* \note The result is really meant for processing only since it has two
* unusual properties: First, any path denoting the current directory
* in the input, such as "." will result in an empty path "". Second,
* any non-empty result path will have a trailing '/'. For other
* uses, prettyPath() may be more appropriate.
*
* Some examples:
* <table>
* <tr><th> p </th><th> result </th></tr>
* <tr><td> "" </td><td> "" </td></tr>
* <tr><td> "." </td><td> "" </td></tr>
* <tr><td> "./" </td><td> "" </td></tr>
* <tr><td> "a/.." </td><td> "" </td></tr>
* <tr><td> ".." </td><td> "../" </td></tr>
* <tr><td> "../a" </td><td> "../a/" </td></tr>
* <tr><td> "a" </td><td> "a/" </td></tr>
* <tr><td> "a//" </td><td> "a/" </td></tr>
* <tr><td> "a///b" </td><td> "a/b/" </td></tr>
* <tr><td> "/" </td><td> "/" </td></tr>
* <tr><td> "/." </td><td> "/" </td></tr>
* <tr><td> "/.." </td><td> "/" </td></tr>
* <tr><td> "/a/.." </td><td> "/" </td></tr>
* <tr><td> "/a" </td><td> "/a/" </td></tr>
* <tr><td> "/a/" </td><td> "/a/" </td></tr>
* <tr><td> "/../a/" </td><td> "/a/" </td></tr>
* </table>
*/
std::string processPath(const std::string& p);
//! check whether the given path indicates that it is a directory
/**
* In particular the following kinds of paths indicate a directory:
* <ul>
* <li> The empty path (denotes the current directory),
* <li> any path with a trailing '/',
* <li> any path whose last component is "." or "..".
* </ul>
*/
bool pathIndicatesDirectory(const std::string& p);
//! pretty print path
/**
* \param p Path to pretty-print.
* \param isDirectory Whether to append a '/' to make clear this is a
* directory.
*
* Pretty print the path. This removes any duplicate '/' and any
* superfluous occurances of ".." and ".". The resulting path will have a
* trailing '/' if it is the root path or if isDirectory is true. It will
* however not have a trailing '/' if it is otherwise clear that it is a
* directory -- i.e. if its last component is "." or "..".
*
* Some examples:
* <table>
* <tr><th> p </th><th> isDirectory </th><th> result </th></tr>
* <tr><td> "" </td><td> anything </td><td> "." </td></tr>
* <tr><td> "." </td><td> anything </td><td> "." </td></tr>
* <tr><td> "./" </td><td> anything </td><td> "." </td></tr>
* <tr><td> "a/.." </td><td> anything </td><td> "." </td></tr>
* <tr><td> ".." </td><td> anything </td><td> ".." </td></tr>
* <tr><td> "../a" </td><td> true </td><td> "../a/" </td></tr>
* <tr><td> "../a" </td><td> false </td><td> "../a" </td></tr>
* <tr><td> "a" </td><td> true </td><td> "a/" </td></tr>
* <tr><td> "a" </td><td> false </td><td> "a" </td></tr>
* <tr><td> "a//" </td><td> true </td><td> "a/" </td></tr>
* <tr><td> "a//" </td><td> false </td><td> "a" </td></tr>
* <tr><td> "a///b" </td><td> true </td><td> "a/b/" </td></tr>
* <tr><td> "a///b" </td><td> false </td><td> "a/b" </td></tr>
* <tr><td> "/" </td><td> anything </td><td> "/" </td></tr>
* <tr><td> "/." </td><td> anything </td><td> "/" </td></tr>
* <tr><td> "/.." </td><td> anything </td><td> "/" </td></tr>
* <tr><td> "/a/.." </td><td> anything </td><td> "/" </td></tr>
* <tr><td> "/a" </td><td> true </td><td> "/a/" </td></tr>
* <tr><td> "/a" </td><td> false </td><td> "/a" </td></tr>
* <tr><td> "/a/" </td><td> true </td><td> "/a/" </td></tr>
* <tr><td> "/a/" </td><td> false </td><td> "/a" </td></tr>
* <tr><td> "/../a/" </td><td> true </td><td> "/a/" </td></tr>
* <tr><td> "/../a/" </td><td> false </td><td> "/a" </td></tr>
* </table>
*/
std::string prettyPath(const std::string& p, bool isDirectory);
//! pretty print path
/**
* \param p Path to pretty-print.
*
* This is like prettyPath(const std::string& p, bool isDirectory) with
* isDirectory automatically determined using pathIndicatesDirectory(p).
*/
std::string prettyPath(const std::string& p);
//! compute a relative path between two paths
/**
* \param newbase Base path for the resulting relative path.
* \param p Path re sulting path should resolve to, when taken
* reltively to newbase.
*
* Compute a relative path from newbase to p. newbase is assumed to be a
* directory. p and newbase should either both be absolute, or both be
* relative. In the latter case they are assumed to both be relative to
* the same unspecified directory. The has the form of something sanitized
* by processPath().
*
* \throw NotImplemented The condition that newbase and p must both be
* relative or both be absolute does not hold.
* \throw NotImplemented After sanitization newbase has more leading ".."
* components than p.
*/
std::string relativePath(const std::string& newbase, const std::string& p);
/** @} group Path */
}
#endif // DUNE_COMMON_PATH_HH