Mercurial > code
view modules/fs/fs.hpp @ 565:a1841ba6eb61
Net: various documentation fixes
author | David Demelier <markand@malikania.fr> |
---|---|
date | Thu, 23 Jun 2016 13:50:27 +0200 |
parents | 730358cb0648 |
children | 67da1bacd884 |
line wrap: on
line source
/* * fs.hpp -- filesystem operations * * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr> * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef FS_HPP #define FS_HPP /** * \file fs.hpp * \brief Filesystem operations made easy. */ /** * \page filesystem Filesystem * \brief Filesystem support * * ## Options * * The following options can be set by the user: * * - **FS_HAVE_STAT**: (bool) Set to true if sys/stat.h and stat function are available, automatically detected. * * ## Export macros * * You must define `FS_DLL` globally and `FS_BUILDING_DLL` when compiling the library if you want a DLL, alternatively you can provide * your own `FS_EXPORT` macro instead. */ /** * \cond FS_HIDDEN_SYMBOLS */ #if !defined(FS_HAVE_STAT) # if defined(_WIN32) # define FS_HAVE_STAT # elif defined(__linux__) # define FS_HAVE_STAT # elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) # define FS_HAVE_STAT # elif defined(__APPLE__) # define FS_HAVE_STAT # endif #endif #if !defined(FS_EXPORT) # if defined(FS_DLL) # if defined(_WIN32) # if defined(FS_BUILDING_DLL) # define FS_EXPORT __declspec(dllexport) # else # define FS_EXPORT __declspec(dllimport) # endif # else # define FS_EXPORT # endif # else # define FS_EXPORT # endif #endif /** * \endcond */ #if defined(FS_HAVE_STAT) # include <sys/stat.h> #endif #include <regex> #include <string> #include <vector> /** * \brief Filesystem namespace. */ namespace fs { /** * \enum Flags * \brief Flags for readdir. */ enum Flags { Dot = (1 << 0), //!< if set, also lists "." DotDot = (1 << 1) //!< if set, also lists ".." }; /** * \class Entry * \brief Entry in the directory list. */ class Entry { public: /** * \brief Describe the type of an entry */ enum Type : char { Unknown, //!< File type is unknown, File, //!< File is regular type, Dir, //!< File is directory, Link //!< File is link }; std::string name; //!< name of entry (base name) Type type{Unknown}; //!< type of file }; /** * Check if two entries are identical. * * \param e1 the first entry * \param e2 the second entry * \return true if they are identical */ inline bool operator==(const Entry &e1, const Entry &e2) noexcept { return e1.name == e2.name && e1.type == e2.type; } /** * Check if two entries are different. * * \param e1 the first entry * \param e2 the second entry * \return true if they are different */ inline bool operator!=(const Entry &e1, const Entry &e2) noexcept { return !(e1 == e2); } /** * Get the separator for that system. * * \return \ on Windows and / otherwise */ inline char separator() noexcept { #if defined(_WIN32) return '\\'; #else return '/'; #endif } /** * Clean a path by removing any extra / or \ and add a trailing one. * * \param path the path * \return the updated path */ FS_EXPORT std::string clean(std::string path); /** * Get the base name from a path. * * Example, baseName("/etc/foo.conf") // foo.conf * * \param path the path * \return the base name */ FS_EXPORT std::string baseName(std::string path); /** * Get the parent directory from a path. * * Example, dirName("/etc/foo.conf") // /etc * * \param path the path * \return the parent directory */ FS_EXPORT std::string dirName(std::string path); #if defined(FS_HAVE_STAT) /** * Get stat information. * * \param path the path * \return the stat information * \throw std::runtime_error on failure */ FS_EXPORT struct stat stat(const std::string &path); #endif // !HAVE_STAT /** * Check if a file exists. * * If HAVE_ACCESS is defined, the function access is used, otherwise stat is used. * * \param path the path to check * \return true if the path exists */ FS_EXPORT bool exists(const std::string &path) noexcept; /** * Check if the path is absolute. * * \param path the path * \return true if the path is absolute */ FS_EXPORT bool isAbsolute(const std::string &path) noexcept; /** * Check if the path is relative. * * \param path the path * \return true if the path is absolute */ FS_EXPORT bool isRelative(const std::string &path) noexcept; /** * Check if the file is readable. * * \param path the path * \return true if has read access */ FS_EXPORT bool isReadable(const std::string &path) noexcept; /** * Check if the file is writable. * * \param path the path * \return true if has write access */ FS_EXPORT bool isWritable(const std::string &path) noexcept; /** * Check if the file is a regular file. * * \param path the path * \return true if it is a file and false if not or not readable * \throw std::runtime_error if the operation is not supported */ FS_EXPORT bool isFile(const std::string &path); /** * Check if the file is a directory. * * \param path the path * \return true if it is a directory and false if not or not readable * \throw std::runtime_error if the operation is not supported */ FS_EXPORT bool isDirectory(const std::string &path); /** * Check if the file is a symbolic link. * * \param path the path * \return true if it is a symbolic link and false if not or not readable * \throw std::runtime_error if the operation is not supported */ FS_EXPORT bool isSymlink(const std::string &path); /** * Read a directory and return a list of entries (not recursive). * * \param path the directory path * \param flags the optional flags (see Flags) * \return the list of entries * \throw std::runtime_error on failure */ FS_EXPORT std::vector<Entry> readdir(const std::string &path, int flags = 0); /** * Create a directory recursively. * * \param path the path * \param mode the optional mode (not always supported) * \throw std::runtime_error on failure * \post all intermediate directories are created */ FS_EXPORT void mkdir(const std::string &path, int mode = 0700); /** * Remove a directory recursively. * * If errors happens, they are silently discarded to remove as much as possible. * * \param path the path */ FS_EXPORT void rmdir(const std::string &path) noexcept; /** * Search an item recursively. * * The predicate must have the following signature: * void f(const std::string &base, const Entry &entry) * * Where: * - base is the current parent directory in the tree * - entry is the current entry * * \param base the base directory * \param predicate the predicate * \return the full path name to the file or empty string if never found * \throw std::runtime_error on read errors */ template <typename Predicate> std::string findIf(const std::string &base, Predicate &&predicate) { /* * Do not go deeply to the tree before testing all files in the current directory for performances reasons, we iterate * this directory to search for the entry name and iterate again over all sub directories if not found. */ std::string path; std::vector<Entry> entries = readdir(base); for (const auto &entry : entries) { if (predicate(base, entry)) { path = base + separator() + entry.name; break; } } if (!path.empty()) return path; for (const auto &entry : entries) { if (entry.type != Entry::Dir) continue; path = findIf(base + separator() + entry.name, std::forward<Predicate>(predicate)); if (!path.empty()) break; } return path; } /** * Find a file by name recursively. * * \param base the base directory * \param name the file name * \return the full path name to the file or empty string if never found * \throw std::runtime_error on read errors */ inline std::string find(const std::string &base, const std::string &name) { return findIf(base, [&] (const auto &, const auto &entry) { return entry.name == name; }); } /** * Overload by regular expression. * * \param base the base directory * \param regex the regular expression * \return the full path name to the file or empty string if never found * \throw std::runtime_error on read errors */ inline std::string find(const std::string &base, const std::regex ®ex) { return findIf(base, [&] (const auto &, const auto &entry) { return std::regex_match(entry.name, regex); }); } /** * Get the current working directory. * * \return the current working directory * \throw std::runtime_error on failure */ FS_EXPORT std::string cwd(); } // !fs #endif // !FS_HPP