From 656549f039b4f9945b3b07d4b4e50d9e666165b6 Mon Sep 17 00:00:00 2001 From: maelstrom Date: Tue, 2 Jun 2026 11:27:44 +0200 Subject: [PATCH] feat: directory-based resource resolver --- engine/include/fishbone/client.h | 20 +++++++++--- engine/include/fishbone/logger.h | 23 ++++++++++++++ engine/include/fishbone/resource.h | 32 +++++++++++++++++-- engine/src/client.cc | 2 ++ engine/src/engine.cc | 6 ++++ engine/src/logger.cc | 28 +++++++++++++++++ engine/src/resource/resource.cc | 35 +++++++++++++++++++++ engine/src/resource/unix.cc | 46 ++++++++++++++++++++++++++++ engine/tests/CMakeLists.txt | 4 ++- engine/tests/src/resource.cc | 34 ++++++++++++++++++++ engine/tests/src/thread.cc | 3 +- engine/tests/testresources/lorem.txt | 1 + 12 files changed, 223 insertions(+), 11 deletions(-) create mode 100644 engine/include/fishbone/logger.h create mode 100644 engine/src/engine.cc create mode 100644 engine/src/logger.cc create mode 100644 engine/src/resource/resource.cc create mode 100644 engine/src/resource/unix.cc create mode 100644 engine/tests/src/resource.cc create mode 100644 engine/tests/testresources/lorem.txt diff --git a/engine/include/fishbone/client.h b/engine/include/fishbone/client.h index e29a7cb..befd151 100644 --- a/engine/include/fishbone/client.h +++ b/engine/include/fishbone/client.h @@ -5,25 +5,35 @@ namespace fishbone { class Client; -}; + class ResourceResolver; +}; // namespace fishbone #include #include #include #include +#include namespace fishbone { - class Client { + class BaseEngine : public Logger { + protected: + ResourceResolver* resourceResolver; + + public: + ResourceResolver* getResourceResolver(); + }; + + class Client : public BaseEngine { public: Client(std::unordered_map> param); ~Client(); bool step(); - + fishbone::Window* window; fishbone::SoundDriver* sounddrv; - fishbone::Mixer* mixer; - fishbone::Renderer* renderer; + fishbone::Mixer* mixer; + fishbone::Renderer* renderer; }; }; // namespace fishbone diff --git a/engine/include/fishbone/logger.h b/engine/include/fishbone/logger.h new file mode 100644 index 0000000..571f666 --- /dev/null +++ b/engine/include/fishbone/logger.h @@ -0,0 +1,23 @@ +#ifndef __FISHBONE_LOGGER_H__ +#define __FISHBONE_LOGGER_H__ + +#include + +namespace fishbone { + class Logger { + public: + enum class Cause { + INFO, + DEBUG, + WARNING, + ERROR, + CRITICAL, + }; + + void log(std::string message); + void log(Cause cause, std::string message); + }; + +} // namespace fishbone + +#endif \ No newline at end of file diff --git a/engine/include/fishbone/resource.h b/engine/include/fishbone/resource.h index a995f15..cbe6f4f 100644 --- a/engine/include/fishbone/resource.h +++ b/engine/include/fishbone/resource.h @@ -1,21 +1,47 @@ -#ifndef __FISHBONE_THREAD_H__ -#define __FISHBONE_THREAD_H__ +#ifndef __FISHBONE_RESOURCE_H__ +#define __FISHBONE_RESOURCE_H__ #include namespace fishbone { class Resource; + class BaseEngine; }; // namespace fishbone #include namespace fishbone { + class ResourceResolver { + public: + virtual bool exists(std::string path) = 0; + virtual size_t getSize(std::string path) = 0; + virtual bool copyData(std::string path, char* buffer, size_t maxSize) = 0; + }; + + class DirectoryResourceResolver : public ResourceResolver { + std::vector searchPaths; + + std::string findAbsolutePath(std::string path); + public: + DirectoryResourceResolver(std::vector searchPaths); + + bool exists(std::string path) override; + size_t getSize(std::string path) override; + bool copyData(std::string path, char* buffer, size_t maxSize) override; + }; + class Resource { + char* buffer; + size_t bufferSize; + public: fishbone::File* open(std::string path); - Resource(std::string path); + Resource(BaseEngine* engine, std::string path); ~Resource(); + + char* getBuffer(); + size_t getSize(); }; }; // namespace fishbone diff --git a/engine/src/client.cc b/engine/src/client.cc index bc17717..4537cdb 100644 --- a/engine/src/client.cc +++ b/engine/src/client.cc @@ -1,3 +1,4 @@ +#include #include fishbone::Client::Client(std::unordered_map> param){ @@ -5,6 +6,7 @@ fishbone::Client::Client(std::unordered_mapsounddrv = new fishbone::SoundDriver(); this->mixer = &this->sounddrv->mixer; this->renderer = new fishbone::Renderer(); + this->resourceResolver = new fishbone::DirectoryResourceResolver({"/usr/share/fishbowl/assets"}); } fishbone::Client::~Client(){ diff --git a/engine/src/engine.cc b/engine/src/engine.cc new file mode 100644 index 0000000..af4f6bf --- /dev/null +++ b/engine/src/engine.cc @@ -0,0 +1,6 @@ +#include +#include + +fishbone::ResourceResolver* fishbone::BaseEngine::getResourceResolver() { + return this->resourceResolver; +} \ No newline at end of file diff --git a/engine/src/logger.cc b/engine/src/logger.cc new file mode 100644 index 0000000..f1c45e7 --- /dev/null +++ b/engine/src/logger.cc @@ -0,0 +1,28 @@ +#include +#include + +static const char* CAUSE_NAMES[] = { + "INFO", + "DEBUG", + "WARNING", + "ERROR", + "CRITICAL", +}; + +static const char* CAUSE_COLORS[] = { + "", // INFO + "", // DEBUG + "\x1B[33m", // WARNING + "\x1B[31m", // ERROR + "\x1B[91m", // CRITICAL +}; + +static const char* FORMAT_CLEAR = "\x1B[0m"; + +void fishbone::Logger::log(Logger::Cause cause, std::string message) { + printf("%s[%s] %s%s\n", CAUSE_COLORS[(int)cause], CAUSE_NAMES[(int)cause], message.c_str(), FORMAT_CLEAR); +} + +void fishbone::Logger::log(std::string message) { + log(Logger::Cause::INFO, message); +} \ No newline at end of file diff --git a/engine/src/resource/resource.cc b/engine/src/resource/resource.cc new file mode 100644 index 0000000..649438e --- /dev/null +++ b/engine/src/resource/resource.cc @@ -0,0 +1,35 @@ +#include +#include +#include + +fishbone::Resource::Resource(fishbone::BaseEngine* engine, std::string path) { + fishbone::ResourceResolver* resolver = engine->getResourceResolver(); + + if (!resolver->exists(path)) { + buffer = nullptr; + bufferSize = 0; + engine->log(Logger::Cause::WARNING, "Resource does not exist: " + path); + return; + } + + this->bufferSize = resolver->getSize(path); + this->buffer = new char[bufferSize]; + resolver->copyData(path, buffer, bufferSize); +} + +fishbone::Resource::~Resource() { + if (this->buffer) + delete this->buffer; +} + +char* fishbone::Resource::getBuffer() { + return this->buffer; +} + +size_t fishbone::Resource::getSize() { + return this->bufferSize; +} + +fishbone::DirectoryResourceResolver::DirectoryResourceResolver(std::vector searchPaths) { + this->searchPaths = searchPaths; +} \ No newline at end of file diff --git a/engine/src/resource/unix.cc b/engine/src/resource/unix.cc new file mode 100644 index 0000000..4162488 --- /dev/null +++ b/engine/src/resource/unix.cc @@ -0,0 +1,46 @@ +#include +#include +#include +#include + +std::string fishbone::DirectoryResourceResolver::findAbsolutePath(std::string path) { + for(std::string searchPath : this->searchPaths) { + if(access((searchPath + "/" + path).c_str(), 0) == 0) { + return searchPath + "/" + path; + } + } + return ""; +} + +bool fishbone::DirectoryResourceResolver::exists(std::string path) { + return findAbsolutePath(path) != ""; +} + +size_t fishbone::DirectoryResourceResolver::getSize(std::string path) { + std::string absPath; + if ((absPath = findAbsolutePath(path)) == "") + return false; + + struct stat buf; + stat(absPath.c_str(), &buf); + + return buf.st_size; +} + +bool fishbone::DirectoryResourceResolver::copyData(std::string path, char* buffer, size_t maxSize) { + std::string absPath; + if ((absPath = findAbsolutePath(path)) == "") + return false; + + FILE* file = fopen(absPath.c_str(), "rb"); + if (!file) + return false; + + if (fread(buffer, maxSize, 1, file) == 0) { + fclose(file); + return false; + } + + fclose(file); + return true; +} \ No newline at end of file diff --git a/engine/tests/CMakeLists.txt b/engine/tests/CMakeLists.txt index e7c1c11..bd8b7cd 100644 --- a/engine/tests/CMakeLists.txt +++ b/engine/tests/CMakeLists.txt @@ -6,4 +6,6 @@ file(GLOB_RECURSE SRCS src/**.cc src/**.c) add_executable(fishbone_test ${SRCS}) target_link_libraries(fishbone_test PRIVATE fishbone Catch2::Catch2WithMain) target_include_directories(fishbone_test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src) -catch_discover_tests(fishbone_test) \ No newline at end of file +catch_discover_tests(fishbone_test) + +file(COPY testresources DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) \ No newline at end of file diff --git a/engine/tests/src/resource.cc b/engine/tests/src/resource.cc new file mode 100644 index 0000000..ab56575 --- /dev/null +++ b/engine/tests/src/resource.cc @@ -0,0 +1,34 @@ +#include "fishbone/client.h" +#include "fishbone/resource.h" +#include +#include +#include +#include + +namespace { + class TestEngine : public fishbone::BaseEngine { + public: + TestEngine() { + // TODO: Use abstraction instead of relying on POSIX + char cwd[PATH_MAX]; + getcwd(cwd, PATH_MAX); + this->resourceResolver = new fishbone::DirectoryResourceResolver({std::string(cwd) + "/testresources"}); + } + }; +} // namespace + +static const char* LOREM = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut " + "labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi " + "ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum " + "dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia " + "deserunt mollit anim id est laborum."; + +TEST_CASE("Directory loader") { + TestEngine engine; + + fishbone::Resource rsc(&engine, "lorem.txt"); + + REQUIRE(rsc.getBuffer() != NULL); + REQUIRE(rsc.getSize() == strlen(LOREM)); + REQUIRE(strncmp(rsc.getBuffer(), LOREM, rsc.getSize()) == 0); +} \ No newline at end of file diff --git a/engine/tests/src/thread.cc b/engine/tests/src/thread.cc index 6964453..21b5b3d 100644 --- a/engine/tests/src/thread.cc +++ b/engine/tests/src/thread.cc @@ -1,6 +1,5 @@ -#include "fishbone/thread.h" #include -#include +#include #include #include diff --git a/engine/tests/testresources/lorem.txt b/engine/tests/testresources/lorem.txt new file mode 100644 index 0000000..08e00ed --- /dev/null +++ b/engine/tests/testresources/lorem.txt @@ -0,0 +1 @@ +Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. \ No newline at end of file