From 08903414e3546bc2c76bef73b2337ccf79886530 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 18 Jun 2015 14:41:44 +0200 Subject: Move path and filesystem from build2 to libbutl --- butl/path.ixx | 171 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 171 insertions(+) create mode 100644 butl/path.ixx (limited to 'butl/path.ixx') diff --git a/butl/path.ixx b/butl/path.ixx new file mode 100644 index 0000000..0cbbeaf --- /dev/null +++ b/butl/path.ixx @@ -0,0 +1,171 @@ +// file : butl/path.ixx -*- C++ -*- +// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#ifdef _WIN32 +# include // std::tolower +# include // std::towlower +#endif + +namespace butl +{ +#ifdef _WIN32 + template <> + inline char path_traits:: + tolower (char c) + { + return std::tolower (c); + } + + template <> + inline wchar_t path_traits:: + tolower (wchar_t c) + { + return std::towlower (c); + } +#endif + + template + inline bool basic_path:: + absolute () const + { +#ifdef _WIN32 + return this->path_.size () > 1 && this->path_[1] == ':'; +#else + return !this->path_.empty () && traits::is_separator (this->path_[0]); +#endif + } + + template + inline bool basic_path:: + root () const + { +#ifdef _WIN32 + return this->path_.size () == 2 && this->path_[1] == ':'; +#else + return this->path_.size () == 1 && traits::is_separator (this->path_[0]); +#endif + } + + template + inline bool basic_path:: + sub (const basic_path& p) const + { + size_type n (p.path_.size ()); + + if (n == 0) + return true; + + size_type m (this->path_.size ()); + + // The second condition guards against the /foo-bar vs /foo case. + // + return m >= n && this->path_.compare (0, n, p.path_) == 0 && + (traits::is_separator (p.path_.back ()) || // p ends with a separator + m == n || // *this == p + traits::is_separator (this->path_[n])); // next char is a separator + } + + template + inline bool basic_path:: + sup (const basic_path& p) const + { + size_type n (p.path_.size ()); + + if (n == 0) + return true; + + size_type m (this->path_.size ()); + + // The second condition guards against the /foo-bar vs bar case. + // + return m >= n && this->path_.compare (m - n, n, p.path_) == 0 && + (m == n || // *this == p + traits::is_separator (this->path_[m - n - 1])); // prev char separator + } + + template + inline auto basic_path:: + begin () const -> iterator + { + size_type b, e; + + if (this->path_.empty ()) + b = e = string_type::npos; + +#ifndef _WIN32 + else if (root ()) + { + // We want to return a single empty component. Here we return + // the begin position one past the end. Not sure if this legal. + // + b = 1; + e = string_type::npos; + } +#endif + else + { + b = 0; + e = traits::find_separator (this->path_); + } + + return iterator (this->path_, b, e); + } + + template + inline auto basic_path:: + end () const -> iterator + { + return iterator (this->path_, string_type::npos, string_type::npos); + } + + template + inline basic_path& basic_path:: + complete () + { + if (relative ()) + *this = current () / *this; + + return *this; + } + + template + inline typename basic_path::dir_type basic_path:: + root_directory () const + { + return absolute () +#ifdef _WIN32 + ? dir_type (this->path_, 2) +#else + ? dir_type ("/") +#endif + : dir_type (); + } + + template + inline basic_path basic_path:: + base () const + { + size_type p (traits::find_extension (this->path_)); + return p != string_type::npos + ? basic_path (this->path_.c_str (), p) + : *this; + } + + template + inline const C* basic_path:: + extension () const + { + size_type p (traits::find_extension (this->path_)); + return p != string_type::npos ? this->path_.c_str () + p + 1 : nullptr; + } + +#ifndef _WIN32 + template + inline typename basic_path::string_type basic_path:: + posix_string () const + { + return string (); + } +#endif +} -- cgit v1.1