feat: directory-based resource resolver

This commit is contained in:
maelstrom 2026-06-02 11:27:44 +02:00
commit 656549f039
12 changed files with 223 additions and 11 deletions

View file

@ -5,25 +5,35 @@
namespace fishbone {
class Client;
};
class ResourceResolver;
}; // namespace fishbone
#include <fishbone/sound.h>
#include <fishbone/window.h>
#include <fishbone/mixer.h>
#include <fishbone/draw.h>
#include <fishbone/logger.h>
namespace fishbone {
class Client {
class BaseEngine : public Logger {
protected:
ResourceResolver* resourceResolver;
public:
ResourceResolver* getResourceResolver();
};
class Client : public BaseEngine {
public:
Client(std::unordered_map<std::string, std::vector<std::string>> param);
~Client();
bool step();
fishbone::Window* window;
fishbone::SoundDriver* sounddrv;
fishbone::Mixer* mixer;
fishbone::Renderer* renderer;
fishbone::Mixer* mixer;
fishbone::Renderer* renderer;
};
}; // namespace fishbone

View file

@ -0,0 +1,23 @@
#ifndef __FISHBONE_LOGGER_H__
#define __FISHBONE_LOGGER_H__
#include <fishbone/pre.h>
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

View file

@ -1,21 +1,47 @@
#ifndef __FISHBONE_THREAD_H__
#define __FISHBONE_THREAD_H__
#ifndef __FISHBONE_RESOURCE_H__
#define __FISHBONE_RESOURCE_H__
#include <fishbone/pre.h>
namespace fishbone {
class Resource;
class BaseEngine;
}; // namespace fishbone
#include <fishbone/file.h>
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<std::string> searchPaths;
std::string findAbsolutePath(std::string path);
public:
DirectoryResourceResolver(std::vector<std::string> 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

View file

@ -1,3 +1,4 @@
#include <fishbone/resource.h>
#include <fishbone/foundation.h>
fishbone::Client::Client(std::unordered_map<std::string, std::vector<std::string>> param){
@ -5,6 +6,7 @@ fishbone::Client::Client(std::unordered_map<std::string, std::vector<std::string
this->sounddrv = 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(){

6
engine/src/engine.cc Normal file
View file

@ -0,0 +1,6 @@
#include <fishbone/client.h>
#include <fishbone/resource.h>
fishbone::ResourceResolver* fishbone::BaseEngine::getResourceResolver() {
return this->resourceResolver;
}

28
engine/src/logger.cc Normal file
View file

@ -0,0 +1,28 @@
#include <cstdio>
#include <fishbone/logger.h>
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);
}

View file

@ -0,0 +1,35 @@
#include <fishbone/client.h>
#include <fishbone/resource.h>
#include <vector>
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<std::string> searchPaths) {
this->searchPaths = searchPaths;
}

View file

@ -0,0 +1,46 @@
#include <cstdio>
#include <fishbone/resource.h>
#include <unistd.h>
#include <sys/stat.h>
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;
}

View file

@ -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)
catch_discover_tests(fishbone_test)
file(COPY testresources DESTINATION ${CMAKE_CURRENT_BINARY_DIR})

View file

@ -0,0 +1,34 @@
#include "fishbone/client.h"
#include "fishbone/resource.h"
#include <catch2/catch_test_macros.hpp>
#include <cstring>
#include <limits.h>
#include <unistd.h>
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);
}

View file

@ -1,6 +1,5 @@
#include "fishbone/thread.h"
#include <catch2/catch_test_macros.hpp>
#include <cstdio>
#include <fishbone/thread.h>
#include <cstdlib>
#include <unistd.h>

View file

@ -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.