diff options
-rw-r--r-- | butl/path | 68 | ||||
-rw-r--r-- | butl/path.ixx | 15 | ||||
-rw-r--r-- | butl/path.txx | 31 |
3 files changed, 98 insertions, 16 deletions
@@ -74,13 +74,20 @@ namespace butl static size_type find_separator (string_type const& s, size_type pos = 0) { - for (size_type n (s.size ()); pos < n; ++pos) + const C* r (find_separator (s.c_str () + pos, s.size () - pos)); + return r != nullptr ? r - s.c_str () : string_type::npos; + } + + static const C* + find_separator (const C* s, size_type n) + { + for (const C* e (s + n); s != e; ++s) { - if (is_separator (s[pos])) - return pos; + if (is_separator (*s)) + return s; } - return string_type::npos; + return nullptr; } static size_type @@ -360,10 +367,10 @@ namespace butl public: bool - empty () const - { - return this->path_.empty (); - } + empty () const {return this->path_.empty ();} + + size_type + size () const {return this->path_.size ();} // Return true if this path doesn't have any directories. Note // that "/foo" is not a simple path (it is "foo" in root directory) @@ -562,6 +569,15 @@ namespace butl basic_path& operator/= (basic_path const&); + // Append a single path component (must not contain directory separators) + // as a string, without first constructing the path object. + // + basic_path& + operator/= (string_type const&); + + basic_path& + operator/= (const C*); + basic_path operator+ (string_type const& s) const { @@ -569,6 +585,12 @@ namespace butl } basic_path + operator+ (const C* s) const + { + return basic_path (this->path_ + s); + } + + basic_path operator+ (C c) const { return basic_path (this->path_ + c); @@ -582,6 +604,13 @@ namespace butl } basic_path& + operator+= (const C* s) + { + this->path_ += s; + return *this; + } + + basic_path& operator+= (C c) { this->path_ += c; @@ -622,6 +651,11 @@ namespace butl init (this->path_); } + // Common implementation for operator=/(). + // + void + combine (const C*, size_type); + private: template <class P, class C1, class K1> friend P butl::path_cast (const basic_path<C1, K1>&); @@ -648,6 +682,24 @@ namespace butl return r; } + template <typename C, typename K> + inline basic_path<C, K> + operator/ (basic_path<C, K> const& x, std::basic_string<C> const& y) + { + basic_path<C, K> r (x); + r /= y; + return r; + } + + template <typename C, typename K> + inline basic_path<C, K> + operator/ (basic_path<C, K> const& x, const C* y) + { + basic_path<C, K> r (x); + r /= y; + return r; + } + template <typename C, typename K1, typename K2> inline bool operator== (const basic_path<C, K1>& x, const basic_path<C, K2>& y) diff --git a/butl/path.ixx b/butl/path.ixx index 1628ece..48d6576 100644 --- a/butl/path.ixx +++ b/butl/path.ixx @@ -233,4 +233,19 @@ namespace butl return string (); } #endif + + template <typename C, typename K> + inline void basic_path<C, K>:: + combine (const C* r, size_type rn) + { + size_type ln (this->path_.size ()); + + if (ln != 0 && rn != 0) + { + if (!traits::is_separator (this->path_[ln - 1])) + this->path_ += traits::directory_separator; + } + + this->path_.append (r, rn); + } } diff --git a/butl/path.txx b/butl/path.txx index 35c6956..94fbd90 100644 --- a/butl/path.txx +++ b/butl/path.txx @@ -61,16 +61,31 @@ namespace butl if (r.absolute () && !this->path_.empty ()) // Allow ('' / '/foo'). throw invalid_basic_path<C> (r.path_); - if (this->path_.empty () || r.path_.empty ()) - { - this->path_ += r.path_; - return *this; - } + combine (r.path_.c_str (), r.path_.size ()); + return *this; + } + + template <typename C, typename K> + basic_path<C, K>& basic_path<C, K>:: + operator/= (string_type const& r) + { + if (traits::find_separator (r) != string_type::npos) + throw invalid_basic_path<C> (r); + + combine (r.c_str (), r.size ()); + return *this; + } + + template <typename C, typename K> + basic_path<C, K>& basic_path<C, K>:: + operator/= (const C* r) + { + size_type rn (string_type::traits_type::length (r)); - if (!traits::is_separator (this->path_[this->path_.size () - 1])) - this->path_ += traits::directory_separator; + if (traits::find_separator (r, rn) != nullptr) + throw invalid_basic_path<C> (r); - this->path_ += r.path_; + combine (r, rn); return *this; } |