From 8e761289a2446367267c6c0d9a26e734f0f78306 Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Wed, 16 Dec 2020 20:29:05 +0300 Subject: Get rid of legacy build systems and rename cutl/ to libcutl/ --- libcutl/fs/path.hxx | 332 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 332 insertions(+) create mode 100644 libcutl/fs/path.hxx (limited to 'libcutl/fs/path.hxx') diff --git a/libcutl/fs/path.hxx b/libcutl/fs/path.hxx new file mode 100644 index 0000000..1d2119c --- /dev/null +++ b/libcutl/fs/path.hxx @@ -0,0 +1,332 @@ +// file : libcutl/fs/path.hxx +// license : MIT; see accompanying LICENSE file + +#ifndef LIBCUTL_FS_PATH_HXX +#define LIBCUTL_FS_PATH_HXX + +#include +#include + +#include + +#include + +namespace cutl +{ + namespace fs + { + template + class basic_path; + + template + struct path_traits + { + typedef std::basic_string string_type; + typedef typename string_type::size_type size_type; + + // Canonical directory and path seperators. + // +#ifdef _WIN32 + static C const directory_separator = '\\'; + static C const path_separator = ';'; +#else + static C const directory_separator = '/'; + static C const path_separator = ':'; +#endif + + // Directory separator tests. On some platforms there + // could be multiple seperators. For example, on Windows + // we check for both '/' and '\'. + // + static bool + is_separator (C c) + { +#ifdef _WIN32 + return c == '\\' || c == '/'; +#else + return c == '/'; +#endif + } + + static size_type + find_separator (string_type const& s, size_type pos = 0) + { + for (size_type n (s.size ()); pos < n; ++pos) + { + if (is_separator (s[pos])) + return pos; + } + + return string_type::npos; + } + + static size_type + rfind_separator (string_type const& s, size_type pos = string_type::npos) + { + if (pos == string_type::npos) + pos = s.size (); + else + pos++; + + for (; pos > 0; --pos) + { + if (is_separator (s[pos - 1])) + return pos - 1; + } + + return string_type::npos; + } + + static int + compare (string_type const& l, string_type const& r) + { + size_type ln (l.size ()), rn (r.size ()), n (ln < rn ? ln : rn); + for (size_type i (0); i != n; ++i) + { +#ifdef _WIN32 + C lc (tolower (l[i])), rc (tolower (r[i])); +#else + C lc (l[i]), rc (r[i]); +#endif + if (is_separator (lc) && is_separator (rc)) + continue; + + if (lc < rc) return -1; + if (lc > rc) return 1; + } + + return ln < rn ? -1 : (ln > rn ? 1 : 0); + } + + private: +#ifdef _WIN32 + static C + tolower (C); +#endif + }; + + template + class invalid_basic_path; + + typedef basic_path path; + typedef invalid_basic_path invalid_path; + + typedef basic_path wpath; + typedef invalid_basic_path invalid_wpath; + + // + // + class LIBCUTL_EXPORT invalid_path_base: exception + { + public: + virtual char const* + what () const noexcept; + }; + + template + class invalid_basic_path: public invalid_path_base + { + public: + typedef std::basic_string string_type; + + invalid_basic_path (C const* p): path_ (p) {} + invalid_basic_path (string_type const& p): path_ (p) {} + ~invalid_basic_path () noexcept {} + + string_type const& + path () const + { + return path_; + } + + private: + string_type path_; + }; + + template + class basic_path + { + public: + typedef std::basic_string string_type; + typedef typename string_type::size_type size_type; + + typedef path_traits traits; + + // Construct special empty path. + // + basic_path () + { + } + + explicit + basic_path (C const* s) + : path_ (s) + { + init (); + } + + basic_path (C const* s, size_type n) + : path_ (s, n) + { + init (); + } + + explicit + basic_path (string_type const& s) + : path_ (s) + { + init (); + } + + void + swap (basic_path& p) + { + path_.swap (p.path_); + } + + void + clear () + { + path_.clear (); + } + + static basic_path + current (); + + static void + current (basic_path const&); + + public: + bool + empty () const + { + return path_.empty (); + } + + bool + absolute () const; + + bool + relative () const + { + return !absolute (); + } + + bool + root () const; + + public: + // Return the path without the directory part. + // + basic_path + leaf () const; + + // Return the directory part of the path or empty path if + // there is no directory. + // + basic_path + directory () const; + + // Return the path without the extension, if any. + // + basic_path + base () const; + + public: + // Normalize the path. This includes collapsing the '.' and '..' + // directories if possible, collapsing multiple directory + // separators, and converting all directory separators to the + // canonical form. Returns *this. + // + basic_path& + normalize (); + + // Make the path absolute using the current directory unless + // it is already absolute. + // + basic_path& + complete (); + + public: + basic_path + operator/ (basic_path const& x) const + { + basic_path r (*this); + r /= x; + return r; + } + + basic_path& + operator/= (basic_path const&); + + basic_path + operator+ (string_type const& s) const + { + return basic_path (path_ + s); + } + + basic_path& + operator+= (string_type const& s) + { + path_ += s; + return *this; + } + + // Note that comparison is case-insensitive if the filesystem is + // not case-sensitive (e.g., Windows). + // + bool + operator== (basic_path const& x) const + { + return traits::compare (path_, x.path_) == 0; + } + + bool + operator!= (basic_path const& x) const + { + return !(*this == x); + } + + bool + operator< (basic_path const& x) const + { + return traits::compare (path_, x.path_) < 0; + } + + public: + const string_type& + string () const + { + return path_; + } + + // If possible, return a POSIX representation of the path. For example, + // for a Windows path in the form foo\bar this function will return + // foo/bar. If it is not possible to create a POSIX representation for + // this path (e.g., c:\foo), this function will throw the invalid_path + // exception. + // + string_type + posix_string () const; + + private: + void + init (); + + private: + string_type path_; + }; + + template + inline std::basic_ostream& + operator<< (std::basic_ostream& os, basic_path const& p) + { + return os << p.string (); + } + } +} + +#include +#include + +#endif // LIBCUTL_FS_PATH_HXX -- cgit v1.1