#pragma once #include "IPlatformFileIO.h" #include #include #include #if defined(__linux__) #include #endif // Standard filesystem implementation for desktop platforms. class StdFileIO : public IPlatformFileIO { public: ReadResult readFile(const std::filesystem::path& path, void* buffer, std::size_t capacity) override { std::error_code ec; auto size = std::filesystem::file_size(path, ec); if (ec) return {ReadStatus::NotFound, 0, 0}; if (size > capacity) return {ReadStatus::TooLarge, 0, static_cast(size)}; std::ifstream f(path, std::ios::binary); if (!f) return {ReadStatus::NotFound, 0, 0}; f.read(static_cast(buffer), static_cast(size)); auto read = static_cast(f.gcount()); return {f ? ReadStatus::Ok : ReadStatus::ReadError, read, static_cast(size)}; } ReadResult readFileSegment(const std::filesystem::path& path, std::size_t offset, void* buffer, std::size_t bytesToRead) override { std::error_code ec; auto size = std::filesystem::file_size(path, ec); if (ec) return {ReadStatus::NotFound, 0, 0}; if (offset + bytesToRead > size) return {ReadStatus::TooLarge, 0, static_cast(size)}; std::ifstream f(path, std::ios::binary); if (!f) return {ReadStatus::NotFound, 0, 0}; f.seekg(static_cast(offset)); f.read(static_cast(buffer), static_cast(bytesToRead)); auto read = static_cast(f.gcount()); return {f ? ReadStatus::Ok : ReadStatus::ReadError, read, static_cast(size)}; } std::vector readFileToVec( const std::filesystem::path& path) override { std::error_code ec; auto size = std::filesystem::file_size(path, ec); if (ec) return {}; std::vector data(static_cast(size)); std::ifstream f(path, std::ios::binary); if (!f) return {}; f.read(reinterpret_cast(data.data()), static_cast(size)); return data; } bool writeFile(const std::filesystem::path& path, const void* buffer, std::size_t bytesToWrite) override { std::ofstream f(path, std::ios::binary); if (!f) return false; f.write(static_cast(buffer), static_cast(bytesToWrite)); return f.good(); } bool exists(const std::filesystem::path& path) override { return std::filesystem::exists(path); } std::size_t fileSize(const std::filesystem::path& path) override { std::error_code ec; auto size = std::filesystem::file_size(path, ec); return ec ? 0 : static_cast(size); } std::filesystem::path getBasePath() override { #if defined(__linux__) && !defined (__android__) char buf[4096]; ssize_t len = readlink("/proc/self/exe", buf, sizeof(buf) - 1); if (len > 0) { buf[len] = '\0'; return std::filesystem::path(buf).parent_path(); } #elif defined(__android__) // Because of the static init fiasco // I need to set the path before loading the library // I can only do this through ENV return std::filesystem::path( getenv("MC_PATH") ); #endif return std::filesystem::current_path(); } std::filesystem::path getUserDataPath() override { return getBasePath(); } };