vfs_concat.h 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. // Copyright 2018 yuzu emulator team
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #pragma once
  5. #include <map>
  6. #include <memory>
  7. #include <string_view>
  8. #include <boost/container/flat_map.hpp>
  9. #include "core/file_sys/vfs.h"
  10. #include "core/file_sys/vfs_static.h"
  11. namespace FileSys {
  12. class ConcatenatedVfsFile;
  13. // Wrapper function to allow for more efficient handling of files.size() == 0, 1 cases.
  14. VirtualFile ConcatenateFiles(std::vector<VirtualFile> files, std::string name = "");
  15. // Convenience function that turns a map of offsets to files into a concatenated file, filling gaps
  16. // with template parameter.
  17. template <u8 filler_byte>
  18. VirtualFile ConcatenateFiles(std::map<u64, VirtualFile> files, std::string name = "") {
  19. if (files.empty())
  20. return nullptr;
  21. if (files.size() == 1)
  22. return files.begin()->second;
  23. for (auto iter = files.begin(); iter != --files.end();) {
  24. const auto old = iter++;
  25. if (old->first + old->second->GetSize() != iter->first) {
  26. files.emplace(old->first + old->second->GetSize(),
  27. std::make_shared<StaticVfsFile<filler_byte>>(iter->first - old->first -
  28. old->second->GetSize()));
  29. }
  30. }
  31. if (files.begin()->first != 0)
  32. files.emplace(0, std::make_shared<StaticVfsFile<filler_byte>>(files.begin()->first));
  33. return std::shared_ptr<VfsFile>(new ConcatenatedVfsFile(std::move(files), std::move(name)));
  34. }
  35. // Class that wraps multiple vfs files and concatenates them, making reads seamless. Currently
  36. // read-only.
  37. class ConcatenatedVfsFile : public VfsFile {
  38. friend VirtualFile ConcatenateFiles(std::vector<VirtualFile> files, std::string name);
  39. template <u8 filler_byte>
  40. friend VirtualFile ConcatenateFiles(std::map<u64, VirtualFile> files, std::string name);
  41. ConcatenatedVfsFile(std::vector<VirtualFile> files, std::string name);
  42. ConcatenatedVfsFile(std::map<u64, VirtualFile> files, std::string name);
  43. public:
  44. ~ConcatenatedVfsFile() override;
  45. std::string GetName() const override;
  46. std::size_t GetSize() const override;
  47. bool Resize(std::size_t new_size) override;
  48. std::shared_ptr<VfsDirectory> GetContainingDirectory() const override;
  49. bool IsWritable() const override;
  50. bool IsReadable() const override;
  51. std::size_t Read(u8* data, std::size_t length, std::size_t offset) const override;
  52. std::size_t Write(const u8* data, std::size_t length, std::size_t offset) override;
  53. bool Rename(std::string_view name) override;
  54. private:
  55. // Maps starting offset to file -- more efficient.
  56. std::map<u64, VirtualFile> files;
  57. std::string name;
  58. };
  59. } // namespace FileSys