nar-accessor: non-recursive NarMember::find
This avoids a possible stack overflow if directories are very deeply nested.
This commit is contained in:
parent
4412f7c083
commit
5ee06e612a
|
@ -21,25 +21,6 @@ struct NarMember
|
||||||
|
|
||||||
/* If this is a directory, all the children of the directory. */
|
/* If this is a directory, all the children of the directory. */
|
||||||
std::map<std::string, NarMember> children;
|
std::map<std::string, NarMember> children;
|
||||||
|
|
||||||
NarMember* find(const Path & path)
|
|
||||||
{
|
|
||||||
if(path == "") return this;
|
|
||||||
|
|
||||||
if(type != FSAccessor::Type::tDirectory) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto split = std::find(path.begin() + 1, path.end(), '/');
|
|
||||||
std::string child_name(path.begin() + 1, split);
|
|
||||||
std::string remaining(split, path.end());
|
|
||||||
|
|
||||||
auto child = children.find(child_name);
|
|
||||||
if(child == children.end()) return nullptr;
|
|
||||||
|
|
||||||
return child->second.find(remaining);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NarIndexer : ParseSink, StringSource
|
struct NarIndexer : ParseSink, StringSource
|
||||||
|
@ -114,8 +95,27 @@ struct NarIndexer : ParseSink, StringSource
|
||||||
NarMember* find(const Path & path)
|
NarMember* find(const Path & path)
|
||||||
{
|
{
|
||||||
Path canon = path == "" ? "" : canonPath(path);
|
Path canon = path == "" ? "" : canonPath(path);
|
||||||
NarMember* result = root.find(canon);
|
NarMember* current = &root;
|
||||||
return result;
|
auto end = path.end();
|
||||||
|
for(auto it = path.begin(); it != end; ) {
|
||||||
|
// because it != end, the remaining component is non-empty so we need
|
||||||
|
// a directory
|
||||||
|
if(current->type != FSAccessor::Type::tDirectory) return nullptr;
|
||||||
|
|
||||||
|
// skip slash (canonPath above ensures that this is always a slash)
|
||||||
|
assert(*it == '/');
|
||||||
|
it += 1;
|
||||||
|
|
||||||
|
// lookup current component
|
||||||
|
auto next = std::find(it, end, '/');
|
||||||
|
auto child = current->children.find(std::string(it, next));
|
||||||
|
if(child == current->children.end()) return nullptr;
|
||||||
|
current = &child->second;
|
||||||
|
|
||||||
|
it = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return current;
|
||||||
}
|
}
|
||||||
|
|
||||||
NarMember& at(const Path & path) {
|
NarMember& at(const Path & path) {
|
||||||
|
|
Loading…
Reference in a new issue