aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libbutl/path.mxx6
-rw-r--r--libbutl/path.txx16
2 files changed, 19 insertions, 3 deletions
diff --git a/libbutl/path.mxx b/libbutl/path.mxx
index 12479ce..5a41ddc 100644
--- a/libbutl/path.mxx
+++ b/libbutl/path.mxx
@@ -952,6 +952,12 @@ LIBBUTL_MODEXPORT namespace butl
basic_path
relative (basic_path) const;
+ // As above but return nullopt rather than throw if a relative path cannot
+ // be derived.
+ //
+ optional<basic_path>
+ try_relative (basic_path) const;
+
// Iteration over path components.
//
// Note that for an absolute POSIX path the first component is empty,
diff --git a/libbutl/path.txx b/libbutl/path.txx
index 45b62bd..84fc038 100644
--- a/libbutl/path.txx
+++ b/libbutl/path.txx
@@ -103,8 +103,8 @@ LIBBUTL_MODEXPORT namespace butl //@@ MOD Clang needs this for some reason.
#endif
template <typename C, typename K>
- basic_path<C, K> basic_path<C, K>::
- relative (basic_path<C, K> d) const
+ optional<basic_path<C, K>> basic_path<C, K>::
+ try_relative (basic_path<C, K> d) const
{
dir_type r;
@@ -118,12 +118,22 @@ LIBBUTL_MODEXPORT namespace butl //@@ MOD Clang needs this for some reason.
// Roots of the paths do not match.
//
if (d.root ())
- throw invalid_basic_path<C> (this->path_);
+ return nullopt;
}
return r / leaf (d);
}
+ template <typename C, typename K>
+ basic_path<C, K> basic_path<C, K>::
+ relative (basic_path<C, K> d) const
+ {
+ if (optional<basic_path<C, K>> r = try_relative (std::move (d)))
+ return std::move (*r);
+
+ throw invalid_basic_path<C> (this->path_);
+ }
+
#ifdef _WIN32
// Find the actual spelling of a name in the specified dir. If the name is
// found, append it to the result and return true. Otherwise, return false.