diff options
Diffstat (limited to 'butl/path-map')
-rw-r--r-- | butl/path-map | 81 |
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 |