#pragma once #include "gp_config.hpp" #include "gp/allocator/aggregator.hpp" #include "gp/buffer.hpp" #include "gp/optional.hpp" #include "gp/variant.hpp" #include "gp/vfs/fs_types.hpp" #include namespace gp { class vfs { private: struct virtual_fs { virtual ~virtual_fs() = default; virtual fs::open_return open(buffer, fs::file_flags, fs::file_permissions) = 0; virtual fs::read_return read(gp_config::file_descriptor_t, buffer) = 0; virtual fs::write_return write(gp_config::file_descriptor_t, buffer, size_t) = 0; virtual fs::close_return close(gp_config::file_descriptor_t) = 0; }; template class abstract_fs final : public virtual_fs{ concrete internal_representation; public: abstract_fs(abstract_fs& v) = delete; abstract_fs(abstract_fs&& v) : internal_representation{v.internal_representation} {} abstract_fs(concrete& v) = delete; abstract_fs(concrete&& v) : internal_representation{v} {} virtual ~abstract_fs() override = default; virtual fs::open_return open(buffer path, fs::file_flags flags, fs::file_permissions perms) override { return internal_representation.open(path, flags, perms); } virtual fs::read_return read(gp_config::file_descriptor_t fd, buffer buff) override { return internal_representation.read(fd, buff); } virtual fs::write_return write(gp_config::file_descriptor_t fd, buffer buff, size_t offset) override { return internal_representation.write(fd, buff, offset); } virtual fs::close_return close(gp_config::file_descriptor_t fd) override { return internal_representation.close(fd); } }; reference_wrapper allocator; virtual_fs* file_system; public: template vfs(T&& v, reference_wrapper _ref) : allocator{_ref} , file_system{new(allocator.get().allocate(sizeof(T))) T(gp::move(v))} {} fs::open_return open(buffer path, fs::file_flags flags, fs::file_permissions perms) { return file_system->open(path, flags, perms); } fs::read_return read(gp_config::file_descriptor_t fd, buffer buff) { return file_system->read(fd, buff); } fs::write_return write(gp_config::file_descriptor_t fd, buffer buff, size_t offset) { return file_system->write(fd, buff, offset); } fs::close_return close(gp_config::file_descriptor_t fd) { return file_system->close(fd); } ~vfs() { file_system->~virtual_fs(); allocator.get().deallocate(file_system); } }; }