From 89bc63fb386f0e4d6e2b21c0d806da1e8de0a34d Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 19 Jan 2018 09:05:51 +0200 Subject: Add path::make_{directory,leaf,base}() --- libbutl/path.ixx | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ libbutl/path.mxx | 24 +++++++++++++++++-- 2 files changed, 95 insertions(+), 2 deletions(-) diff --git a/libbutl/path.ixx b/libbutl/path.ixx index f86a57e..b754bed 100644 --- a/libbutl/path.ixx +++ b/libbutl/path.ixx @@ -150,6 +150,10 @@ LIBBUTL_MODEXPORT namespace butl //@@ MOD Clang needs this for some reason. inline basic_path basic_path:: leaf () const { + // While it would have been simpler to implement this one in term of + // make_leaf(), this implementation is potentially more efficient + // (think of the small string optimization). + // const string_type& s (this->path_); size_type n (_size ()); @@ -163,9 +167,37 @@ LIBBUTL_MODEXPORT namespace butl //@@ MOD Clang needs this for some reason. } template + inline basic_path& basic_path:: + make_leaf () + { + string_type& s (this->path_); + size_type n (_size ()); + + size_type p (n != 0 + ? traits::rfind_separator (s, n - 1) + : string_type::npos); + + if (p != string_type::npos) + { + s.erase (0, p + 1); + + // Keep the original tsep unless the path became empty. + // + if (s.empty ()) + this->tsep_ = 0; + } + + return *this; + } + + template inline typename basic_path::dir_type basic_path:: directory () const { + // While it would have been simpler to implement this one in term of + // make_directory(), this implementation is potentially more efficient + // (think of the small string optimization). + // const string_type& s (this->path_); size_type n (_size ()); @@ -179,6 +211,23 @@ LIBBUTL_MODEXPORT namespace butl //@@ MOD Clang needs this for some reason. } template + inline basic_path& basic_path:: + make_directory () + { + string_type& s (this->path_); + size_type n (_size ()); + + size_type p (n != 0 + ? traits::rfind_separator (s, n - 1) + : string_type::npos); + + s.resize (p != string_type::npos ? p + 1 : 0); // Include trailing slash. + _init (); + + return *this; + } + + template inline auto basic_path:: begin () const -> iterator { @@ -279,6 +328,10 @@ LIBBUTL_MODEXPORT namespace butl //@@ MOD Clang needs this for some reason. inline basic_path basic_path:: base () const { + // While it would have been simpler to implement this one in term of + // make_base(), this implementation is potentially more efficient (think + // of the small string optimization). + // const string_type& s (this->path_); size_type p (traits::find_extension (s)); @@ -288,6 +341,26 @@ LIBBUTL_MODEXPORT namespace butl //@@ MOD Clang needs this for some reason. } template + inline basic_path& basic_path:: + make_base () + { + string_type& s (this->path_); + size_type p (traits::find_extension (s)); + + if (p != string_type::npos) + { + s.resize (0, p); + + // Keep the original tsep unless the path became empty. + // + if (s.empty ()) + this->tsep_ = 0; + } + + return *this; + } + + template inline typename basic_path::string_type basic_path:: extension () const { diff --git a/libbutl/path.mxx b/libbutl/path.mxx index 520453a..01fa0fc 100644 --- a/libbutl/path.mxx +++ b/libbutl/path.mxx @@ -510,14 +510,18 @@ LIBBUTL_MODEXPORT namespace butl // Constructors. // - path_data (): tsep_ (0) {} + path_data () + : tsep_ (0) {} path_data (string_type&& p, difference_type ts) : path_ (std::move (p)), tsep_ (path_.empty () ? 0 : ts) {} explicit path_data (string_type&& p) - : path_ (std::move (p)), tsep_ (0) + : path_ (std::move (p)) { _init (); } + + void + _init () { size_type n (path_.size ()), i; @@ -531,6 +535,8 @@ LIBBUTL_MODEXPORT namespace butl path_.pop_back (); } } + else + tsep_ = 0; } }; @@ -764,6 +770,11 @@ LIBBUTL_MODEXPORT namespace butl basic_path leaf () const; + // As above but make the instance itself the leaf. Return *this. + // + basic_path& + make_leaf (); + // Return the path without the specified directory part. Throws // invalid_path if the directory is not a prefix of *this. Expects both // paths to be normalized. @@ -777,6 +788,11 @@ LIBBUTL_MODEXPORT namespace butl dir_type directory () const; + // As above but make the instance itself the directory. Return *this. + // + basic_path& + make_directory (); + // Return the directory part of the path without the specified leaf part. // Throws invalid_path if the leaf is not a suffix of *this. Expects both // paths to be normalized. @@ -795,6 +811,9 @@ LIBBUTL_MODEXPORT namespace butl basic_path base () const; + basic_path& + make_base (); + // Return the extension or empty string if not present. If not empty, then // the result starts with the character past the dot. // @@ -1081,6 +1100,7 @@ LIBBUTL_MODEXPORT namespace butl basic_path (data_type&& d): base_type (std::move (d)) {} using base_type::_size; + using base_type::_init; // Common implementation for operator/= and operator+=. // -- cgit v1.1