Compare commits

..

No commits in common. "c45a270a0b01d9887992e31c644a641f96eba1a8" and "cba6e26995ae1b4660e3a4ec6c2ccd9df426e080" have entirely different histories.

4 changed files with 78 additions and 64 deletions

View File

@ -13,6 +13,8 @@ import oar;
export namespace app { export namespace app {
struct directory : public coral::fs { struct directory : public coral::fs {
using coral::fs::access_result;
struct rules { struct rules {
bool can_read; bool can_read;
@ -21,22 +23,24 @@ export namespace app {
directory() : path_buffer{0} {} directory() : path_buffer{0} {}
void read_file(coral::path const & file_path, access_result read_file(coral::path const & file_path,
coral::callable<void(coral::readable const &)> const & then) { coral::callable<void(coral::readable const &)> const & then) {
if (this->prefix_length == 0) return; if (this->prefix_length == 0) return access_result::not_found;
if (!this->access_rules.can_read) return; if (!this->access_rules.can_read) return access_result::access_denied;
::SDL_RWops * rw_ops{this->open_rw(file_path, {.can_read = true})}; ::SDL_RWops * rw_ops = this->open_rw(file_path, {.can_read = true});
if (rw_ops == nullptr) return; if (rw_ops == nullptr) return access_result::not_found;
then([rw_ops](coral::slice<uint8_t> const & buffer) -> size_t { then([rw_ops](coral::slice<uint8_t> const & buffer) -> size_t {
return ::SDL_RWread(rw_ops, buffer.pointer, sizeof(uint8_t), buffer.length); return ::SDL_RWread(rw_ops, buffer.pointer, sizeof(uint8_t), buffer.length);
}); });
::SDL_RWclose(rw_ops); ::SDL_RWclose(rw_ops);
return access_result::ok;
} }
void target(coral::slice<char const> const & directory_path, rules const & access_rules) { void target(coral::slice<char const> const & directory_path, rules const & access_rules) {
@ -53,22 +57,24 @@ export namespace app {
} }
} }
void write_file(coral::path const & file_path, access_result write_file(coral::path const & file_path,
coral::callable<void(coral::writable const &)> const & then) { coral::callable<void(coral::writable const &)> const & then) {
if (this->prefix_length == 0) return; if (this->prefix_length == 0) return access_result::not_found;
if (!this->access_rules.can_write) return; if (!this->access_rules.can_write) return access_result::access_denied;
::SDL_RWops * rw_ops{this->open_rw(file_path, {.can_write = true})}; ::SDL_RWops * rw_ops = this->open_rw(file_path, {.can_write = true});
if (rw_ops == nullptr) return; if (rw_ops == nullptr) return access_result::not_found;
then([rw_ops](coral::slice<uint8_t const> const & buffer) -> size_t { then([rw_ops](coral::slice<uint8_t const> const & buffer) -> size_t {
return ::SDL_RWwrite(rw_ops, buffer.pointer, sizeof(uint8_t), buffer.length); return ::SDL_RWwrite(rw_ops, buffer.pointer, sizeof(uint8_t), buffer.length);
}); });
::SDL_RWclose(rw_ops); ::SDL_RWclose(rw_ops);
return access_result::ok;
} }
private: private:
@ -81,14 +87,14 @@ export namespace app {
coral::u8 path_buffer[path_max]; coral::u8 path_buffer[path_max];
::SDL_RWops * open_rw(coral::path const & file_path, rules const & file_rules) { ::SDL_RWops * open_rw(coral::path const & file_path, rules const & file_rules) {
coral::u8 * const path_begin{this->path_buffer + this->prefix_length}; coral::u8 * const path_begin = this->path_buffer + this->prefix_length;
coral::slice const path_remaining = coral::slice const path_remaining =
{path_begin, path_begin + (path_max - this->prefix_length) - 1}; {path_begin, path_begin + (path_max - this->prefix_length) - 1};
if (path_remaining.length < file_path.byte_size()) return nullptr; if (path_remaining.length < file_path.byte_size()) return nullptr;
coral::copy(path_remaining, file_path.as_slice().as_bytes()); coral::copy(path_remaining, coral::slice{file_path.begin(), file_path.end()}.as_bytes());
return ::SDL_RWFromFile(reinterpret_cast<char const *>(this->path_buffer), "r"); return ::SDL_RWFromFile(reinterpret_cast<char const *>(this->path_buffer), "r");
} }
@ -105,12 +111,12 @@ export namespace app {
constexpr directory::rules read_only_rules = {.can_read = true}; constexpr directory::rules read_only_rules = {.can_read = true};
{ {
char * const path{::SDL_GetBasePath()}; char * const path = ::SDL_GetBasePath();
if (path == nullptr) { if (path == nullptr) {
this->cwd_directory.target("./", read_only_rules); this->cwd_directory.target("./", read_only_rules);
} else { } else {
coral::usize path_length{0}; coral::usize path_length = 0;
while (path[path_length] != 0) path_length += 1; while (path[path_length] != 0) path_length += 1;
@ -125,10 +131,10 @@ export namespace app {
} }
{ {
char * const path{::SDL_GetPrefPath("ona", title.begin())}; char * const path = ::SDL_GetPrefPath("ona", title.begin());
if (path != nullptr) { if (path != nullptr) {
coral::usize path_length{0}; coral::usize path_length = 0;
while (path[path_length] != 0) path_length += 1; while (path[path_length] != 0) path_length += 1;
@ -160,8 +166,8 @@ export namespace app {
} }
void log(app::log_level level, coral::slice<char const> const & message) { void log(app::log_level level, coral::slice<char const> const & message) {
coral::i32 const length{static_cast<coral::i32>( coral::i32 const length = static_cast<coral::i32>(
coral::min(message.length, static_cast<size_t>(coral::i32_max)))}; coral::min(message.length, static_cast<size_t>(coral::i32_max)));
::SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, ::SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION,
SDL_LOG_PRIORITY_INFO, "%.*s", length, message.pointer); SDL_LOG_PRIORITY_INFO, "%.*s", length, message.pointer);
@ -209,12 +215,6 @@ export namespace app {
this->retitle(title); this->retitle(title);
} }
void present() {
if (this->sdl_renderer != nullptr) {
::SDL_RenderPresent(this->sdl_renderer);
}
}
void render(canvas & source_canvas) { void render(canvas & source_canvas) {
if (this->sdl_renderer != nullptr) { if (this->sdl_renderer != nullptr) {
SDL_SetRenderDrawColor(this->sdl_renderer, source_canvas.background_color.to_r8(), SDL_SetRenderDrawColor(this->sdl_renderer, source_canvas.background_color.to_r8(),
@ -257,6 +257,12 @@ export namespace app {
return show_result::ok; return show_result::ok;
} }
void present() {
if (this->sdl_renderer != nullptr) {
::SDL_RenderPresent(this->sdl_renderer);
}
}
private: private:
coral::path title; coral::path title;

View File

@ -29,13 +29,6 @@ export namespace coral {
this->buffer[max] = max - text_size; this->buffer[max] = max - text_size;
} }
/**
* Returns a weak reference to the [path] as a [slice].
*/
constexpr slice<char const> as_slice() const {
return {this->buffer, this->byte_size()};
}
/** /**
* Returns the base pointer of the path name. * Returns the base pointer of the path name.
* *
@ -57,7 +50,8 @@ export namespace coral {
* they are identical. * they are identical.
*/ */
constexpr size compare(path const & that) const { constexpr size compare(path const & that) const {
return coral::compare(this->as_slice().as_bytes(), that.as_slice().as_bytes()); return coral::compare(slice{this->begin(), this->end()}.as_bytes(),
slice{that.begin(), that.end()}.as_bytes());
} }
/** /**
@ -72,7 +66,8 @@ export namespace coral {
* otherwise `false`. * otherwise `false`.
*/ */
constexpr bool equals(path const & that) const { constexpr bool equals(path const & that) const {
return coral::equals(this->as_slice().as_bytes(), that.as_slice().as_bytes()); return coral::equals(slice{this->begin(), this->end()}.as_bytes(),
slice{that.begin(), that.end()}.as_bytes());
} }
/** /**
@ -81,7 +76,7 @@ export namespace coral {
* *Note:* the returned hash code is not guaranteed to be unique. * *Note:* the returned hash code is not guaranteed to be unique.
*/ */
constexpr u64 hash() const { constexpr u64 hash() const {
return coral::hash(this->as_slice().as_bytes()); return coral::hash(slice{this->begin(), this->end()}.as_bytes());
} }
/** /**
@ -110,22 +105,43 @@ export namespace coral {
* Platform-generalized file system interface. * Platform-generalized file system interface.
*/ */
struct fs { struct fs {
/**
* The result from a file access operation.
*
* [file_result::ok] indicates a successful file access operation.
*
* [file_result::not_found] signals that the file was not found.
*
* [file_result::access_denied] warns that the file was found but cannot be opened through
* the file system interface. The most common scenario for this error is a lack of required
* file permissions.
*/
enum class [[nodiscard]] access_result {
ok,
not_found,
access_denied,
};
/** /**
* Attempts to read the file in the file system located at `file_path` relative, calling * Attempts to read the file in the file system located at `file_path` relative, calling
* `then` if it was successfully opened for reading. * `then` if it was successfully opened for reading.
* *
* The returned [access_result] indicates whether the operation was successful or not.
*
* Once `then` returns, access to the file is closed automatically. * Once `then` returns, access to the file is closed automatically.
*/ */
virtual void read_file(path const & file_path, virtual access_result read_file(path const & file_path,
callable<void(readable const &)> const & then) = 0; callable<void(readable const &)> const & then) = 0;
/** /**
* Attempts to write the file in the file system located at `file_path` relative, calling * Attempts to write the file in the file system located at `file_path` relative, calling
* `then` if it was successfully opened for writing. * `then` if it was successfully opened for writing.
* *
* The returned [access_result] indicates whether the operation was successful or not.
*
* Once `then` returns, access to the file is closed automatically. * Once `then` returns, access to the file is closed automatically.
*/ */
virtual void write_file(path const & file_path, virtual access_result write_file(path const & file_path,
callable<void(writable const &)> const & then) = 0; callable<void(writable const &)> const & then) = 0;
}; };
} }

View File

@ -21,16 +21,22 @@ export namespace oar {
}; };
struct archive : public coral::fs { struct archive : public coral::fs {
using coral::fs::access_result;
archive() { archive() {
} }
void read_file(coral::path const & file_path, access_result read_file(coral::path const & file_path,
coral::callable<void(coral::readable const &)> const & then) override { coral::callable<void(coral::readable const &)> const & then) override {
return access_result::access_denied;
} }
void write_file(coral::path const & file_path, virtual access_result write_file(coral::path const & file_path,
coral::callable<void(coral::writable const &)> const & then) override { coral::callable<void(coral::writable const &)> const & then) override {
return access_result::access_denied;
} }
}; };
} }

View File

@ -15,20 +15,22 @@ extern "C" int main(int argc, char const * const * argv) {
constexpr coral::path config_path{"config.kym"}; constexpr coral::path config_path{"config.kym"};
bool is_config_loaded{false}; bool is_config_loaded{false};
system.res_fs().read_file(config_path, [&](coral::readable const & file) { if ((system.res_fs().read_file(config_path, [&](coral::readable const & file) {
coral::allocator * const allocator{&system.thread_safe_allocator()}; kym::vm vm{&system.thread_safe_allocator(),
[&system](coral::slice<char const> const & error_message) {
system.log(app::log_level::error, error_message);
}};
kym::vm vm{allocator, [&system](coral::slice<char const> const & error_message) { if (!vm.init({
system.log(app::log_level::error, error_message); .datastack_size = 64,
}}; .callstack_size = 64,
})) {
if (!vm.init({.datastack_size = 64, .callstack_size = 64})) {
system.log(app::log_level::error, "failed to allocate memory for config vm"); system.log(app::log_level::error, "failed to allocate memory for config vm");
return; return;
} }
coral::stack<coral::u8> script_source{allocator}; coral::stack<coral::u8> script_source{&system.thread_safe_allocator()};
coral::u8 stream_buffer[1024]{0}; coral::u8 stream_buffer[1024]{0};
if (!coral::stream(coral::sequence_writer{&script_source}, file, stream_buffer).is_ok()) if (!coral::stream(coral::sequence_writer{&script_source}, file, stream_buffer).is_ok())
@ -52,7 +54,7 @@ extern "C" int main(int argc, char const * const * argv) {
vm.with_object(config.get_field("title"), [&](kym::bound_object & title) { vm.with_object(config.get_field("title"), [&](kym::bound_object & title) {
coral::stack<coral::u8, 128> title_buffer{&system.thread_safe_allocator()}; coral::stack<coral::u8, 128> title_buffer{&system.thread_safe_allocator()};
if (!title.stringify(coral::sequence_writer{&title_buffer}).is_ok()) { if (!title.stringify(coral::sequence_writer(&title_buffer)).is_ok()) {
system.log(app::log_level::error, system.log(app::log_level::error,
"failed to decode `title` property of config"); "failed to decode `title` property of config");
@ -63,23 +65,7 @@ extern "C" int main(int argc, char const * const * argv) {
}); });
}); });
}); });
}); }) != coral::fs::access_result::ok) || (!is_config_loaded)) return coral::u8_max;
if (!is_config_loaded) {
coral::stack<coral::u8> error_message{&system.thread_safe_allocator()};
{
coral::sequence_writer error_writer{&error_message};
if (!error_writer(coral::slice{"failed to load "}.as_bytes()).is_ok())
return coral::u8_max;
if (!error_writer(config_path.as_slice().as_bytes()).is_ok())
return coral::u8_max;
}
return coral::u8_max;
}
// app::canvas canvas_2d(); // app::canvas canvas_2d();