mirror of
https://github.com/enduro2d/enduro2d.git
synced 2025-12-15 00:11:55 +07:00
promises for async vfs operations
This commit is contained in:
125
headers/3rdparty/promise.hpp/promise.hpp
vendored
125
headers/3rdparty/promise.hpp/promise.hpp
vendored
@@ -178,16 +178,16 @@ namespace promise_hpp
|
|||||||
then([
|
then([
|
||||||
n = next,
|
n = next,
|
||||||
f = std::forward<ResolveF>(on_resolve)
|
f = std::forward<ResolveF>(on_resolve)
|
||||||
](const T& v) mutable {
|
](auto&& v) mutable {
|
||||||
auto np = invoke_hpp::invoke(
|
auto np = invoke_hpp::invoke(
|
||||||
std::forward<decltype(f)>(f),
|
std::forward<decltype(f)>(f),
|
||||||
v);
|
std::forward<decltype(v)>(v));
|
||||||
np.then([n]() mutable {
|
std::move(np).then([n]() mutable {
|
||||||
n.resolve();
|
n.resolve();
|
||||||
}, [n](std::exception_ptr e) mutable {
|
}).except([n](std::exception_ptr e) mutable {
|
||||||
n.reject(e);
|
n.reject(e);
|
||||||
});
|
});
|
||||||
}, [n = next](std::exception_ptr e) mutable {
|
}).except([n = next](std::exception_ptr e) mutable {
|
||||||
n.reject(e);
|
n.reject(e);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -205,16 +205,16 @@ namespace promise_hpp
|
|||||||
then([
|
then([
|
||||||
n = next,
|
n = next,
|
||||||
f = std::forward<ResolveF>(on_resolve)
|
f = std::forward<ResolveF>(on_resolve)
|
||||||
](const T& v) mutable {
|
](auto&& v) mutable {
|
||||||
auto np = invoke_hpp::invoke(
|
auto np = invoke_hpp::invoke(
|
||||||
std::forward<decltype(f)>(f),
|
std::forward<decltype(f)>(f),
|
||||||
v);
|
std::forward<decltype(v)>(v));
|
||||||
np.then([n](const typename ResolveFR::value_type& nv) mutable {
|
std::move(np).then([n](auto&& nv) mutable {
|
||||||
n.resolve(nv);
|
n.resolve(std::forward<decltype(nv)>(nv));
|
||||||
}, [n](std::exception_ptr e) mutable {
|
}).except([n](std::exception_ptr e) mutable {
|
||||||
n.reject(e);
|
n.reject(e);
|
||||||
});
|
});
|
||||||
}, [n = next](std::exception_ptr e) mutable {
|
}).except([n = next](std::exception_ptr e) mutable {
|
||||||
n.reject(e);
|
n.reject(e);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -225,10 +225,10 @@ namespace promise_hpp
|
|||||||
auto then_all(ResolveF&& on_resolve) {
|
auto then_all(ResolveF&& on_resolve) {
|
||||||
return then([
|
return then([
|
||||||
f = std::forward<ResolveF>(on_resolve)
|
f = std::forward<ResolveF>(on_resolve)
|
||||||
](const T& v) mutable {
|
](auto&& v) mutable {
|
||||||
auto r = invoke_hpp::invoke(
|
auto r = invoke_hpp::invoke(
|
||||||
std::forward<decltype(f)>(f),
|
std::forward<decltype(f)>(f),
|
||||||
v);
|
std::forward<decltype(v)>(v));
|
||||||
return make_all_promise(std::move(r));
|
return make_all_promise(std::move(r));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -237,10 +237,10 @@ namespace promise_hpp
|
|||||||
auto then_any(ResolveF&& on_resolve) {
|
auto then_any(ResolveF&& on_resolve) {
|
||||||
return then([
|
return then([
|
||||||
f = std::forward<ResolveF>(on_resolve)
|
f = std::forward<ResolveF>(on_resolve)
|
||||||
](const T& v) mutable {
|
](auto&& v) mutable {
|
||||||
auto r = invoke_hpp::invoke(
|
auto r = invoke_hpp::invoke(
|
||||||
std::forward<decltype(f)>(f),
|
std::forward<decltype(f)>(f),
|
||||||
v);
|
std::forward<decltype(v)>(v));
|
||||||
return make_any_promise(std::move(r));
|
return make_any_promise(std::move(r));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -274,14 +274,13 @@ namespace promise_hpp
|
|||||||
template < typename RejectF >
|
template < typename RejectF >
|
||||||
promise<T> except(RejectF&& on_reject) {
|
promise<T> except(RejectF&& on_reject) {
|
||||||
return then(
|
return then(
|
||||||
[](const T& value) { return value; },
|
[](auto&& v) { return std::forward<decltype(v)>(v); },
|
||||||
std::forward<RejectF>(on_reject));
|
std::forward<RejectF>(on_reject));
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename U >
|
template < typename U >
|
||||||
bool resolve(U&& value) {
|
bool resolve(U&& value) {
|
||||||
return state_->resolve(
|
return state_->resolve(std::forward<U>(value));
|
||||||
std::forward<U>(value));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool reject(std::exception_ptr e) noexcept {
|
bool reject(std::exception_ptr e) noexcept {
|
||||||
@@ -298,6 +297,14 @@ namespace promise_hpp
|
|||||||
return state_->get();
|
return state_->get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const T& get_or_default(const T& def) const noexcept {
|
||||||
|
try {
|
||||||
|
return get();
|
||||||
|
} catch (...) {
|
||||||
|
return def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void wait() const noexcept {
|
void wait() const noexcept {
|
||||||
state_->wait();
|
state_->wait();
|
||||||
}
|
}
|
||||||
@@ -391,10 +398,10 @@ namespace promise_hpp
|
|||||||
|
|
||||||
template < typename U, typename ResolveF, typename RejectF >
|
template < typename U, typename ResolveF, typename RejectF >
|
||||||
std::enable_if_t<std::is_void<U>::value, void>
|
std::enable_if_t<std::is_void<U>::value, void>
|
||||||
attach(promise<U>& next, ResolveF&& resolve, RejectF&& reject) {
|
attach(promise<U>& next, ResolveF&& on_resolve, RejectF&& on_reject) {
|
||||||
auto reject_h = [
|
auto reject_h = [
|
||||||
n = next,
|
n = next,
|
||||||
f = std::forward<RejectF>(reject)
|
f = std::forward<RejectF>(on_reject)
|
||||||
](std::exception_ptr e) mutable {
|
](std::exception_ptr e) mutable {
|
||||||
try {
|
try {
|
||||||
invoke_hpp::invoke(
|
invoke_hpp::invoke(
|
||||||
@@ -408,18 +415,15 @@ namespace promise_hpp
|
|||||||
|
|
||||||
auto resolve_h = [
|
auto resolve_h = [
|
||||||
n = next,
|
n = next,
|
||||||
f = std::forward<ResolveF>(resolve),
|
f = std::forward<ResolveF>(on_resolve)
|
||||||
j = reject_h
|
](auto&& v) mutable {
|
||||||
](const T& v) mutable {
|
|
||||||
try {
|
try {
|
||||||
invoke_hpp::invoke(
|
invoke_hpp::invoke(
|
||||||
std::forward<decltype(f)>(f),
|
std::forward<decltype(f)>(f),
|
||||||
v);
|
std::forward<decltype(v)>(v));
|
||||||
n.resolve();
|
n.resolve();
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
invoke_hpp::invoke(
|
n.reject(std::current_exception());
|
||||||
std::move(j),
|
|
||||||
std::current_exception());
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -429,10 +433,10 @@ namespace promise_hpp
|
|||||||
|
|
||||||
template < typename U, typename ResolveF, typename RejectF >
|
template < typename U, typename ResolveF, typename RejectF >
|
||||||
std::enable_if_t<!std::is_void<U>::value, void>
|
std::enable_if_t<!std::is_void<U>::value, void>
|
||||||
attach(promise<U>& next, ResolveF&& resolve, RejectF&& reject) {
|
attach(promise<U>& next, ResolveF&& on_resolve, RejectF&& on_reject) {
|
||||||
auto reject_h = [
|
auto reject_h = [
|
||||||
n = next,
|
n = next,
|
||||||
f = std::forward<RejectF>(reject)
|
f = std::forward<RejectF>(on_reject)
|
||||||
](std::exception_ptr e) mutable {
|
](std::exception_ptr e) mutable {
|
||||||
try {
|
try {
|
||||||
invoke_hpp::invoke(
|
invoke_hpp::invoke(
|
||||||
@@ -446,18 +450,15 @@ namespace promise_hpp
|
|||||||
|
|
||||||
auto resolve_h = [
|
auto resolve_h = [
|
||||||
n = next,
|
n = next,
|
||||||
f = std::forward<ResolveF>(resolve),
|
f = std::forward<ResolveF>(on_resolve)
|
||||||
j = reject_h
|
](auto&& v) mutable {
|
||||||
](const T& v) mutable {
|
|
||||||
try {
|
try {
|
||||||
auto r = invoke_hpp::invoke(
|
auto r = invoke_hpp::invoke(
|
||||||
std::forward<decltype(f)>(f),
|
std::forward<decltype(f)>(f),
|
||||||
v);
|
std::forward<decltype(v)>(v));
|
||||||
n.resolve(std::move(r));
|
n.resolve(std::move(r));
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
invoke_hpp::invoke(
|
n.reject(std::current_exception());
|
||||||
std::move(j),
|
|
||||||
std::current_exception());
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -576,12 +577,12 @@ namespace promise_hpp
|
|||||||
]() mutable {
|
]() mutable {
|
||||||
auto np = invoke_hpp::invoke(
|
auto np = invoke_hpp::invoke(
|
||||||
std::forward<decltype(f)>(f));
|
std::forward<decltype(f)>(f));
|
||||||
np.then([n]() mutable {
|
std::move(np).then([n]() mutable {
|
||||||
n.resolve();
|
n.resolve();
|
||||||
}, [n](std::exception_ptr e) mutable {
|
}).except([n](std::exception_ptr e) mutable {
|
||||||
n.reject(e);
|
n.reject(e);
|
||||||
});
|
});
|
||||||
}, [n = next](std::exception_ptr e) mutable {
|
}).except([n = next](std::exception_ptr e) mutable {
|
||||||
n.reject(e);
|
n.reject(e);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -602,12 +603,12 @@ namespace promise_hpp
|
|||||||
]() mutable {
|
]() mutable {
|
||||||
auto np = invoke_hpp::invoke(
|
auto np = invoke_hpp::invoke(
|
||||||
std::forward<decltype(f)>(f));
|
std::forward<decltype(f)>(f));
|
||||||
np.then([n](const typename ResolveFR::value_type& nv) mutable {
|
std::move(np).then([n](auto&& nv) mutable {
|
||||||
n.resolve(nv);
|
n.resolve(std::forward<decltype(nv)>(nv));
|
||||||
}, [n](std::exception_ptr e) mutable {
|
}).except([n](std::exception_ptr e) mutable {
|
||||||
n.reject(e);
|
n.reject(e);
|
||||||
});
|
});
|
||||||
}, [n = next](std::exception_ptr e) mutable {
|
}).except([n = next](std::exception_ptr e) mutable {
|
||||||
n.reject(e);
|
n.reject(e);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -687,6 +688,14 @@ namespace promise_hpp
|
|||||||
state_->get();
|
state_->get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void get_or_default() const noexcept {
|
||||||
|
try {
|
||||||
|
return get();
|
||||||
|
} catch (...) {
|
||||||
|
// nothing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void wait() const noexcept {
|
void wait() const noexcept {
|
||||||
state_->wait();
|
state_->wait();
|
||||||
}
|
}
|
||||||
@@ -777,10 +786,10 @@ namespace promise_hpp
|
|||||||
|
|
||||||
template < typename U, typename ResolveF, typename RejectF >
|
template < typename U, typename ResolveF, typename RejectF >
|
||||||
std::enable_if_t<std::is_void<U>::value, void>
|
std::enable_if_t<std::is_void<U>::value, void>
|
||||||
attach(promise<U>& next, ResolveF&& resolve, RejectF&& reject) {
|
attach(promise<U>& next, ResolveF&& on_resolve, RejectF&& on_reject) {
|
||||||
auto reject_h = [
|
auto reject_h = [
|
||||||
n = next,
|
n = next,
|
||||||
f = std::forward<RejectF>(reject)
|
f = std::forward<RejectF>(on_reject)
|
||||||
](std::exception_ptr e) mutable {
|
](std::exception_ptr e) mutable {
|
||||||
try {
|
try {
|
||||||
invoke_hpp::invoke(
|
invoke_hpp::invoke(
|
||||||
@@ -794,17 +803,14 @@ namespace promise_hpp
|
|||||||
|
|
||||||
auto resolve_h = [
|
auto resolve_h = [
|
||||||
n = next,
|
n = next,
|
||||||
f = std::forward<ResolveF>(resolve),
|
f = std::forward<ResolveF>(on_resolve)
|
||||||
j = reject_h
|
|
||||||
]() mutable {
|
]() mutable {
|
||||||
try {
|
try {
|
||||||
invoke_hpp::invoke(
|
invoke_hpp::invoke(
|
||||||
std::forward<decltype(f)>(f));
|
std::forward<decltype(f)>(f));
|
||||||
n.resolve();
|
n.resolve();
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
invoke_hpp::invoke(
|
n.reject(std::current_exception());
|
||||||
std::move(j),
|
|
||||||
std::current_exception());
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -814,10 +820,10 @@ namespace promise_hpp
|
|||||||
|
|
||||||
template < typename U, typename ResolveF, typename RejectF >
|
template < typename U, typename ResolveF, typename RejectF >
|
||||||
std::enable_if_t<!std::is_void<U>::value, void>
|
std::enable_if_t<!std::is_void<U>::value, void>
|
||||||
attach(promise<U>& next, ResolveF&& resolve, RejectF&& reject) {
|
attach(promise<U>& next, ResolveF&& on_resolve, RejectF&& on_reject) {
|
||||||
auto reject_h = [
|
auto reject_h = [
|
||||||
n = next,
|
n = next,
|
||||||
f = std::forward<RejectF>(reject)
|
f = std::forward<RejectF>(on_reject)
|
||||||
](std::exception_ptr e) mutable {
|
](std::exception_ptr e) mutable {
|
||||||
try {
|
try {
|
||||||
invoke_hpp::invoke(
|
invoke_hpp::invoke(
|
||||||
@@ -831,17 +837,14 @@ namespace promise_hpp
|
|||||||
|
|
||||||
auto resolve_h = [
|
auto resolve_h = [
|
||||||
n = next,
|
n = next,
|
||||||
f = std::forward<ResolveF>(resolve),
|
f = std::forward<ResolveF>(on_resolve)
|
||||||
j = reject_h
|
|
||||||
]() mutable {
|
]() mutable {
|
||||||
try {
|
try {
|
||||||
auto r = invoke_hpp::invoke(
|
auto r = invoke_hpp::invoke(
|
||||||
std::forward<decltype(f)>(f));
|
std::forward<decltype(f)>(f));
|
||||||
n.resolve(std::move(r));
|
n.resolve(std::move(r));
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
invoke_hpp::invoke(
|
n.reject(std::current_exception());
|
||||||
std::move(j),
|
|
||||||
std::current_exception());
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1020,11 +1023,11 @@ namespace promise_hpp
|
|||||||
context,
|
context,
|
||||||
resolver,
|
resolver,
|
||||||
result_index
|
result_index
|
||||||
](const child_promise_value_t& v) mutable {
|
](auto&& v) mutable {
|
||||||
if ( context->apply_result(result_index, v) ) {
|
if ( context->apply_result(result_index, std::forward<decltype(v)>(v)) ) {
|
||||||
resolver(std::move(context->results));
|
resolver(std::move(context->results));
|
||||||
}
|
}
|
||||||
}, rejector);
|
}).except(rejector);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -1051,7 +1054,7 @@ namespace promise_hpp
|
|||||||
|
|
||||||
return make_promise<child_promise_value_t>([begin, end](auto&& resolver, auto&& rejector){
|
return make_promise<child_promise_value_t>([begin, end](auto&& resolver, auto&& rejector){
|
||||||
for ( auto iter = begin; iter != end; ++iter ) {
|
for ( auto iter = begin; iter != end; ++iter ) {
|
||||||
(*iter).then(resolver, rejector);
|
(*iter).then(resolver).except(rejector);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,12 @@ namespace e2d
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class vfs_load_async_exception final : public exception {
|
||||||
|
const char* what() const noexcept final {
|
||||||
|
return "vfs load async exception";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class vfs final : public module<vfs> {
|
class vfs final : public module<vfs> {
|
||||||
public:
|
public:
|
||||||
vfs();
|
vfs();
|
||||||
@@ -27,8 +33,7 @@ namespace e2d
|
|||||||
virtual ~file_source() noexcept = default;
|
virtual ~file_source() noexcept = default;
|
||||||
virtual bool valid() const noexcept = 0;
|
virtual bool valid() const noexcept = 0;
|
||||||
virtual bool exists(str_view path) const = 0;
|
virtual bool exists(str_view path) const = 0;
|
||||||
virtual input_stream_uptr open(str_view path) const = 0;
|
virtual input_stream_uptr read(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 output_stream_uptr write(str_view path, bool append) const = 0;
|
||||||
virtual bool trace(str_view path, filesystem::trace_func func) const = 0;
|
virtual bool trace(str_view path, filesystem::trace_func func) const = 0;
|
||||||
};
|
};
|
||||||
@@ -43,10 +48,15 @@ namespace e2d
|
|||||||
bool unregister_scheme_alias(str_view scheme);
|
bool unregister_scheme_alias(str_view scheme);
|
||||||
|
|
||||||
bool exists(const url& url) const;
|
bool exists(const url& url) const;
|
||||||
input_stream_uptr open(const url& url) const;
|
|
||||||
std::pair<buffer,bool> load(const url& url) const;
|
input_stream_uptr read(const url& url) const;
|
||||||
output_stream_uptr write(const url& url, bool append) const;
|
output_stream_uptr write(const url& url, bool append) const;
|
||||||
stdex::promise<std::pair<buffer,bool>> load_async(const url& url) const;
|
|
||||||
|
bool load(const url& url, buffer& dst) const;
|
||||||
|
stdex::promise<buffer> load_async(const url& url) const;
|
||||||
|
|
||||||
|
bool load_as_string(const url& url, str& dst) const;
|
||||||
|
stdex::promise<str> load_as_string_async(const url& url) const;
|
||||||
|
|
||||||
template < typename Iter >
|
template < typename Iter >
|
||||||
bool extract(const url& url, Iter result_iter) const;
|
bool extract(const url& url, Iter result_iter) const;
|
||||||
@@ -64,8 +74,7 @@ namespace e2d
|
|||||||
~archive_file_source() noexcept final;
|
~archive_file_source() noexcept final;
|
||||||
bool valid() const noexcept final;
|
bool valid() const noexcept final;
|
||||||
bool exists(str_view path) const final;
|
bool exists(str_view path) const final;
|
||||||
input_stream_uptr open(str_view path) const final;
|
input_stream_uptr read(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;
|
output_stream_uptr write(str_view path, bool append) const final;
|
||||||
bool trace(str_view path, filesystem::trace_func func) const final;
|
bool trace(str_view path, filesystem::trace_func func) const final;
|
||||||
private:
|
private:
|
||||||
@@ -79,8 +88,7 @@ namespace e2d
|
|||||||
~filesystem_file_source() noexcept final;
|
~filesystem_file_source() noexcept final;
|
||||||
bool valid() const noexcept final;
|
bool valid() const noexcept final;
|
||||||
bool exists(str_view path) const final;
|
bool exists(str_view path) const final;
|
||||||
input_stream_uptr open(str_view path) const final;
|
input_stream_uptr read(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;
|
output_stream_uptr write(str_view path, bool append) const final;
|
||||||
bool trace(str_view path, filesystem::trace_func func) const final;
|
bool trace(str_view path, filesystem::trace_func func) const final;
|
||||||
};
|
};
|
||||||
|
|||||||
Submodule modules/promise.hpp updated: 4fb77fb49d...5871ecea02
@@ -95,7 +95,7 @@ namespace
|
|||||||
bool initialize() final {
|
bool initialize() final {
|
||||||
the<vfs>().register_scheme<archive_file_source>(
|
the<vfs>().register_scheme<archive_file_source>(
|
||||||
"piratepack",
|
"piratepack",
|
||||||
the<vfs>().open(url("resources://bin/kenney_piratepack.zip")));
|
the<vfs>().read(url("resources://bin/kenney_piratepack.zip")));
|
||||||
|
|
||||||
the<vfs>().register_scheme_alias(
|
the<vfs>().register_scheme_alias(
|
||||||
"ships",
|
"ships",
|
||||||
@@ -104,9 +104,9 @@ namespace
|
|||||||
shader_ = the<render>().create_shader(
|
shader_ = the<render>().create_shader(
|
||||||
vs_source_cstr, fs_source_cstr);
|
vs_source_cstr, fs_source_cstr);
|
||||||
texture1_ = the<render>().create_texture(
|
texture1_ = the<render>().create_texture(
|
||||||
the<vfs>().open(url("ships://ship (2).png")));
|
the<vfs>().read(url("ships://ship (2).png")));
|
||||||
texture2_ = the<render>().create_texture(
|
texture2_ = the<render>().create_texture(
|
||||||
the<vfs>().open(url("ships://ship (19).png")));
|
the<vfs>().read(url("ships://ship (19).png")));
|
||||||
|
|
||||||
if ( !shader_ || !texture1_ || !texture2_ ) {
|
if ( !shader_ || !texture1_ || !texture2_ ) {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -155,7 +155,7 @@ namespace
|
|||||||
bool initialize() final {
|
bool initialize() final {
|
||||||
the<vfs>().register_scheme<archive_file_source>(
|
the<vfs>().register_scheme<archive_file_source>(
|
||||||
"piratepack",
|
"piratepack",
|
||||||
the<vfs>().open(url("resources://bin/kenney_piratepack.zip")));
|
the<vfs>().read(url("resources://bin/kenney_piratepack.zip")));
|
||||||
|
|
||||||
the<vfs>().register_scheme_alias(
|
the<vfs>().register_scheme_alias(
|
||||||
"ships",
|
"ships",
|
||||||
@@ -165,7 +165,7 @@ namespace
|
|||||||
vs_source_cstr, fs_source_cstr);
|
vs_source_cstr, fs_source_cstr);
|
||||||
|
|
||||||
texture_ = the<render>().create_texture(
|
texture_ = the<render>().create_texture(
|
||||||
the<vfs>().open(url("ships://ship (3).png")));
|
the<vfs>().read(url("ships://ship (3).png")));
|
||||||
|
|
||||||
if ( !shader_ || !texture_ ) {
|
if ( !shader_ || !texture_ ) {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ namespace
|
|||||||
bool initialize() final {
|
bool initialize() final {
|
||||||
the<vfs>().register_scheme<archive_file_source>(
|
the<vfs>().register_scheme<archive_file_source>(
|
||||||
"piratepack",
|
"piratepack",
|
||||||
the<vfs>().open(url("resources://bin/kenney_piratepack.zip")));
|
the<vfs>().read(url("resources://bin/kenney_piratepack.zip")));
|
||||||
|
|
||||||
the<vfs>().register_scheme_alias(
|
the<vfs>().register_scheme_alias(
|
||||||
"ships",
|
"ships",
|
||||||
@@ -120,7 +120,7 @@ namespace
|
|||||||
vs_source_cstr, fs_source_cstr);
|
vs_source_cstr, fs_source_cstr);
|
||||||
|
|
||||||
texture_ = the<render>().create_texture(
|
texture_ = the<render>().create_texture(
|
||||||
the<vfs>().open(url("ships://ship (3).png")));
|
the<vfs>().read(url("ships://ship (3).png")));
|
||||||
|
|
||||||
if ( !shader_ || !texture_ ) {
|
if ( !shader_ || !texture_ ) {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -98,7 +98,10 @@ namespace e2d
|
|||||||
const auto resolved_url = resolve_url(url);
|
const auto resolved_url = resolve_url(url);
|
||||||
const auto scheme_iter = schemes.find(resolved_url.scheme());
|
const auto scheme_iter = schemes.find(resolved_url.scheme());
|
||||||
return (scheme_iter != schemes.cend() && scheme_iter->second)
|
return (scheme_iter != schemes.cend() && scheme_iter->second)
|
||||||
? stdex::invoke(std::forward<F>(f), scheme_iter->second, resolved_url.path())
|
? stdex::invoke(
|
||||||
|
std::forward<F>(f),
|
||||||
|
scheme_iter->second,
|
||||||
|
resolved_url.path())
|
||||||
: std::forward<R>(fallback_result);
|
: std::forward<R>(fallback_result);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -140,22 +143,14 @@ namespace e2d
|
|||||||
}, false);
|
}, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
input_stream_uptr vfs::open(const url& url) const {
|
input_stream_uptr vfs::read(const url& url) const {
|
||||||
std::lock_guard<std::mutex> guard(state_->mutex);
|
std::lock_guard<std::mutex> guard(state_->mutex);
|
||||||
return state_->with_file_source(url,
|
return state_->with_file_source(url,
|
||||||
[](const file_source_uptr& source, const str& path) {
|
[](const file_source_uptr& source, const str& path) {
|
||||||
return source->open(path);
|
return source->read(path);
|
||||||
}, input_stream_uptr());
|
}, input_stream_uptr());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<buffer,bool> vfs::load(const url& url) const {
|
|
||||||
std::lock_guard<std::mutex> guard(state_->mutex);
|
|
||||||
return state_->with_file_source(url,
|
|
||||||
[](const file_source_uptr& source, const str& path) {
|
|
||||||
return source->load(path);
|
|
||||||
}, std::make_pair(buffer(), false));
|
|
||||||
}
|
|
||||||
|
|
||||||
output_stream_uptr vfs::write(const url& url, bool append) const {
|
output_stream_uptr vfs::write(const url& url, bool append) const {
|
||||||
std::lock_guard<std::mutex> guard(state_->mutex);
|
std::lock_guard<std::mutex> guard(state_->mutex);
|
||||||
return state_->with_file_source(url,
|
return state_->with_file_source(url,
|
||||||
@@ -164,13 +159,40 @@ namespace e2d
|
|||||||
}, output_stream_uptr());
|
}, output_stream_uptr());
|
||||||
}
|
}
|
||||||
|
|
||||||
stdex::promise<std::pair<buffer,bool>> vfs::load_async(const url& url) const {
|
bool vfs::load(const url& url, buffer& dst) const {
|
||||||
return state_->worker.async([](input_stream_uptr stream){
|
return load_async(url)
|
||||||
buffer buf;
|
.then([&dst](auto&& src){
|
||||||
return streams::try_read_tail(buf, stream)
|
dst = std::forward<decltype(src)>(src);
|
||||||
? std::make_pair(std::move(buf), true)
|
return true;
|
||||||
: std::make_pair(buffer(), false);
|
}).get_or_default(false);
|
||||||
}, open(url));
|
}
|
||||||
|
|
||||||
|
stdex::promise<buffer> vfs::load_async(const url& url) const {
|
||||||
|
return state_->worker.async([this](auto&& url_copy){
|
||||||
|
buffer content;
|
||||||
|
if ( !streams::try_read_tail(content, read(url_copy)) ) {
|
||||||
|
throw vfs_load_async_exception();
|
||||||
|
}
|
||||||
|
return content;
|
||||||
|
}, url);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool vfs::load_as_string(const url& url, str& dst) const {
|
||||||
|
return load_as_string_async(url)
|
||||||
|
.then([&dst](auto&& src){
|
||||||
|
dst = std::forward<decltype(src)>(src);
|
||||||
|
return true;
|
||||||
|
}).get_or_default(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
stdex::promise<str> vfs::load_as_string_async(const url& url) const {
|
||||||
|
return state_->worker.async([this](auto&& url_copy){
|
||||||
|
str content;
|
||||||
|
if ( !streams::try_read_tail(content, read(url_copy)) ) {
|
||||||
|
throw vfs_load_async_exception();
|
||||||
|
}
|
||||||
|
return content;
|
||||||
|
}, url);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool vfs::trace(const url& url, filesystem::trace_func func) const {
|
bool vfs::trace(const url& url, filesystem::trace_func func) const {
|
||||||
@@ -250,7 +272,7 @@ namespace e2d
|
|||||||
MZ_ZIP_FLAG_CASE_SENSITIVE);
|
MZ_ZIP_FLAG_CASE_SENSITIVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
input_stream_uptr archive_file_source::open(str_view path) const {
|
input_stream_uptr archive_file_source::read(str_view path) const {
|
||||||
try {
|
try {
|
||||||
struct owned_state_t {
|
struct owned_state_t {
|
||||||
state::archive_ptr archive;
|
state::archive_ptr archive;
|
||||||
@@ -265,19 +287,6 @@ namespace e2d
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<buffer,bool> archive_file_source::load(str_view path) const {
|
|
||||||
std::size_t mem_size = 0;
|
|
||||||
void* mem = mz_zip_reader_extract_file_to_heap(
|
|
||||||
state_->archive.get(),
|
|
||||||
make_utf8(path).c_str(),
|
|
||||||
&mem_size,
|
|
||||||
MZ_ZIP_FLAG_CASE_SENSITIVE);
|
|
||||||
std::unique_ptr<void, decltype(&mz_free)> mem_uptr(mem, mz_free);
|
|
||||||
return mem
|
|
||||||
? std::make_pair(buffer(mem, mem_size), true)
|
|
||||||
: std::make_pair(buffer(), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
output_stream_uptr archive_file_source::write(str_view path, bool append) const {
|
output_stream_uptr archive_file_source::write(str_view path, bool append) const {
|
||||||
E2D_UNUSED(path, append);
|
E2D_UNUSED(path, append);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@@ -338,17 +347,10 @@ namespace e2d
|
|||||||
return filesystem::file_exists(path);
|
return filesystem::file_exists(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
input_stream_uptr filesystem_file_source::open(str_view path) const {
|
input_stream_uptr filesystem_file_source::read(str_view path) const {
|
||||||
return make_read_file(path);
|
return make_read_file(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<buffer,bool> filesystem_file_source::load(str_view path) const {
|
|
||||||
buffer buf;
|
|
||||||
return filesystem::try_read_all(buf, path)
|
|
||||||
? std::make_pair(std::move(buf), true)
|
|
||||||
: std::make_pair(buffer(), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
output_stream_uptr filesystem_file_source::write(str_view path, bool append) const {
|
output_stream_uptr filesystem_file_source::write(str_view path, bool append) const {
|
||||||
if ( !filesystem::create_directory_recursive(path::parent_path(path)) ) {
|
if ( !filesystem::create_directory_recursive(path::parent_path(path)) ) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|||||||
@@ -1390,7 +1390,7 @@ namespace e2d
|
|||||||
|
|
||||||
const auto asset_url = library.root() / address;
|
const auto asset_url = library.root() / address;
|
||||||
input_stream_uptr stream = modules::is_initialized<vfs>()
|
input_stream_uptr stream = modules::is_initialized<vfs>()
|
||||||
? the<vfs>().open(asset_url)
|
? the<vfs>().read(asset_url)
|
||||||
: input_stream_uptr();
|
: input_stream_uptr();
|
||||||
|
|
||||||
if ( !stream ) {
|
if ( !stream ) {
|
||||||
@@ -1462,7 +1462,7 @@ namespace e2d
|
|||||||
|
|
||||||
const auto asset_url = library.root() / address;
|
const auto asset_url = library.root() / address;
|
||||||
input_stream_uptr stream = modules::is_initialized<vfs>()
|
input_stream_uptr stream = modules::is_initialized<vfs>()
|
||||||
? the<vfs>().open(asset_url)
|
? the<vfs>().read(asset_url)
|
||||||
: input_stream_uptr();
|
: input_stream_uptr();
|
||||||
|
|
||||||
if ( !stream ) {
|
if ( !stream ) {
|
||||||
|
|||||||
@@ -25,21 +25,27 @@ TEST_CASE("vfs"){
|
|||||||
}
|
}
|
||||||
{
|
{
|
||||||
buffer b;
|
buffer b;
|
||||||
auto r = v.open({"file", file_path});
|
auto r = v.read({"file", file_path});
|
||||||
REQUIRE(r);
|
REQUIRE(r);
|
||||||
REQUIRE(streams::try_read_tail(b, r));
|
REQUIRE(streams::try_read_tail(b, r));
|
||||||
REQUIRE(b == buffer{"hello", 5});
|
REQUIRE(b == buffer{"hello", 5});
|
||||||
REQUIRE(v.open({"file2", file_path}) == input_stream_uptr());
|
REQUIRE(v.read({"file2", file_path}) == input_stream_uptr());
|
||||||
REQUIRE(v.open({"file", nofile_path}) == input_stream_uptr());
|
REQUIRE(v.read({"file", nofile_path}) == input_stream_uptr());
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
auto r = v.load({"file", file_path});
|
buffer b0;
|
||||||
REQUIRE(r.second);
|
REQUIRE(v.load({"file", file_path}, b0));
|
||||||
REQUIRE(r.first == buffer{"hello", 5});
|
REQUIRE(b0 == buffer{"hello", 5});
|
||||||
|
|
||||||
auto r2 = v.load_async({"file", file_path}).get();
|
auto b1 = v.load_async({"file", file_path}).get();
|
||||||
REQUIRE(r2.second);
|
REQUIRE(b1 == buffer{"hello", 5});
|
||||||
REQUIRE(r2.first == buffer{"hello", 5});
|
|
||||||
|
str b2;
|
||||||
|
REQUIRE(v.load_as_string({"file", file_path}, b2));
|
||||||
|
REQUIRE(b2 == "hello");
|
||||||
|
|
||||||
|
auto b3 = v.load_as_string_async({"file", file_path}).get();
|
||||||
|
REQUIRE(b3 == "hello");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
@@ -58,17 +64,17 @@ TEST_CASE("vfs"){
|
|||||||
|
|
||||||
REQUIRE_FALSE(v.register_scheme<archive_file_source>(
|
REQUIRE_FALSE(v.register_scheme<archive_file_source>(
|
||||||
"archive",
|
"archive",
|
||||||
v.open(url("resources://bin/noresources.zip"))));
|
v.read(url("resources://bin/noresources.zip"))));
|
||||||
|
|
||||||
REQUIRE(v.register_scheme<filesystem_file_source>("file"));
|
REQUIRE(v.register_scheme<filesystem_file_source>("file"));
|
||||||
|
|
||||||
REQUIRE_FALSE(v.register_scheme<archive_file_source>(
|
REQUIRE_FALSE(v.register_scheme<archive_file_source>(
|
||||||
"archive",
|
"archive",
|
||||||
v.open(url("resources://bin/noresources.zip"))));
|
v.read(url("resources://bin/noresources.zip"))));
|
||||||
|
|
||||||
REQUIRE(v.register_scheme<archive_file_source>(
|
REQUIRE(v.register_scheme<archive_file_source>(
|
||||||
"archive",
|
"archive",
|
||||||
v.open(url("resources://bin/resources.zip"))));
|
v.read(url("resources://bin/resources.zip"))));
|
||||||
|
|
||||||
REQUIRE(v.exists({"archive", "test.txt"}));
|
REQUIRE(v.exists({"archive", "test.txt"}));
|
||||||
REQUIRE_FALSE(v.exists({"archive", "TEst.txt"}));
|
REQUIRE_FALSE(v.exists({"archive", "TEst.txt"}));
|
||||||
@@ -122,50 +128,70 @@ TEST_CASE("vfs"){
|
|||||||
REQUIRE_FALSE(v.extract(url("archive://test.txt"), std::back_inserter(result)));
|
REQUIRE_FALSE(v.extract(url("archive://test.txt"), std::back_inserter(result)));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
auto f = v.open(url("archive://test.txt"));
|
auto f = v.read(url("archive://test.txt"));
|
||||||
REQUIRE(f);
|
REQUIRE(f);
|
||||||
buffer b;
|
buffer b;
|
||||||
REQUIRE(streams::try_read_tail(b, f));
|
REQUIRE(streams::try_read_tail(b, f));
|
||||||
REQUIRE(b == buffer("hello", 5));
|
REQUIRE(b == buffer("hello", 5));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
auto r = v.load(url("archive://test.txt"));
|
buffer b0;
|
||||||
REQUIRE(r.second);
|
REQUIRE(v.load(url("archive://test.txt"), b0));
|
||||||
REQUIRE(r.first == buffer("hello", 5));
|
REQUIRE(b0 == buffer("hello", 5));
|
||||||
|
|
||||||
auto r2 = v.load_async(url("archive://test.txt")).get();
|
auto b1 = v.load_async(url("archive://test.txt")).get();
|
||||||
REQUIRE(r2.second);
|
REQUIRE(b1 == buffer("hello", 5));
|
||||||
REQUIRE(r2.first == buffer("hello", 5));
|
|
||||||
|
str b2;
|
||||||
|
REQUIRE(v.load_as_string(url("archive://test.txt"), b2));
|
||||||
|
REQUIRE(b2 == "hello");
|
||||||
|
|
||||||
|
auto b3 = v.load_as_string_async(url("archive://test.txt")).get();
|
||||||
|
REQUIRE(b3 == "hello");
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
auto f = v.open(url("archive://folder/file.txt"));
|
auto f = v.read(url("archive://folder/file.txt"));
|
||||||
REQUIRE(f);
|
REQUIRE(f);
|
||||||
buffer b;
|
buffer b;
|
||||||
REQUIRE(streams::try_read_tail(b, f));
|
REQUIRE(streams::try_read_tail(b, f));
|
||||||
REQUIRE(b == buffer("world", 5));
|
REQUIRE(b == buffer("world", 5));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
auto r = v.load(url("archive://folder/file.txt"));
|
buffer b0;
|
||||||
REQUIRE(r.second);
|
REQUIRE(v.load(url("archive://folder/file.txt"), b0));
|
||||||
REQUIRE(r.first == buffer("world", 5));
|
REQUIRE(b0 == buffer("world", 5));
|
||||||
|
|
||||||
auto r2 = v.load_async(url("archive://folder/file.txt")).get();
|
auto b1 = v.load_async(url("archive://folder/file.txt")).get();
|
||||||
REQUIRE(r2.second);
|
REQUIRE(b1 == buffer("world", 5));
|
||||||
REQUIRE(r2.first == buffer("world", 5));
|
|
||||||
|
str b2;
|
||||||
|
REQUIRE(v.load_as_string(url("archive://folder/file.txt"), b2));
|
||||||
|
REQUIRE(b2 == "world");
|
||||||
|
|
||||||
|
auto b3 = v.load_as_string_async(url("archive://folder/file.txt")).get();
|
||||||
|
REQUIRE(b3 == "world");
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
REQUIRE(v.open(url("archive://TEst.txt")) == input_stream_uptr());
|
REQUIRE(v.read(url("archive://TEst.txt")) == input_stream_uptr());
|
||||||
|
|
||||||
auto r = v.load(url("archive://TEst.txt"));
|
buffer b0;
|
||||||
REQUIRE_FALSE(r.second);
|
REQUIRE_FALSE(v.load(url("archive://TEst.txt"), b0));
|
||||||
REQUIRE(r.first.empty());
|
REQUIRE(b0.empty());
|
||||||
|
|
||||||
auto r2 = v.load_async(url("archive://TEst.txt")).get();
|
REQUIRE_THROWS_AS(
|
||||||
REQUIRE_FALSE(r2.second);
|
v.load_async(url("archive://TEst.txt")).get(),
|
||||||
REQUIRE(r2.first.empty());
|
vfs_load_async_exception);
|
||||||
|
|
||||||
|
str b2;
|
||||||
|
REQUIRE_FALSE(v.load_as_string(url("archive://TEst.txt"), b2));
|
||||||
|
REQUIRE(b2.empty());
|
||||||
|
|
||||||
|
REQUIRE_THROWS_AS(
|
||||||
|
v.load_as_string_async(url("archive://TEst.txt")).get(),
|
||||||
|
vfs_load_async_exception);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
auto f = v.open(url("archive://test.txt"));
|
auto f = v.read(url("archive://test.txt"));
|
||||||
REQUIRE(f);
|
REQUIRE(f);
|
||||||
REQUIRE(v.unregister_scheme("archive"));
|
REQUIRE(v.unregister_scheme("archive"));
|
||||||
buffer b;
|
buffer b;
|
||||||
|
|||||||
Reference in New Issue
Block a user