aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2018-01-19 09:05:51 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2018-01-19 09:05:51 +0200
commit89bc63fb386f0e4d6e2b21c0d806da1e8de0a34d (patch)
tree94e95a3a79e73e6d076f5f19fe7a5ac0e0841506
parente3bf8b04654d4131be6ea4be670e66827b489d2e (diff)
Add path::make_{directory,leaf,base}()
-rw-r--r--libbutl/path.ixx73
-rw-r--r--libbutl/path.mxx24
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<C, K> basic_path<C, K>::
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 <typename C, typename K>
+ inline basic_path<C, K>& basic_path<C, K>::
+ 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 <typename C, typename K>
inline typename basic_path<C, K>::dir_type basic_path<C, K>::
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 <typename C, typename K>
+ inline basic_path<C, K>& basic_path<C, K>::
+ 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 <typename C, typename K>
inline auto basic_path<C, K>::
begin () const -> iterator
{
@@ -279,6 +328,10 @@ LIBBUTL_MODEXPORT namespace butl //@@ MOD Clang needs this for some reason.
inline basic_path<C, K> basic_path<C, K>::
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 <typename C, typename K>
+ inline basic_path<C, K>& basic_path<C, K>::
+ 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 <typename C, typename K>
inline typename basic_path<C, K>::string_type basic_path<C, K>::
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+=.
//