| // SPDX-License-Identifier: Apache-2.0 |
| // Copyright Apache Software Foundation 2019 |
| /** @file |
| |
| Simple path and file utilities. |
| */ |
| |
| #pragma once |
| |
| #include <sys/stat.h> |
| |
| #include <string> |
| #include <string_view> |
| #include <system_error> |
| #include <chrono> |
| |
| #include "swoc/swoc_version.h" |
| #include "swoc/TextView.h" |
| |
| namespace swoc { inline namespace SWOC_VERSION_NS { |
| namespace file { |
| /** Utility class for file system paths. |
| */ |
| class path { |
| using self_type = path; |
| |
| public: |
| static constexpr char SEPARATOR = '/'; |
| |
| /// Default construct empty path. |
| path() = default; |
| |
| /// Copy constructor - copies the path. |
| path(const self_type& that) = default; |
| |
| /// Move constructor. |
| path(self_type&& that) = default; |
| |
| /// Construct from a null terminated string. |
| explicit path(const char *src); |
| |
| /// Construct from a string view. |
| path(std::string_view src); |
| // template < typename ... Args > explicit path(std::string_view base, Args... rest); |
| |
| /// Move from an existing string |
| path(std::string&& that); |
| |
| /// Replace the path with a copy of @a that. |
| self_type& operator=(const self_type& that) = default; |
| |
| /// Replace the path with the contents of @a that. |
| self_type& operator=(self_type&& that) = default; |
| |
| /// Assign @a p as the path. |
| self_type& operator=(std::string_view p); |
| |
| /** Append or replace path with @a that. |
| * |
| * If @a that is absolute, it replaces @a this. Otherwise @a that is appended with exactly one |
| * separator. |
| * |
| * @param that Filesystem path. |
| * @return @a this |
| */ |
| self_type& operator/=(const self_type& that); |
| |
| self_type& operator/=(std::string_view that); |
| |
| /// Check if the path is empty. |
| bool empty() const; |
| |
| /// Check if the path is absolute. |
| bool is_absolute() const; |
| |
| /// Check if the path is not absolute. |
| bool is_relative() const; |
| |
| self_type parent_path() const; |
| |
| /// Access the path explicitly. |
| char const *c_str() const; |
| |
| /// The path as a string. |
| std::string const& string() const; |
| |
| /// A view of the path. |
| swoc::TextView view() const; |
| |
| protected: |
| std::string _path; ///< File path. |
| }; |
| |
| /// Information about a file. |
| class file_status { |
| using self_type = file_status; |
| |
| protected: |
| struct ::stat _stat; ///< File information. |
| |
| friend self_type status(const path& file, std::error_code& ec) noexcept; |
| friend int file_type(const self_type&); |
| friend off_t file_size(const self_type&); |
| friend bool is_regular_file(const file_status&); |
| friend bool is_dir(const file_status&); |
| friend bool is_char_device(const file_status&); |
| friend bool is_block_device(const file_status&); |
| friend std::chrono::system_clock::time_point modify_time(file_status const& fs); |
| friend std::chrono::system_clock::time_point access_time(file_status const& fs); |
| friend std::chrono::system_clock::time_point status_time(file_status const& fs); |
| }; |
| |
| /** Get the status of the file at @a p. |
| * |
| * @param file Path to file. |
| * @param ec Error code return. |
| * @return Status of the file. |
| */ |
| file_status status(const path& file, std::error_code& ec) noexcept; |
| |
| // Related free functions. |
| // These are separate because they are not part of std::filesystem::path. |
| |
| /// Return the file type value. |
| int file_type(const file_status& fs); |
| |
| /// Check if the path is to a regular file. |
| bool is_regular_file(const file_status& fs); |
| |
| /// Check if the path is to a directory. |
| bool is_dir(const file_status& p); |
| |
| /// Check if the path is to a character device. |
| bool is_char_device(const file_status& fs); |
| |
| /// Check if the path is to a block device. |
| bool is_block_device(const file_status& fs); |
| |
| /// Size of the file or block device. |
| off_t file_size(const file_status& fs); |
| |
| /// Check if file is readable. |
| bool is_readable(const path& s); |
| |
| std::chrono::system_clock::time_point modify_time(file_status const& fs); |
| std::chrono::system_clock::time_point access_time(file_status const& fs); |
| std::chrono::system_clock::time_point status_time(file_status const& fs); |
| |
| /** Load the file at @a p into a @c std::string. |
| * |
| * @param p Path to file |
| * @param ec Error code result of the file operation. |
| * @return The contents of the file. |
| */ |
| std::string load(const path& p, std::error_code& ec); |
| |
| /* ------------------------------------------------------------------- */ |
| |
| inline path::path(char const *src) : _path(src) {} |
| |
| inline path::path(std::string_view base) : _path(base) {} |
| |
| inline path::path(std::string&& that) : _path(std::move(that)) {} |
| |
| inline path& |
| path::operator=(std::string_view p) { |
| _path.assign(p); |
| return *this; |
| } |
| |
| inline char const * |
| path::c_str() const { |
| return _path.c_str(); |
| } |
| |
| inline std::string const& |
| path::string() const { |
| return _path; |
| } |
| |
| inline swoc::TextView |
| path::view() const { |
| return _path; |
| } |
| |
| inline bool |
| path::empty() const { |
| return _path.empty(); |
| } |
| |
| inline bool |
| path::is_absolute() const { |
| return !_path.empty() && '/' == _path[0]; |
| } |
| |
| inline bool |
| path::is_relative() const { |
| return !this->is_absolute(); |
| } |
| |
| inline path& |
| path::operator/=(const self_type& that) { |
| return *this /= std::string_view(that._path); |
| } |
| |
| inline bool operator==(path const& lhs, path const& rhs) { |
| return lhs.view() == rhs.view(); |
| } |
| |
| inline bool operator!=(path const& lhs, path const& rhs) { |
| return lhs.view() != rhs.view(); |
| } |
| |
| /** Combine two strings as file paths. |
| |
| @return A @c path with the combined path. |
| */ |
| inline path |
| operator/(const path& lhs, const path& rhs) { |
| return path(lhs) /= rhs; |
| } |
| |
| inline path |
| operator/(path&& lhs, const path& rhs) { |
| return path(std::move(lhs)) /= rhs; |
| } |
| |
| inline path |
| operator/(const path& lhs, std::string_view rhs) { |
| return path(lhs) /= rhs; |
| } |
| |
| inline path |
| operator/(path&& lhs, std::string_view rhs) { |
| return path(std::move(lhs)) /= rhs; |
| } |
| |
| } // namespace file |
| |
| class BufferWriter; |
| namespace bwf { |
| struct Spec; |
| } |
| |
| BufferWriter& bwformat(BufferWriter& w, bwf::Spec const& spec, file::path const& p); |
| }} // namespace swoc |
| |
| namespace std { |
| /// Enable use of path as a key in STL hashed containers. |
| template<> struct hash<swoc::file::path> { |
| size_t operator() (swoc::file::path const& path) const { |
| return hash<string_view>()(path.view()); |
| } |
| }; |
| } // namespace std |