// file : butl/path-map -*- C++ -*- // copyright : Copyright (c) 2014-2016 Code Synthesis Ltd // license : MIT; see accompanying LICENSE file #ifndef BUTL_PATH_MAP #define BUTL_PATH_MAP #include #include 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 struct compare_prefix>: compare_prefix> { typedef basic_path key_type; typedef C delimiter_type; typedef std::basic_string string_type; typedef compare_prefix> base; explicit compare_prefix (delimiter_type d): base (d) {} bool operator() (const key_type& x, const key_type& y) const { const string_type& xs (x.string ()); const string_type& ys (y.string ()); return base::compare (xs.c_str (), root (xs) ? 0 : xs.size (), ys.c_str (), root (ys) ? 0 : ys.size ()) < 0; } bool prefix (const key_type& p, const key_type& k) const { const string_type& ps (p.string ()); const string_type& ks (k.string ()); return base::prefix (root (ps) ? string_type () : ps, root (ks) ? string_type () : ks); } protected: static bool root (const string_type& p) { return p.size () == 1 && key_type::traits::is_separator (p[0]); } }; template using path_map = prefix_map; template using dir_path_map = prefix_map; } #endif // BUTL_PATH_MAP