Euphoria
vfs.cc
Go to the documentation of this file.
1 #include "io/vfs.h"
2 
3 #include <fstream>
4 
5 #include "assert/assert.h"
6 
7 #include "log/log.h"
8 
9 #include "base/os.h"
10 #include "base/stringmerger.h"
11 #include "base/stringutils.h"
12 
13 #include "io/io.h"
14 #include "io/vfs_path.h"
15 
16 
17 
18 namespace eu::io
19 {
21 
22 
23  ListedFile::ListedFile(const std::string& n, bool b, bool f)
24  : name(n)
25  , is_builtin(b)
26  , is_file(f)
27  {
28  }
29 
30 
32 
33 
34  void
36  {
37  auto& target = file.is_file ? files : folders;
38  const auto found = target.find(file.name);
39  if(found == target.end())
40  {
41  target[file.name] = file;
42  }
43  }
44 
45 
46  void
47  FileList::add(const std::string& n, bool b, bool f)
48  {
49  add(ListedFile {n, b, f});
50  }
51 
52 
54 
55 
56  ReadRoot::~ReadRoot() = default;
57 
58 
59  WriteRoot::~WriteRoot() = default;
60 
61 
63 
64 
65  FileSystem::FileSystem() = default;
66 
67 
68  FileSystem::~FileSystem() = default;
69 
70 
71  void
72  FileSystem::add_read_root(const std::shared_ptr<ReadRoot>& root)
73  {
74  read_roots.push_back(root);
75  }
76 
77 
78  void
79  FileSystem::set_write_root(const std::shared_ptr<WriteRoot>& root)
80  {
81  write_root = root;
82  }
83 
84 
85  std::shared_ptr<MemoryChunk>
87  {
88  FilePath path = a_path;
89 
90  if(a_path.get_directory().contains_relative())
91  {
92  const auto resolved_path = resolve_relative(a_path, DirPath::from_root());
93  if(resolved_path.has_value() == false)
94  {
95  LOG_ERROR("Unable to resolve path to a valid path {0}", a_path);
96  return MemoryChunk::create_null();
97  }
98  path = resolved_path.value();
99  }
100 
101  for(auto& root: read_roots)
102  {
103  std::shared_ptr<MemoryChunk> file = root->read_file(path);
104  if(file != nullptr)
105  {
106  return file;
107  }
108  }
109 
110  return MemoryChunk::create_null();
111  }
112 
113 
114  void
116  (
117  const FilePath& path,
118  std::shared_ptr<MemoryChunk> data
119  )
120  {
122  write_root->write_file(path, data);
123  }
124 
125 
126  std::vector<ListedFile>
128  {
129  FileList combined;
130  for(auto& root: read_roots)
131  {
132  const auto files = root->list_files(path);
133  for(const auto& f: files.files)
134  {
135  combined.add(f.second);
136  }
137  for(const auto& f: files.folders)
138  {
139  combined.add(f.second);
140  }
141  }
142 
143  std::vector<ListedFile> r;
144  for(const auto& f: combined.folders)
145  {
146  r.emplace_back(f.second);
147  }
148  for(const auto& f: combined.files)
149  {
150  r.emplace_back(f.second);
151  }
152  return r;
153  }
154 
155 
156  std::string
158  {
159  std::vector<std::string> ret;
160  for(auto& root: read_roots)
161  {
162  root->add_description(&ret);
163  }
164 
165  return string_mergers::array.merge(ret);
166  }
167 
168 
169  std::optional<std::string>
171  (
172  const FilePath& path
173  )
174  {
175  std::shared_ptr<MemoryChunk> file = read_file(path);
176  if(file == nullptr)
177  {
178  return std::nullopt;
179  }
180 
181  // data is unsigned char, cast it to char and assume it is a string
182  return std::string(file->get_data(), file->get_size() - 1);
183  }
184 
185 
187 
188 
190 
191 
192  void
194  (
195  const FilePath& path,
196  const std::string& content
197  )
198  {
199  std::shared_ptr<MemoryChunk> file = create_memory_chunk_from_string(content);
200  register_file_data(path, file);
201  }
202 
203 
204  void
206  (
207  const FilePath& path,
208  const std::shared_ptr<MemoryChunk>& content
209  )
210  {
211  catalog.insert(std::make_pair(path, content));
212  }
213 
214 
215  std::shared_ptr<ReadRootCatalog>
217  {
218  ASSERT(fs);
219  auto catalog = std::make_shared<ReadRootCatalog>();
220  fs->add_read_root(catalog);
221  return catalog;
222  }
223 
224 
225  std::shared_ptr<MemoryChunk>
227  {
228  const auto found = catalog.find(path);
229 
230  if(found == catalog.end())
231  {
232  return MemoryChunk::create_null();
233  }
234 
235  return found->second;
236  }
237 
238 
239  void
240  ReadRootCatalog::add_description(std::vector<std::string>* strings)
241  {
242  const auto keys = from_key_to_string_vector(catalog);
243  strings->insert(strings->end(), keys.begin(), keys.end());
244  }
245 
246  FileList
248  {
249  FileList r;
250  for(const auto& f: catalog)
251  {
252  const auto file = f.first;
253  const auto [folder, filename] = file.split_directories_and_file();
254  if(path == folder)
255  {
256  r.add(filename, true, true);
257  }
258  }
259 
260  return r;
261  }
262 
263 
265 
266 
267  std::string
268  combine_folder_and_path(const std::string& folder, const FilePath& path)
269  {
270  return folder + path.path.substr(2);
271  }
272 
273 
274  std::string
275  combine_folder_and_path(const std::string& folder, const DirPath& path)
276  {
277  return folder + path.path.substr(2);
278  }
279 
280 
281  std::string
282  make_sure_folder_ends_with_slash(const std::string& folder)
283  {
284  const std::string slash = "/";
285 
286  const std::string the_folder
287  = ends_with(folder, slash) ? folder : folder + slash;
288  return the_folder;
289  }
290 
291 
293 
294 
296  : folder(std::move(f))
297  {
298  }
299 
300 
301  std::shared_ptr<MemoryChunk>
303  {
304  const std::string& full_path = combine_folder_and_path(folder, path);
305  return io::read_file_to_chunk(full_path);
306  }
307 
308 
309  void
310  ReadRootPhysicalFolder::add_description(std::vector<std::string>* strings)
311  {
312  strings->emplace_back(folder);
313  }
314 
315 
316  void
317  ReadRootPhysicalFolder::add(FileSystem* fs, const std::string& folder)
318  {
319  ASSERT(fs);
320 
321  auto catalog = std::make_shared<ReadRootPhysicalFolder>(make_sure_folder_ends_with_slash(folder));
322 
323  fs->add_read_root(catalog);
324  }
325 
326 
327  void
329  {
330  const std::string folder = get_current_directory();
332  }
333 
334 
335  FileList
337  {
338  const auto real_path
340  const auto found = list_directory(real_path);
341 
342  FileList r;
343 
344  if(found.valid)
345  {
346  for(const auto& f: found.files)
347  {
348  r.add(f, false, true);
349  }
350  for(const auto& d: found.directories)
351  {
352  auto f = d;
353  if(!ends_with(f, '/'))
354  {
355  f += +"/";
356  }
357  r.add(f, false, false);
358  }
359  }
360 
361  return r;
362  }
363 
364 
366 
367 
370  {
371  }
372 
373 
374  void
376  (
377  const FilePath& path,
378  std::shared_ptr<MemoryChunk> data
379  )
380  {
381  const auto full_path = combine_folder_and_path(folder, path);
382  io::write_chunk_to_file(data, full_path);
383  }
384 }
385 
#define ASSERT(x)
Definition: assert.h:29
std::vector< std::string > from_key_to_string_vector(const std::map< TKey, TValue > &map)
Definition: stringutils.h:178
#define LOG_ERROR(...)
Definition: log.h:9
Definition: enum.h:8
std::string make_sure_folder_ends_with_slash(const std::string &folder)
Definition: vfs.cc:282
std::string combine_folder_and_path(const std::string &folder, const FilePath &path)
Definition: vfs.cc:268
std::shared_ptr< MemoryChunk > read_file_to_chunk(const std::string &full_path)
Definition: io.cc:37
std::optional< DirPath > resolve_relative(const DirPath &base)
Definition: vfs_path.cc:349
void write_chunk_to_file(std::shared_ptr< MemoryChunk > chunk, const std::string &full_path)
Definition: io.cc:14
constexpr StringMerger array
Definition: stringmerger.h:91
std::string get_current_directory()
Definition: os.cc:35
bool ends_with(const std::string &str, char c)
Definition: os.cc:139
std::shared_ptr< MemoryChunk > create_memory_chunk_from_string(const std::string &content)
Definition: memorychunk.cc:66
DirectoryListing list_directory(const std::string &path)
Definition: os.cc:95
String utility functions.
static std::shared_ptr< MemoryChunk > create_null()
Definition: memorychunk.cc:47
std::string merge(const std::vector< std::string > &strings) const
Definition: stringmerger.cc:11
std::string path
contains either . or ~ at the start, / at the end
Definition: vfs_path.h:69
bool contains_relative() const
Definition: vfs_path.cc:270
static DirPath from_root()
Definition: vfs_path.cc:218
void add(const ListedFile &file)
Definition: vfs.cc:35
std::map< std::string, ListedFile > files
Definition: vfs.h:27
std::map< std::string, ListedFile > folders
Definition: vfs.h:28
DirPath get_directory() const
Definition: vfs_path.cc:137
std::string path
contains either .
Definition: vfs_path.h:39
std::vector< std::shared_ptr< ReadRoot > > read_roots
Definition: vfs.h:75
std::optional< std::string > read_file_to_string(const FilePath &path)
Definition: vfs.cc:171
void add_read_root(const std::shared_ptr< ReadRoot > &root)
Definition: vfs.cc:72
void write_file(const FilePath &path, std::shared_ptr< MemoryChunk > data)
Definition: vfs.cc:116
std::shared_ptr< MemoryChunk > read_file(const FilePath &path)
Definition: vfs.cc:86
std::string get_roots_as_string()
Definition: vfs.cc:157
std::vector< ListedFile > list_files(const DirPath &path)
Definition: vfs.cc:127
void set_write_root(const std::shared_ptr< WriteRoot > &root)
Definition: vfs.cc:79
std::shared_ptr< WriteRoot > write_root
Definition: vfs.h:76
bool is_file
Definition: vfs.h:19
ListedFile()=default
std::string name
Definition: vfs.h:17
void register_file_data(const FilePath &path, const std::shared_ptr< MemoryChunk > &content)
Definition: vfs.cc:206
void add_description(std::vector< std::string > *strings) override
Definition: vfs.cc:240
static std::shared_ptr< ReadRootCatalog > create_and_add(FileSystem *fs)
Definition: vfs.cc:216
FileList list_files(const DirPath &path) override
Definition: vfs.cc:247
std::shared_ptr< MemoryChunk > read_file(const FilePath &path) override
Definition: vfs.cc:226
void register_file_string(const FilePath &path, const std::string &content)
Definition: vfs.cc:194
void add_description(std::vector< std::string > *strings) override
Definition: vfs.cc:310
static void add(FileSystem *fs, const std::string &folder)
Definition: vfs.cc:317
static void add_current_directory(FileSystem *fs)
Definition: vfs.cc:328
FileList list_files(const DirPath &path) override
Definition: vfs.cc:336
std::shared_ptr< MemoryChunk > read_file(const FilePath &path) override
Definition: vfs.cc:302
ReadRootPhysicalFolder(std::string folder)
Definition: vfs.cc:295
virtual ~ReadRoot()
WriteRootPhysicalFolder(const std::string &f)
Definition: vfs.cc:368
void write_file(const FilePath &path, std::shared_ptr< MemoryChunk > data) override
Definition: vfs.cc:376
virtual ~WriteRoot()