From 288718b4977058bdcf692422173f3642b0aa4d1d Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Mon, 29 Jun 2020 12:10:04 +0200 Subject: Add path::combine(string,separator) In particular, this can be used to recombine a path during iteration: dir_path r; for (auto i (d.begin ()); i != d.end (); ++i) r.combine (*i, i.separator ()); --- libbutl/path.mxx | 40 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) (limited to 'libbutl/path.mxx') diff --git a/libbutl/path.mxx b/libbutl/path.mxx index 136f361..1ee2a66 100644 --- a/libbutl/path.mxx +++ b/libbutl/path.mxx @@ -72,11 +72,15 @@ LIBBUTL_MODEXPORT namespace butl struct invalid_basic_path: invalid_path_base { using string_type = std::basic_string; + using size_type = typename string_type::size_type; string_type path; - invalid_basic_path (const C* p): path (p) {} + explicit invalid_basic_path (const string_type& p): path (p) {} + explicit + invalid_basic_path (const C* p): path (p) {} + invalid_basic_path (const C* p, size_type n): path (p, n) {} }; enum class path_abnormality: std::uint16_t @@ -943,6 +947,16 @@ LIBBUTL_MODEXPORT namespace butl // Iteration over path components. // + // Note that for an absolute POSIX path the first component is empty, + // not `/`. Which means recombining a path with operator/= is not going + // to work. Instead, do something along these lines: + // + // dir_path r; + // for (auto i (d.begin ()); i != d.end (); ++i) + // r.combine (*i, i.separator ()); + // + // @@ TODO: would be nice to skip consecutive separators (foo//bar). + // public: struct iterator { @@ -1022,6 +1036,8 @@ LIBBUTL_MODEXPORT namespace butl iterator operator-- (int) {iterator r (*this); operator-- (); return r;} + // @@ TODO: this should return string_view. + // string_type operator* () const { @@ -1137,11 +1153,14 @@ LIBBUTL_MODEXPORT namespace butl realize (); public: + // Combine two paths. Note: empty path on RHS has no effect. + // basic_path& operator/= (basic_path const&); // Combine a single path component (must not contain directory separators) - // as a string, without first constructing the path object. + // as a string, without first constructing the path object. Note: empty + // string has no effect. // basic_path& operator/= (string_type const&); @@ -1149,6 +1168,19 @@ LIBBUTL_MODEXPORT namespace butl basic_path& operator/= (const C*); + // As above but with an optional separator after the component. Note that + // if the LHS is empty and the string is empty but the separator is not + // '\0', then on POSIX this is treated as a root component. + // + void + combine (string_type const&, C separator); + + void + combine (const C*, C separator); + + void + combine (const C*, size_type, C separator); + // Append to the end of the path (normally an extension, etc). // basic_path& @@ -1240,10 +1272,10 @@ LIBBUTL_MODEXPORT namespace butl // Common implementation for operator/=. // void - combine (const C*, size_type, difference_type); + combine_impl (const C*, size_type, difference_type); void - combine (const C*, size_type); + combine_impl (const C*, size_type); // Friends. // -- cgit v1.1