# # # patch "paths.hh" # from [3d1de2d3c8fa9008734e67e842e4978459dbbca6] # to [da4234713de13f25872f19199aedd53a3b954be3] # # patch "roster.cc" # from [b0be9f64968bba7a9b4bb492959a052911c25614] # to [c06c6511adc1f102a95323b179f00a2ce022ed2d] # ============================================================ --- paths.hh 3d1de2d3c8fa9008734e67e842e4978459dbbca6 +++ paths.hh da4234713de13f25872f19199aedd53a3b954be3 @@ -133,8 +133,7 @@ private: private: utf8 data; - // constructor for use by trusted any_path and file_path operations. - // bypasses validation. + // constructor for use by trusted operations. bypasses validation. path_component(std::string const & path, std::string::size_type start, std::string::size_type stop = std::string::npos) @@ -143,6 +142,7 @@ private: friend class any_path; friend class file_path; + friend class roster_t; }; std::ostream & operator<<(std::ostream &, path_component const &); template <> void dump(path_component const &, std::string &); ============================================================ --- roster.cc b0be9f64968bba7a9b4bb492959a052911c25614 +++ roster.cc c06c6511adc1f102a95323b179f00a2ce022ed2d @@ -577,40 +577,33 @@ equal_shapes(roster_t const & a, roster_ return true; } -// this logic is common to get_node and has_node. the return is NULL if the -// target node does not exist. -static node_t -get_node_worker(roster_t const & r, file_path const & p) -{ - if (p.empty()) - return r.root(); - - file_path dir; - path_component base; - p.dirname_basename(dir, base); - - node_t parent = get_node_worker(r, dir); - if (!parent || !is_dir_t(parent)) - return node_t(); - - dir_t pd = downcast_to_dir_t(parent); - dir_map::const_iterator child = pd->children.find(base); - if (child == pd->children.end()) - return node_t(); - - return child->second; -} - node_t roster_t::get_node(file_path const & p) const { MM(*this); MM(p); + I(has_root()); + if (p.empty()) + return root_dir; - node_t n = get_node_worker(*this, p); - I(n); - return n; + dir_t nd = root_dir; + string const & pi = p.as_internal(); + string::size_type start = 0, stop; + for (;;) + { + stop = pi.find('/', start); + path_component pc(pi, start, (stop == string::npos + ? stop : stop - start)); + dir_map::const_iterator child = nd->children.find(pc); + + I(child != nd->children.end()); + if (stop == string::npos) + return child->second; + + start = stop + 1; + nd = downcast_to_dir_t(child->second); + } } bool @@ -630,10 +623,34 @@ roster_t::has_node(file_path const & p) { MM(*this); MM(p); - return static_cast(get_node_worker(*this, p)); -} + if (!has_root()) + return false; + if (p.empty()) + return true; + + dir_t nd = root_dir; + string const & pi = p.as_internal(); + string::size_type start = 0, stop; + for (;;) + { + stop = pi.find('/', start); + path_component pc(pi, start, (stop == string::npos + ? stop : stop - start)); + dir_map::const_iterator child = nd->children.find(pc); + if (child == nd->children.end()) + return false; + if (stop == string::npos) + return true; + if (!is_dir_t(child->second)) + return false; + + start = stop + 1; + nd = downcast_to_dir_t(child->second); + } +} + node_t roster_t::get_node(node_id nid) const { @@ -646,13 +663,13 @@ roster_t::get_name(node_id nid, file_pat { I(!null_node(nid)); - stack sp; + stack sp; size_t size = 0; while (nid != root_dir->self) { node_t n = get_node(nid); - sp.push(n->name); + sp.push(n); size += n->name().length() + 1; nid = n->parent; } @@ -663,14 +680,14 @@ roster_t::get_name(node_id nid, file_pat return; } - I(!bookkeeping_path::internal_string_is_bookkeeping_path(utf8(sp.top()()))); + I(!bookkeeping_path::internal_string_is_bookkeeping_path(utf8(sp.top()->name()))); string tmp; tmp.reserve(size); for (;;) { - tmp += sp.top()(); + tmp += sp.top()->name(); sp.pop(); if (sp.empty()) break;