From 6e9322987dbbb4a0f54c271c0bc0785d9a92443c Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Sun, 17 Jun 2018 20:19:10 -0400 Subject: [PATCH] Finish abstract Vfs classes --- src/core/file_sys/vfs.cpp | 58 ++++++++++++++++++- src/core/file_sys/vfs.h | 116 +++++++++++++++++++++++--------------- 2 files changed, 127 insertions(+), 47 deletions(-) diff --git a/src/core/file_sys/vfs.cpp b/src/core/file_sys/vfs.cpp index 59852dbd5d..bd19ac0743 100644 --- a/src/core/file_sys/vfs.cpp +++ b/src/core/file_sys/vfs.cpp @@ -2,6 +2,62 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include #include "core/file_sys/vfs.h" -namespace FileSys {} +namespace FileSys { + +VfsFile::operator bool() { + return IsGood(); +} + +boost::optional VfsFile::ReadByte(u64 offset) { + auto vec = ReadBytes(offset, 1); + if (vec.empty()) + return boost::none; + return vec[0]; +} + +std::vector VfsFile::ReadAllBytes() { + return ReadBytes(0, GetSize()); +} + +u64 VfsFile::ReplaceBytes(const std::vector& data) { + if (!Resize(data.size())) + return 0; + return WriteBytes(data, 0); +} + +boost::optional VfsDirectory::GetFile(const std::string& name) { + auto files = GetFiles(); + auto iter = std::find_if(files.begin(), files.end(), + [&name](auto file1) { return name == file1.GetName(); }); + return iter == files.end() ? boost::none : boost::make_optional(*iter); +} + +boost::optional VfsDirectory::GetSubdirectory(const std::string& name) { + auto subs = GetSubdirectories(); + auto iter = std::find_if(subs.begin(), subs.end(), + [&name](auto file1) { return name == file1.GetName(); }); + return iter == subs.end() ? boost::none : boost::make_optional(*iter); +} + +u64 VfsDirectory::GetSize() { + auto files = GetFiles(); + auto file_total = std::accumulate(files.begin(), files.end(), 0); + + auto sub_dir = GetSubdirectories(); + auto subdir_total = std::accumulate(sub_dir.begin(), sub_dir.end(), 0); + + return file_total + subdir_total; +} + +bool VfsDirectory::Copy(const std::string& src, const std::string& dest) { + auto f1 = CreateFile(src), f2 = CreateFile(dest); + if (f1 == boost::none || f2 == boost::none) + return false; + + return f2->ReplaceBytes(f1->ReadAllBytes()) == f1->GetSize(); +} + +} // namespace FileSys diff --git a/src/core/file_sys/vfs.h b/src/core/file_sys/vfs.h index 3b6eee91cf..eb4b5a81aa 100644 --- a/src/core/file_sys/vfs.h +++ b/src/core/file_sys/vfs.h @@ -4,69 +4,93 @@ #pragma once -#include "boost/optional.hpp" -#include "common/common_types.h" #include #include +#include "boost/optional.hpp" +#include "common/common_types.h" -namespace FileSys -{ - struct VfsDirectory; +namespace FileSys { +struct VfsDirectory; - struct VfsFile : NonCopyable - { - bool IsReady(); - bool IsGood(); - operator bool(); - void ResetState(); +struct VfsFile : NonCopyable { + virtual bool IsReady() = 0; + virtual bool IsGood() = 0; + virtual operator bool(); + virtual void ResetState() = 0; - std::string GetName(); - u64 GetSize(); - bool Resize(u64 new_size); - boost::optional GetContainingDirectory(); + virtual std::string GetName() = 0; + virtual u64 GetSize() = 0; + virtual bool Resize(u64 new_size) = 0; + virtual boost::optional GetContainingDirectory() = 0; - bool IsWritable(); - bool IsReadable(); + virtual bool IsWritable() = 0; + virtual bool IsReadable() = 0; - std::vector ReadBytes(u64 offset, u64 length); - template u64 ReadBytes(T* data, u64 offset, u64 length); + virtual boost::optional ReadByte(u64 offset); + virtual std::vector ReadBytes(u64 offset, u64 length) = 0; - template std::vector ReadArray(u64 offset, u64 number_elements); - template u64 ReadArray(T* data, u64 offset, u64 number_elements); + template + u64 ReadBytes(T* data, u64 offset, u64 length) { + static_assert(std::is_trivially_copyable(), + "Given array does not consist of trivially copyable objects"); + return ReadArray(reinterpret_cast(data), offset, length); + } - std::vector ReadAllBytes(); + template + std::vector ReadArray(u64 offset, u64 number_elements) { + static_assert(std::is_trivially_copyable(), + "Given array does not consist of trivially copyable objects"); - void WriteBytes(const std::vector& data, u64 offset); - void ReplaceBytes(const std::vector& data); + auto vec = ReadBytes(offset, number_elements * sizeof(T)); + std::vector out_vec(number_elements); + memcpy(out_vec.data(), vec.data(), vec.size()); + return out_vec; + } - bool Rename(const std::string& name); - }; + template + u64 ReadArray(T* data, u64 offset, u64 number_elements) { + static_assert(std::is_trivially_copyable(), + "Given array does not consist of trivially copyable objects"); - struct VfsDirectory : NonCopyable - { - std::vector GetFiles(); - boost::optional GetFile(const std::string& name); + std::vector vec = ReadArray(offset, number_elements); + for (size_t i = 0; i < vec.size(); ++i) + data[i] = vec[i]; - std::vector GetSubdirectories(); - boost::optional GetSubdirectory(const std::string& name); + return vec.size(); + } - bool IsWritable(); - bool IsReadable(); + virtual std::vector ReadAllBytes(); - bool IsRoot(); + virtual u64 WriteBytes(const std::vector& data, u64 offset) = 0; + virtual u64 ReplaceBytes(const std::vector& data); - std::string GetName(); - u64 GetSize(); - boost::optional GetParentDirectory(); + virtual bool Rename(const std::string& name) = 0; +}; - boost::optional CreateSubdirectory(const std::string& name); - boost::optional CreateFile(const std::string& name); +struct VfsDirectory : NonCopyable { + virtual std::vector GetFiles() = 0; + virtual boost::optional GetFile(const std::string& name); - bool DeleteSubdirectory(const std::string& name); - bool DeleteFile(const std::string& name); + virtual std::vector GetSubdirectories() = 0; + virtual boost::optional GetSubdirectory(const std::string& name); - bool Rename(const std::string& name); + virtual bool IsWritable() = 0; + virtual bool IsReadable() = 0; - bool Copy(const std::string& src, const std::string& dest); - }; -} + virtual bool IsRoot() = 0; + + virtual std::string GetName() = 0; + virtual u64 GetSize(); + virtual boost::optional GetParentDirectory() = 0; + + virtual boost::optional CreateSubdirectory(const std::string& name) = 0; + virtual boost::optional CreateFile(const std::string& name) = 0; + + virtual bool DeleteSubdirectory(const std::string& name) = 0; + virtual bool DeleteFile(const std::string& name) = 0; + + virtual bool Rename(const std::string& name) = 0; + + virtual bool Copy(const std::string& src, const std::string& dest); +}; +} // namespace FileSys