vfs: trace, extract

This commit is contained in:
2018-11-23 18:49:44 +07:00
parent f1299a2a7e
commit 827c667b88
4 changed files with 112 additions and 2 deletions

View File

@@ -30,6 +30,7 @@ namespace e2d
virtual input_stream_uptr open(str_view path) const = 0;
virtual std::pair<buffer,bool> load(str_view path) const = 0;
virtual output_stream_uptr write(str_view path, bool append) const = 0;
virtual bool trace(str_view path, filesystem::trace_func func) const = 0;
};
using file_source_uptr = std::unique_ptr<file_source>;
@@ -47,6 +48,10 @@ namespace e2d
output_stream_uptr write(const url& url, bool append) const;
std::future<std::pair<buffer,bool>> load_async(const url& url) const;
template < typename Iter >
bool extract(const url& url, Iter result_iter) const;
bool trace(const url& url, filesystem::trace_func func) const;
url resolve_scheme_aliases(const url& url) const;
private:
class state;
@@ -62,6 +67,7 @@ namespace e2d
input_stream_uptr open(str_view path) const final;
std::pair<buffer,bool> load(str_view path) const final;
output_stream_uptr write(str_view path, bool append) const final;
bool trace(str_view path, filesystem::trace_func func) const final;
private:
class state;
std::unique_ptr<state> state_;
@@ -76,6 +82,7 @@ namespace e2d
input_stream_uptr open(str_view path) const final;
std::pair<buffer,bool> load(str_view path) const final;
output_stream_uptr write(str_view path, bool append) const final;
bool trace(str_view path, filesystem::trace_func func) const final;
};
}
@@ -87,4 +94,12 @@ namespace e2d
scheme,
std::make_unique<T>(std::forward<Args>(args)...));
}
template < typename Iter >
bool vfs::extract(const url& url, Iter result_iter) const {
return trace(url, [&result_iter](str_view filename, bool directory){
*result_iter++ = std::pair<str,bool>{filename, directory};
return true;
});
}
}

View File

@@ -173,6 +173,14 @@ namespace e2d
}, open(url));
}
bool vfs::trace(const url& url, filesystem::trace_func func) const {
std::lock_guard<std::mutex> guard(state_->mutex);
return state_->with_file_source(url,
[&func](const file_source_uptr& source, const str& path) {
return source->trace(path, func);
}, false);
}
url vfs::resolve_scheme_aliases(const url& url) const {
std::lock_guard<std::mutex> guard(state_->mutex);
return state_->resolve_url(url);
@@ -276,6 +284,46 @@ namespace e2d
return nullptr;
}
bool archive_file_source::trace(str_view path, filesystem::trace_func func) const {
str parent = make_utf8(path);
if ( !parent.empty() ) {
if ( parent.back() != '/' ) {
parent += '/';
}
mz_uint32 dir_index = 0;
if ( !mz_zip_reader_locate_file_v2(
state_->archive.get(),
parent.c_str(),
nullptr,
MZ_ZIP_FLAG_CASE_SENSITIVE,
&dir_index) )
{
return false;
}
mz_zip_archive_file_stat dir_stat;
if ( !mz_zip_reader_file_stat(
state_->archive.get(),
dir_index, &dir_stat) )
{
return false;
}
if ( !dir_stat.m_is_directory ) {
return false;
}
}
mz_uint num_files = mz_zip_reader_get_num_files(state_->archive.get());
for ( mz_uint i = 0; i < num_files; ++i ) {
mz_zip_archive_file_stat file_stat;
if ( mz_zip_reader_file_stat(state_->archive.get(), i, &file_stat) ) {
const str_view filename{file_stat.m_filename};
if ( filename.length() > parent.length() && filename.starts_with(parent) ) {
func(file_stat.m_filename, file_stat.m_is_directory);
}
}
}
return true;
}
//
// filesystem_file_source
//
@@ -308,4 +356,8 @@ namespace e2d
}
return make_write_file(path, append);
}
bool filesystem_file_source::trace(str_view path, filesystem::trace_func func) const {
return filesystem::trace_directory_recursive(path, func);
}
}

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:c72ff0ca4cd5c914d557f6e1c08c1f63f7d4da3339c15f1c2b5def5fe13d32d2
size 440
oid sha256:7f9dbd20a52c39630253723d3e5c0f478c8cd70de48048966c0ca5becaa97fe3
size 1423

View File

@@ -78,6 +78,49 @@ TEST_CASE("vfs"){
REQUIRE_FALSE(v.exists({"archive", "test2.txt"}));
REQUIRE_FALSE(v.exists({"archive", "folder/file2.txt"}));
{
vector<std::pair<str,bool>> result;
REQUIRE(v.extract(url("archive://"), std::back_inserter(result)));
REQUIRE(result == vector<std::pair<str, bool>>{
{"folder/", true},
{"folder/file.txt", false},
{"test.txt", false},
{"folder/subfolder/", true},
{"folder/subfolder/file.txt", false},
{"folder2/", true},
{"folder2/file.txt", false},
{"folder2/subfolder2/", true},
{"folder2/subfolder2/file.txt", false}
});
}
{
vector<std::pair<str,bool>> result;
REQUIRE(v.extract(url("archive://folder"), std::back_inserter(result)));
REQUIRE(result == vector<std::pair<str, bool>>{
{"folder/file.txt", false},
{"folder/subfolder/", true},
{"folder/subfolder/file.txt", false}
});
}
{
vector<std::pair<str,bool>> result;
REQUIRE(v.extract(url("archive://folder2/subfolder2"), std::back_inserter(result)));
REQUIRE(result == vector<std::pair<str, bool>>{
{"folder2/subfolder2/file.txt", false}
});
}
{
vector<std::pair<str,bool>> result, result2;
REQUIRE(v.extract(url("archive://folder"), std::back_inserter(result)));
REQUIRE(v.extract(url("archive://folder/"), std::back_inserter(result2)));
REQUIRE(result == result2);
}
{
vector<std::pair<str,bool>> result;
REQUIRE_FALSE(v.extract(url("archive://fold"), std::back_inserter(result)));
REQUIRE_FALSE(v.extract(url("archive://folder3"), std::back_inserter(result)));
REQUIRE_FALSE(v.extract(url("archive://test.txt"), std::back_inserter(result)));
}
{
auto f = v.open(url("archive://test.txt"));
REQUIRE(f);