aboutsummaryrefslogtreecommitdiff
path: root/butl/path-map
diff options
context:
space:
mode:
Diffstat (limited to 'butl/path-map')
-rw-r--r--butl/path-map81
1 files changed, 81 insertions, 0 deletions
diff --git a/butl/path-map b/butl/path-map
new file mode 100644
index 0000000..101a2a9
--- /dev/null
+++ b/butl/path-map
@@ -0,0 +1,81 @@
+// file : butl/path-map -*- C++ -*-
+// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd
+// license : MIT; see accompanying LICENSE file
+
+#ifndef BUTL_PATH_MAP
+#define BUTL_PATH_MAP
+
+#include <butl/path>
+#include <butl/prefix-map>
+
+namespace butl
+{
+ // prefix_map for filesystem paths
+ //
+ // Important: the paths should be normalized and canonicalized.
+ //
+ // Note that the path's representation of POSIX root ('/') is
+ // inconsistent in that we have a trailing delimiter at the end of
+ // the path (its "proper" representation would have been an empty
+ // string but that would have clashed with empty paths). To work
+ // around this snag, this implementation, during key comparison,
+ // detects '/' and treats it as empty. Note that the map will
+ // still store the key as you have first inserted it. So if you
+ // want a particular representation (i.e., empty or '/'), pre-
+ // populate the map with it.
+ //
+ template <typename C, typename K>
+ struct compare_prefix<basic_path<C, K>>: compare_prefix<std::basic_string<C>>
+ {
+ typedef basic_path<C, K> key_type;
+
+ typedef C delimiter_type;
+ typedef std::basic_string<C> string_type;
+ typedef compare_prefix<std::basic_string<C>> base;
+
+ explicit
+ compare_prefix (delimiter_type d): base (d) {}
+
+ bool
+ operator() (const key_type& x, const key_type& y) const
+ {
+ const auto& xs (x.string ());
+ const auto& ys (y.string ());
+
+#ifdef _WIN32
+ return base::compare (xs.c_str (),
+ xs.size (),
+ ys.c_str (),
+ ys.size ()) < 0;
+#else
+ return base::compare (xs.c_str (),
+ x.root () ? 0 : xs.size (),
+ ys.c_str (),
+ y.root () ? 0 : ys.size ()) < 0;
+#endif
+ }
+
+ bool
+ prefix (const key_type& p, const key_type& k) const
+ {
+ const auto& ps (p.string ());
+ const auto& ks (k.string ());
+
+#ifdef _WIN32
+ return base::prefix (ps, ks);
+#else
+ return base::prefix (p.root () ? string_type () : ps,
+ k.root () ? string_type () : ks);
+#endif
+ }
+ };
+
+ template <typename T>
+ using path_map = prefix_map<path, T, path::traits::directory_separator>;
+
+ template <typename T>
+ using dir_path_map =
+ prefix_map<dir_path, T, dir_path::traits::directory_separator>;
+}
+
+#endif // BUTL_PATH_MAP