// 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 // @@ Should only enable_if P is basic_path. // template inline P path_cast (const basic_path& p) { return P (p.path_, false); } template inline P path_cast (basic_path&& p) { return P (std::move (p.path_), false); } template inline bool basic_path:: simple () const { return #ifndef _WIN32 root () || #endif traits::find_separator (this->path_) == string_type::npos; } 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 (const iterator& b, const iterator& e) { //assert (b.p_ == e.p_); if (b != e) { this->path_.assign ( *b.p_, b.b_, (e.b_ != string_type::npos ? e.b_ - b.b_ - 1 : e.b_)); #ifndef _WIN32 if (this->path_.empty ()) this->path_ = '/'; #endif // No init() should be necessary. } } 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 }