diff --git a/include/dwarfs/filesystem_v2.h b/include/dwarfs/filesystem_v2.h index 348a0de1..62b013c3 100644 --- a/include/dwarfs/filesystem_v2.h +++ b/include/dwarfs/filesystem_v2.h @@ -87,6 +87,15 @@ class filesystem_v2 { impl_->walk(func); } + void walk_inode_order(std::function const& func) const { + impl_->walk_inode_order(func); + } + + void walk_inode_order( + std::function const& func) const { + impl_->walk_inode_order(func); + } + std::optional find(const char* path) const { return impl_->find(path); } @@ -147,6 +156,10 @@ class filesystem_v2 { virtual void walk(std::function const& func) const = 0; virtual void walk(std::function const& func) const = 0; + virtual void + walk_inode_order(std::function const& func) const = 0; + virtual void walk_inode_order( + std::function const& func) const = 0; virtual std::optional find(const char* path) const = 0; virtual std::optional find(int inode) const = 0; virtual std::optional diff --git a/include/dwarfs/metadata_v2.h b/include/dwarfs/metadata_v2.h index ed865d31..c5d206f1 100644 --- a/include/dwarfs/metadata_v2.h +++ b/include/dwarfs/metadata_v2.h @@ -91,6 +91,15 @@ class metadata_v2 { impl_->walk(func); } + void walk_inode_order(std::function const& func) const { + impl_->walk_inode_order(func); + } + + void walk_inode_order( + std::function const& func) const { + impl_->walk_inode_order(func); + } + std::optional find(const char* path) const { return impl_->find(path); } @@ -159,6 +168,11 @@ class metadata_v2 { virtual void walk(std::function const& func) const = 0; + virtual void + walk_inode_order(std::function const& func) const = 0; + virtual void walk_inode_order( + std::function const& func) const = 0; + virtual std::optional find(const char* path) const = 0; virtual std::optional find(int inode) const = 0; virtual std::optional diff --git a/src/dwarfs/filesystem_v2.cpp b/src/dwarfs/filesystem_v2.cpp index 354ab9ea..688df457 100644 --- a/src/dwarfs/filesystem_v2.cpp +++ b/src/dwarfs/filesystem_v2.cpp @@ -186,6 +186,11 @@ class filesystem_ : public filesystem_v2::impl { void walk(std::function const& func) const override; void walk(std::function const& func) const override; + void + walk_inode_order(std::function const& func) const override; + void + walk_inode_order(std::function const& func) + const override; std::optional find(const char* path) const override; std::optional find(int inode) const override; std::optional find(int inode, const char* name) const override; @@ -290,6 +295,18 @@ void filesystem_::walk( meta_.walk(func); } +template +void filesystem_::walk_inode_order( + std::function const& func) const { + meta_.walk_inode_order(func); +} + +template +void filesystem_::walk_inode_order( + std::function const& func) const { + meta_.walk_inode_order(func); +} + template std::optional filesystem_::find(const char* path) const { diff --git a/src/dwarfs/metadata_v2.cpp b/src/dwarfs/metadata_v2.cpp index 9b2dc4b3..2e4d3aca 100644 --- a/src/dwarfs/metadata_v2.cpp +++ b/src/dwarfs/metadata_v2.cpp @@ -183,6 +183,12 @@ class metadata_ : public metadata_v2::impl { void walk(std::function const& func) const override; + void + walk_inode_order(std::function const& func) const override; + void + walk_inode_order(std::function const& func) + const override; + std::optional find(const char* path) const override; std::optional find(int inode) const override; std::optional find(int inode, const char* name) const override; @@ -337,20 +343,25 @@ class metadata_ : public metadata_v2::impl { } } - static void walk_call(std::function const& func, - entry_view entry, directory_view) { - func(entry); + void walk_call(std::function const& func, uint32_t entry, + uint32_t) const { + func(make_entry_view(entry)); } - static void - walk_call(std::function const& func, - entry_view entry, directory_view dir) { - func(entry, dir); + void walk_call(std::function const& func, + uint32_t entry, uint32_t dir) const { + func(make_entry_view(entry), make_directory_view(make_entry_view(dir))); } + template + void walk(uint32_t parent_ix, uint32_t entry_ix, set_type& seen, + T&& func) const; + template - void walk(directory_view parent, entry_view entry, set_type& seen, - std::function const& func) const; + void walk_impl(std::function const& func) const; + + template + void walk_inode_order_impl(std::function const& func) const; std::optional get_entry(int inode) const { inode -= inode_offset_; @@ -590,11 +601,11 @@ std::string metadata_::modestring(uint16_t mode) const { } template -template -void metadata_::walk(directory_view parent, entry_view entry, - set_type& seen, - std::function const& func) const { - walk_call(func, entry, parent); +template +void metadata_::walk(uint32_t parent_ix, uint32_t entry_ix, + set_type& seen, T&& func) const { + func(entry_ix, parent_ix); + auto entry = make_entry_view(entry_ix); if (S_ISDIR(entry.mode())) { auto inode = entry.inode(); if (!seen.emplace(inode).second) { @@ -602,24 +613,64 @@ void metadata_::walk(directory_view parent, entry_view entry, } auto dir = make_directory_view(entry); for (auto cur : dir.entry_range()) { - walk(dir, make_entry_view(cur), seen, func); + walk(entry_ix, cur, seen, func); } seen.erase(inode); } } +template +template +void metadata_::walk_impl( + std::function const& func) const { + set_type seen; + walk( + meta_.entry_index()[0], meta_.entry_index()[0], seen, + [&](uint32_t entry, uint32_t parent) { walk_call(func, entry, parent); }); +} + template void metadata_::walk( std::function const& func) const { - set_type seen; - walk(make_directory_view(root_), root_, seen, func); + walk_impl(func); } template void metadata_::walk( std::function const& func) const { + walk_impl(func); +} + +template +template +void metadata_::walk_inode_order_impl( + std::function const& func) const { + std::vector> entries; set_type seen; - walk(make_directory_view(root_), root_, seen, func); + walk(meta_.entry_index()[0], meta_.entry_index()[0], seen, + [&](uint32_t entry_ix, uint32_t parent_ix) { + entries.emplace_back(entry_ix, parent_ix); + }); + std::sort(entries.begin(), entries.end(), + [this](auto const& a, auto const& b) { + return meta_.entries()[a.first].inode() < + meta_.entries()[b.first].inode(); + }); + for (auto [entry, parent] : entries) { + walk_call(func, entry, parent); + } +} + +template +void metadata_::walk_inode_order( + std::function const& func) const { + walk_inode_order_impl(func); +} + +template +void metadata_::walk_inode_order( + std::function const& func) const { + walk_inode_order_impl(func); } template