Skip to content

Commit

Permalink
filesystem setup
Browse files Browse the repository at this point in the history
  • Loading branch information
K1ngst0m committed Oct 28, 2023
1 parent a8c2886 commit 93584d6
Show file tree
Hide file tree
Showing 6 changed files with 410 additions and 1 deletion.
1 change: 1 addition & 0 deletions cmake/AphDefinitions.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@ set(APH_ENGINE_APP_DIR ${APH_ENGINE_DIR}/app)
set(APH_ENGINE_RENDERER_DIR ${APH_ENGINE_DIR}/renderer)
set(APH_ENGINE_WSI_DIR ${APH_ENGINE_DIR}/wsi)
set(APH_ENGINE_THREADS_DIR ${APH_ENGINE_DIR}/threads)
set(APH_ENGINE_FILESYSTEM_DIR ${APH_ENGINE_DIR}/filesystem)
# set(APH_ENGINE_SCENE_DIR ${APH_ENGINE_DIR}/scene)
# set(APH_ENGINE_UI_DIR ${APH_ENGINE_DIR}/ui)
13 changes: 12 additions & 1 deletion engine/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ add_subdirectory(wsi)
add_subdirectory(resource)
add_subdirectory(api)
add_subdirectory(renderer)
add_subdirectory(filesystem)

add_library(aph_engine INTERFACE)

Expand All @@ -14,7 +15,17 @@ target_include_directories(aph_engine INTERFACE
${APH_EXTERNAL_DIR}/glm
${APH_ENGINE_DIR}
)
target_link_libraries(aph_engine INTERFACE common app cli threads wsi resource api renderer)
target_link_libraries(aph_engine INTERFACE
common
app
cli
threads
wsi
resource
api
renderer
aph_filesystem
)

target_link_libraries(aph_engine INTERFACE
mimalloc-static
Expand Down
5 changes: 5 additions & 0 deletions engine/filesystem/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
file(GLOB APH_FILESYSTEM_SRC ${APH_ENGINE_FILESYSTEM_DIR}/*.cpp)
add_library(aph_filesystem STATIC ${APH_FILESYSTEM_SRC})
aph_compiler_options(aph_filesystem)
target_include_directories(aph_filesystem PRIVATE ${APH_ENGINE_DIR})
target_link_libraries(aph_filesystem PRIVATE common)
191 changes: 191 additions & 0 deletions engine/filesystem/filesystem.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
#include "filesystem.h"
#include "common/logger.h"

namespace aph
{

Filesystem::Filesystem()
{
m_protocols["assets"] = "assets/";
m_protocols["models"] = "assets/models";
m_protocols["fonts"] = "assets/fonts";
m_protocols["shader_glsl"] = "assets/shaders/glsl";
m_protocols["shader_slang"] = "assets/shaders/slang";
m_protocols["textures"] = "assets/textures";
m_protocols["file"] = "";
}

Filesystem::~Filesystem()
{
clearMappedFiles();
}

void Filesystem::registerProtocol(std::string_view protocol, const std::string& path)
{
if(protocolExists(protocol))
{
CM_LOG_WARN("overrided the existing protocol %s. path: %s -> %s", protocol, m_protocols[protocol.data()], path);
}
m_protocols[protocol.data()] = path;
}

bool Filesystem::protocolExists(std::string_view protocol)
{
return m_protocols.contains(protocol.data());
}

void Filesystem::removeProtocol(std::string_view protocol)
{
m_protocols.erase(protocol.data());
}

void Filesystem::clearMappedFiles()
{
for(auto& [data, size] : m_mappedFiles)
{
munmap(data, size);
}
m_mappedFiles.clear();
}

std::filesystem::path Filesystem::resolvePath(std::string_view inputPath)
{
auto protocolEnd = inputPath.find("://");
std::string protocol;
std::string relativePath;

if(protocolEnd != std::string::npos)
{
protocol = inputPath.substr(0, protocolEnd);
relativePath = inputPath.substr(protocolEnd + 3);
}
else
{
protocol = "file";
relativePath = inputPath;
}

if(!m_protocols.contains(protocol))
{
CM_LOG_ERR("Unknown protocol: %s", protocol);
return {};
}

return std::filesystem::path(m_protocols[protocol]) / relativePath;
}

void* Filesystem::map(std::string_view path)
{
std::lock_guard<std::mutex> lock(m_mapLock);
auto resolvedPath = resolvePath(path);

int fd = open(resolvedPath.string().c_str(), O_RDONLY);
if(fd == -1)
return nullptr;

struct stat fileStat;
if(fstat(fd, &fileStat) == -1)
{
close(fd);
return nullptr;
}

void* mappedData = mmap(0, fileStat.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
close(fd);

if(mappedData == MAP_FAILED)
{
return nullptr;
}

m_mappedFiles[mappedData] = fileStat.st_size;
return mappedData;
}

void Filesystem::unmap(void* data)
{
if(m_mappedFiles.find(data) != m_mappedFiles.end())
{
munmap(data, m_mappedFiles[data]);
m_mappedFiles.erase(data);
}
}

std::string Filesystem::readFileToString(std::string_view path)
{
std::ifstream file(resolvePath(path), std::ios::in);
if(!file)
{
CM_LOG_ERR("Unable to open file: %s", path);
return {};
}
return std::string((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
}
std::vector<uint8_t> Filesystem::readFileToBytes(std::string_view path)
{
std::ifstream file(resolvePath(path), std::ios::binary | std::ios::ate);
if(!file)
{
CM_LOG_ERR("Unable to open file: %s", path);
return {};
}

std::streamsize size = file.tellg();
file.seekg(0, std::ios::beg);

std::vector<uint8_t> buffer(size);
if(!file.read((char*)buffer.data(), size))
{
CM_LOG_ERR("Error reading file: %s", path);
return {};
}
return buffer;
}
std::vector<std::string> Filesystem::readFileLines(std::string_view path)
{
std::ifstream file(resolvePath(path));
if(!file)
{
CM_LOG_ERR("Unable to open file: %s", path);
return {};
}

std::vector<std::string> lines;
std::string line;
while(std::getline(file, line))
{
lines.push_back(line);
}
return lines;
}
void Filesystem::writeStringToFile(std::string_view path, const std::string& content)
{
std::ofstream file(resolvePath(path).string(), std::ios::binary);
if(!file)
{
throw std::runtime_error("Failed to open file for writing: " + std::string(path));
}
file << content;
}
void Filesystem::writeBytesToFile(std::string_view path, const std::vector<uint8_t>& bytes)
{
std::ofstream file(resolvePath(path).string(), std::ios::binary);
if(!file)
{
throw std::runtime_error("Failed to open file for writing: " + std::string(path));
}
file.write(reinterpret_cast<const char*>(bytes.data()), bytes.size());
}
void Filesystem::writeLinesToFile(std::string_view path, const std::vector<std::string>& lines)
{
std::ofstream file(resolvePath(path).string());
if(!file)
{
throw std::runtime_error("Failed to open file for writing: " + std::string(path));
}
for(const auto& line : lines)
{
file << line << '\n';
}
}
} // namespace aph
54 changes: 54 additions & 0 deletions engine/filesystem/filesystem.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#ifndef FILESYSTEM_H_
#define FILESYSTEM_H_

#include <filesystem>
#include <string>
#include <map>
#include <memory>
#include <iostream>
#include <memory.h>
#include <sys/inotify.h>
#include <thread>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>

namespace aph
{
class Filesystem
{
public:
Filesystem();

~Filesystem();

void* map(std::string_view path);
void unmap(void* data);
void clearMappedFiles();

std::string readFileToString(std::string_view path);
std::vector<uint8_t> readFileToBytes(std::string_view path);
std::vector<std::string> readFileLines(std::string_view path);

void writeStringToFile(std::string_view path, const std::string& content);
void writeBytesToFile(std::string_view path, const std::vector<uint8_t>& bytes);
void writeLinesToFile(std::string_view path, const std::vector<std::string>& lines);

void registerProtocol(std::string_view protocol, const std::string& path);
bool protocolExists(std::string_view protocol);
void removeProtocol(std::string_view protocol);

private:
std::filesystem::path resolvePath(std::string_view inputPath);

private:
std::map<int, std::function<void()>> m_callbacks;
std::map<std::string, std::string> m_protocols;
std::map<void*, std::size_t> m_mappedFiles;
std::mutex m_mapLock;
};

} // namespace aph

#endif // FILESYSTEM_H_
Loading

0 comments on commit 93584d6

Please sign in to comment.