Archived
1
Fork 0
This repository has been archived on 2025-04-12. You can view files and clone it, but cannot push or open issues or pull requests.
prism/engine/platform/include/file.hpp
Joshua Goins ca2c2c9d3d Move all engine-specific models, materials etc. to a new base directory
This is a huge change, and basically breaks everything (as per usual!)

First of, this includes stuff like shaders so anything involving those
are broken and then fixed. A new BuildAssets cmake file is added to
aid in running AssetCompiler, and it seems to work fine on the engine
base assets.

The File API will eventually be revamped to handle this new way of
organizing the files and domains will eventually be gotten rid of all
together since I probably will replace it with game directory
priorities. As it stands right now, there isn't a way to easily
replace say - render_options.cfg with your own game-specific version.

Apple builds are probably broken by this commit (since I'm moving
around content and shader directories) to be fixed later.
2022-05-21 18:28:48 -04:00

138 lines
4 KiB
C++
Executable file

#pragma once
#include <fstream>
#include <string>
#include <vector>
#include <optional>
#include <array>
#include <filesystem>
#include "log.hpp"
#include "path.hpp"
namespace prism {
enum class domain {
game,
base
};
/// Represents a file handle. The file may or may not be fully loaded in memory.
class file {
public:
explicit file(FILE* handle) : handle(handle) {}
file(file&& f) noexcept :
mem(std::move(f.mem)),
handle(std::exchange(f.handle, nullptr)),
data(std::move(f.data)) {}
~file() {
if(handle != nullptr)
fclose(handle);
}
/** Loads a type.
@param t The pointer to the type.
@param s If not 0, the size to load is derived from sizeof(T).
*/
template<typename T>
void read(T* t, const size_t s = 0) {
fread(t, s == 0 ? sizeof(T) : s, 1, handle);
}
void seek(const size_t s) {
fseek(handle, s, SEEK_CUR);
}
/// Reads a string. Assumes the length is an unsigned integer.
void read_string(std::string& str) {
unsigned int length = 0;
read(&length);
if(length > 0) {
str.resize(length);
read(str.data(), sizeof(char) * length);
}
}
/// Loads the entire file into memory, accessible via cast_data()
void read_all() {
fseek(handle, 0L, SEEK_END);
const auto _size = static_cast<size_t>(ftell(handle));
rewind(handle);
data.resize(_size);
fread(data.data(), _size, 1, handle);
}
/// If the file is loaded in memory, cast the underlying data.
template<typename T>
T* cast_data() {
return reinterpret_cast<T*>(data.data());
}
/// If the file is loaded in memory, return the size of the file.
[[nodiscard]] size_t size() const {
return data.size();
}
/// Reads the entire file as a string.
std::string read_as_string() {
auto s = read_as_stream();
return {(std::istreambuf_iterator<char>(s)), std::istreambuf_iterator<char>()};
}
/// Reads the entire file as a ifstream, useful for JSON deserialization.
std::istream read_as_stream() {
read_all();
auto char_data = cast_data<char>();
mem = std::make_unique<membuf>(char_data, char_data + size());
return std::istream(mem.get());
}
private:
struct membuf : std::streambuf {
inline membuf(char* begin, char* end) {
this->setg(begin, begin, end);
}
};
std::unique_ptr<membuf> mem;
FILE* handle = nullptr;
std::vector<std::byte> data;
};
/** Sets the domain path to a location in the filesystem.
@param domain The domain type.
@param mode The access mode.
@param path The absolute file path.
*/
void set_domain_path(domain domain, const path& domain_path);
path get_domain_path(domain domain);
/// Converts an absolute path to a domain relative path.
path get_relative_path(domain domain, const path& domain_relative_path);
/// Returns the path to a writeable directory.
path get_writeable_directory();
/**
Opens a file handle.
@param domain The file domain.
@param path The file path.
@param binary_mode Whether or not to open the file as binary or ASCII. Defaults to false.
@return An optional with a value if the file was loaded correctly, otherwise it's empty.
*/
std::optional<file> open_file(const path& file_path, bool binary_mode = false);
path root_path(const path& path);
path get_file_path(const path& path);
inline path base_domain = "/base", game_domain = "/game";
}
inline std::array<std::string, 3> domain_data;