aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2015-07-14 10:26:32 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2015-07-14 10:26:32 +0200
commit5b9b8d3dadf8471ff3a722fe714bd0900fc6c7ba (patch)
tree9bd7aa37f3ea121eb8f90e47d9b686c6455a35ea
parent80b4ee65c55c896f12109c338ba9aa386b5719c6 (diff)
Add path iterator range constructor
-rw-r--r--butl/path11
-rw-r--r--butl/path.ixx20
-rw-r--r--tests/path/driver.cxx36
3 files changed, 66 insertions, 1 deletions
diff --git a/butl/path b/butl/path
index 5462cc9..5f6d063 100644
--- a/butl/path
+++ b/butl/path
@@ -235,6 +235,8 @@ namespace butl
typedef path_traits<C> traits;
+ struct iterator;
+
// Construct special empty path. Note that we have to provide our
// own implementation rather than using '=default' to make clang
// allow default-initialized const instances of this type.
@@ -256,6 +258,11 @@ namespace butl
basic_path (const string_type& s, size_type p, size_type n)
: base_type (string_type (s, p, n)) {init ();}
+ // Create a path as a sub-path identified by the [begin, end)
+ // range of components.
+ //
+ basic_path (const iterator& begin, const iterator& end);
+
void
swap (basic_path& p)
{
@@ -399,7 +406,7 @@ namespace butl
}
iterator
- operator++ (int) {iterator r (*this); return ++r;}
+ operator++ (int) const {iterator r (*this); return ++r;}
string_type operator* () const
{
@@ -416,6 +423,8 @@ namespace butl
operator!= (const iterator& x, const iterator& y) {return !(x == y);}
private:
+ friend class basic_path;
+
// b != npos && e == npos - last component
// b == npos && e == npos - one past last component (end)
//
diff --git a/butl/path.ixx b/butl/path.ixx
index 3e8a9cc..7ce8c63 100644
--- a/butl/path.ixx
+++ b/butl/path.ixx
@@ -147,6 +147,26 @@ namespace butl
}
template <typename C, typename K>
+ inline basic_path<C, K>::
+ 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 <typename C, typename K>
inline basic_path<C, K>& basic_path<C, K>::
complete ()
{
diff --git a/tests/path/driver.cxx b/tests/path/driver.cxx
index c83fd12..302968d 100644
--- a/tests/path/driver.cxx
+++ b/tests/path/driver.cxx
@@ -112,12 +112,48 @@ main ()
assert (++i != p.end () && *i == "bar");
assert (++i == p.end ());
}
+#ifndef _WIN32
{
path p ("/");
path::iterator i (p.begin ());
assert (i != p.end () && *i == "");
assert (++i == p.end ());
}
+#endif
+
+ // iterator range construction
+ //
+ {
+ path p;
+ assert (path (p.begin (), p.end ()) == p);
+ }
+ {
+ path p ("foo");
+ assert (path (p.begin (), p.end ()) == p);
+ assert (path (p.begin ()++, p.end ()) == path ());
+ }
+ {
+ path p ("foo/bar");
+ assert (path (p.begin (), p.end ()) == p);
+ assert (path (p.begin ()++, p.end ()) == path ("bar"));
+ assert (path (p.begin (), p.begin ()++) == path ("foo"));
+ }
+ {
+ path p ("/foo/bar");
+ assert (path (p.begin (), p.end ()) == p);
+ assert (path (p.begin ()++, p.end ()) == path ("foo/bar"));
+ assert (path ((p.begin ()++)++, p.end ()) == path ("bar"));
+ assert (path (p.begin (), p.begin ()++) == path ("/"));
+ assert (path (p.begin ()++, (p.begin ()++)++) == path ("foo"));
+ assert (path ((p.begin ()++)++, ((p.begin ()++)++)++) == path ("bar"));
+ }
+#ifndef _WIN32
+ {
+ path p ("/");
+ assert (path (p.begin (), p.end ()) == p);
+ assert (path (p.begin ()++, p.end ()) == path ());
+ }
+#endif
// operator/
//