// 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 #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 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 using path_map = prefix_map; template using dir_path_map = prefix_map; } #endif // BUTL_PATH_MAP