2#ifndef LIBSBX_FILESYSTEM_MEMORY_FILESYSTEM_HPP_
3#define LIBSBX_FILESYSTEM_MEMORY_FILESYSTEM_HPP_
5#include <unordered_map>
12#include <libsbx/utility/lockable.hpp>
14#include <libsbx/filesystem/filesystem_base.hpp>
15#include <libsbx/filesystem/memory_file.hpp>
17namespace sbx::filesystem {
19template<utility::lockable Lockable>
24 using lockable_type = Lockable;
27 : _alias_path(std::move(alias_path)) {}
33 [[nodiscard]]
auto initialize() ->
bool override {
34 auto lock = std::scoped_lock{_mutex};
45 auto shutdown() ->
void override {
46 auto lock = std::scoped_lock{_mutex};
52 [[nodiscard]]
auto is_initialized()
const ->
bool override {
53 auto lock = std::scoped_lock{_mutex};
58 [[nodiscard]]
auto base_path()
const ->
const std::string&
override {
59 auto lock = std::scoped_lock{_mutex};
64 [[nodiscard]]
auto virtual_path()
const ->
const std::string&
override {
65 auto lock = std::scoped_lock{_mutex};
70 [[nodiscard]]
auto files()
const -> files_list
override {
71 auto lock = std::scoped_lock{_mutex};
73 auto list = files_list{};
74 list.reserve(_files.size());
76 for (
const auto& [path, entry] : _files) {
77 list.push_back(entry.info);
83 [[nodiscard]]
auto is_read_only()
const ->
bool override {
87 [[nodiscard]]
auto open_file(
const std::string& path,
const file_base::mode mode) -> file_ptr
override {
88 auto lock = std::scoped_lock{_mutex};
90 auto info =
file_info{_alias_path, _alias_path, path};
92 auto [entry, inserted] = _files.try_emplace(path, file_entry{info, std::make_shared<detail::memory_file_object<lockable_type>>()});
94 auto& file_entry = entry->second;
96 if (!file_entry.object) {
97 file_entry.object = std::make_shared<detail::memory_file_object<lockable_type>>();
100 auto file = std::make_shared<basic_memory_file<lockable_type>>(
file_info{file_entry.info}, detail::memory_file_object_ptr<lockable_type>{file_entry.object});
102 if (!file || !file->open(mode)) {
106 file_entry.opened_handles.push_back(file);
111 auto close_file(
const file_ptr& file) ->
void override {
112 auto lock = std::scoped_lock{_mutex};
114 _cleanup_handles(file);
117 [[nodiscard]]
auto create_file(
const std::string& path) -> file_ptr
override {
118 return open_file(path, file_base::mode::read_write | file_base::mode::truncate);
121 [[nodiscard]]
auto remove_file(
const std::string& path) ->
bool override {
122 auto lock = std::scoped_lock{_mutex};
124 auto entry = _files.find(path);
126 if (entry == _files.end()) {
136 [[nodiscard]]
auto copy_file(
const std::string& source,
const std::string& destination,
const bool overwrite =
false) ->
bool override {
137 auto lock = std::scoped_lock{_mutex};
139 auto source_entry = _files.find(source);
141 if (source_entry == _files.end()) {
145 auto destination_entry = _files.find(destination);
147 if (destination_entry != _files.end() && !overwrite) {
151 if (destination_entry != _files.end()) {
152 _files.erase(destination_entry);
155 auto new_object = detail::memory_file_object_ptr<lockable_type>{};
157 if (source_entry->second.object) {
158 new_object = std::make_shared<detail::memory_file_object<lockable_type>>(*source_entry->second.object);
160 new_object = std::make_shared<detail::memory_file_object<lockable_type>>();
163 auto info =
file_info{_alias_path, _alias_path, destination};
165 _files.emplace(destination, file_entry{info, std::move(new_object)});
170 [[nodiscard]]
auto rename_file(
const std::string& source,
const std::string& destination) ->
bool override {
171 if (!copy_file(source, destination,
false)) {
175 return remove_file(source);
178 [[nodiscard]]
auto exists(
const std::string& path)
const ->
bool override {
179 auto lock = std::scoped_lock{_mutex};
180 return _files.find(path) != _files.end();
187 using weak_handle = std::weak_ptr<basic_memory_file<lockable_type>>;
190 detail::memory_file_object_ptr<lockable_type> object;
191 std::vector<weak_handle> opened_handles;
193 void cleanup(
const file_ptr& exclude =
nullptr) {
194 opened_handles.erase(std::remove_if(opened_handles.begin(), opened_handles.end(), [&](
const weak_handle& handle) {
195 return handle.expired() || handle.lock() == exclude;
196 }), opened_handles.end());
201 auto _cleanup_handles(
const file_ptr& to_close =
nullptr) ->
void {
203 const auto& path = to_close->info().virtual_path();
205 auto entry = _files.find(path);
207 if (entry != _files.end()) {
212 for (
auto& [_, entry] : _files) {
213 entry.cleanup(to_close);
219 std::string _alias_path;
220 bool _initialized{
false};
222 mutable lockable_type _mutex;
223 std::unordered_map<std::string, file_entry> _files;
Definition: memory_filesystem.hpp:20
Definition: file_info.hpp:10
Definition: filesystem_base.hpp:14