#pragma once #include #include "gp_config.hpp" #include "gp/variant.hpp" #include "gp/optional.hpp" #include "gp/buffer.hpp" #include "gp/allocator/aggregator.hpp" namespace gp { class vfs { public: struct bad_file final { static constexpr auto _what = "bad_file"; constexpr auto what() { return _what; } }; struct faulty_buffer final { static constexpr auto _what = "faulty_buffer"; constexpr auto what() { return _what; } }; struct interrupted final { static constexpr auto _what = "interrupted"; constexpr auto what() { return _what; } }; struct io_error final { static constexpr auto _what = "io_error"; constexpr auto what() { return _what; } }; struct is_directory final { static constexpr auto _what = "is_directory"; constexpr auto what() { return _what; } }; struct try_again final { static constexpr auto _what = "try_again"; constexpr auto what() { return _what; } }; struct not_connected final { static constexpr auto _what = "not_connected"; constexpr auto what() { return _what; } }; struct impossible_io final { static constexpr auto _what = "impossible_io"; constexpr auto what() { return _what; } }; struct negative_offset final { static constexpr auto _what = "negative_offset"; constexpr auto what() { return _what; } }; struct is_pipe final { static constexpr auto _what = "is_pipe"; constexpr auto what() { return _what; } }; struct buffer_too_big final { static constexpr auto _what = "buffer_too_big"; constexpr auto what() { return _what; } }; struct path_not_directory final { static constexpr auto _what = "path_not_directory"; constexpr auto what() { return _what; } }; struct name_too_long final { static constexpr auto _what = "name_too_long"; constexpr auto what() { return _what; } }; struct does_not_exist final { static constexpr auto _what = "does_not_exist"; constexpr auto what() { return _what; } }; struct may_loop final { static constexpr auto _what = "may_loop"; constexpr auto what() { return _what; } }; struct invalid_flags final { static constexpr auto _what = "invalid_flags"; constexpr auto what() { return _what; } }; struct is_read_only final { static constexpr auto _what = "is_read_only"; constexpr auto what() { return _what; } }; struct fd_limit_reached final { static constexpr auto _what = "fd_limit_reached"; constexpr auto what() { return _what; } }; struct file_limit_reached final { static constexpr auto _what = "file_limit_reached"; constexpr auto what() { return _what; } }; struct no_locking final { static constexpr auto _what = "no_locking"; constexpr auto what() { return _what; } }; struct would_block final { static constexpr auto _what = "would_block"; constexpr auto what() { return _what; } }; struct no_inodes final { static constexpr auto _what = "no_inodes"; constexpr auto what() { return _what; } }; struct no_space final { static constexpr auto _what = "no_space"; constexpr auto what() { return _what; } }; struct quota_reached final { static constexpr auto _what = "quota_reached"; constexpr auto what() { return _what; } }; struct cannot_write_shared_text final { static constexpr auto _what = "cannot_write_shared_text"; constexpr auto what() { return _what; } }; struct faulty_filename final { static constexpr auto _what = "faulty_filename"; constexpr auto what() { return _what; } }; struct exists_already final { static constexpr auto _what = "exists_already"; constexpr auto what() { return _what; } }; struct is_append_only final { static constexpr auto _what = "is_append_only"; constexpr auto what() { return _what; } }; struct unimplemented_operation final { static constexpr auto _what = "unimplemented_operation"; constexpr auto what() { return _what; } }; struct is_busy final { static constexpr auto _what = "is_busy"; constexpr auto what() { return _what; } }; struct bad_relative_path final { static constexpr auto _what = "bad_relative_path"; constexpr auto what() { return _what; } }; struct no_permissions final { static constexpr auto _what = "no_permissions"; constexpr auto what() { return _what; } }; struct success final { static constexpr auto _what = "success"; constexpr auto what() { return _what; } }; struct too_big final { static constexpr auto _what = "too_big"; constexpr auto what() { return _what; } }; struct network_down final { static constexpr auto _what = "network_down"; constexpr auto what() { return _what; } }; struct destination_not_available final { static constexpr auto _what = "destination_not_available"; constexpr auto what() { return _what; } }; struct insufficient_buffer_space final { static constexpr auto _what = "insufficient_buffer_space"; constexpr auto what() { return _what; } }; using read_return = gp::fixed_variant< typename buffer::associated_iterator, // iterator to last element read bad_file, faulty_buffer, interrupted, io_error, is_directory, try_again, not_connected, impossible_io, negative_offset, is_pipe, buffer_too_big >; using open_return = gp::fixed_variant< gp_config::file_descriptor_t, path_not_directory, name_too_long, does_not_exist, may_loop, is_directory, invalid_flags, is_read_only, fd_limit_reached, file_limit_reached, impossible_io, interrupted, no_locking, would_block, no_space, no_inodes, quota_reached, io_error, cannot_write_shared_text, faulty_filename, exists_already, is_append_only, unimplemented_operation, is_busy, bad_relative_path, no_permissions >; using close_return = gp::fixed_variant< success, bad_file, interrupted, io_error >; using write_return = gp::fixed_variant< typename buffer::associated_iterator, bad_file, no_space, quota_reached, too_big, interrupted, io_error, faulty_buffer, is_pipe, try_again, network_down, destination_not_available, impossible_io, buffer_too_big, negative_offset, insufficient_buffer_space >; class file_flags{}; class file_permissions{}; private: struct virtual_fs { virtual ~virtual_fs() = default; virtual open_return open(buffer, file_flags, file_permissions) = 0; virtual read_return read(gp_config::file_descriptor_t, buffer) = 0; virtual write_return write(gp_config::file_descriptor_t, buffer, size_t) = 0; virtual 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 open_return open(buffer path, file_flags flags, file_permissions perms) override { return internal_representation.open(path, flags, perms); } virtual read_return read(gp_config::file_descriptor_t fd, buffer buff) override { return internal_representation.read(fd, buff); } virtual write_return write(gp_config::file_descriptor_t fd, buffer buff, size_t offset) override { return internal_representation.write(fd, buff, offset); } virtual 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))} {} open_return open(buffer path, file_flags flags, file_permissions perms) { return file_system->open(path, flags, perms); } read_return read(gp_config::file_descriptor_t fd, buffer buff) { return file_system->read(fd, buff); } write_return write(gp_config::file_descriptor_t fd, buffer buff, size_t offset) { return file_system->write(fd, buff, offset); } close_return close(gp_config::file_descriptor_t fd) { return file_system->close(fd); } ~vfs() { file_system->~virtual_fs(); allocator.get().deallocate(file_system); } }; }