2 changed files with 134 additions and 0 deletions
@ -0,0 +1,93 @@ |
|||||
|
// Copyright 2018 yuzu emulator team
|
||||
|
// Licensed under GPLv2 or any later version
|
||||
|
// Refer to the license.txt file included.
|
||||
|
|
||||
|
#include <algorithm>
|
||||
|
#include <utility>
|
||||
|
|
||||
|
#include "core/file_sys/vfs_concat.h"
|
||||
|
|
||||
|
namespace FileSys { |
||||
|
|
||||
|
VirtualFile ConcatenateFiles(std::vector<VirtualFile> files, std::string_view name) { |
||||
|
if (files.empty()) |
||||
|
return nullptr; |
||||
|
if (files.size() == 1) |
||||
|
return files[0]; |
||||
|
|
||||
|
return std::shared_ptr<VfsFile>(new ConcatenatedVfsFile(std::move(files), name)); |
||||
|
} |
||||
|
|
||||
|
ConcatenatedVfsFile::ConcatenatedVfsFile(std::vector<VirtualFile> files_, std::string_view name) |
||||
|
: name(name) { |
||||
|
size_t next_offset = 0; |
||||
|
for (const auto& file : files_) { |
||||
|
files[next_offset] = file; |
||||
|
next_offset += file->GetSize(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
std::string ConcatenatedVfsFile::GetName() const { |
||||
|
if (files.empty()) |
||||
|
return ""; |
||||
|
if (!name.empty()) |
||||
|
return name; |
||||
|
return files.begin()->second->GetName(); |
||||
|
} |
||||
|
|
||||
|
size_t ConcatenatedVfsFile::GetSize() const { |
||||
|
if (files.empty()) |
||||
|
return 0; |
||||
|
return files.rbegin()->first + files.rbegin()->second->GetSize(); |
||||
|
} |
||||
|
|
||||
|
bool ConcatenatedVfsFile::Resize(size_t new_size) { |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
std::shared_ptr<VfsDirectory> ConcatenatedVfsFile::GetContainingDirectory() const { |
||||
|
if (files.empty()) |
||||
|
return nullptr; |
||||
|
return files.begin()->second->GetContainingDirectory(); |
||||
|
} |
||||
|
|
||||
|
bool ConcatenatedVfsFile::IsWritable() const { |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
bool ConcatenatedVfsFile::IsReadable() const { |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
size_t ConcatenatedVfsFile::Read(u8* data, size_t length, size_t offset) const { |
||||
|
auto entry = files.end(); |
||||
|
for (auto iter = files.begin(); iter != files.end(); ++iter) { |
||||
|
if (iter->first > offset) { |
||||
|
entry = --iter; |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (entry == files.end() && offset < files.rbegin()->first + files.rbegin()->second->GetSize()) |
||||
|
--entry; |
||||
|
|
||||
|
if (entry == files.end()) |
||||
|
return 0; |
||||
|
|
||||
|
const auto remaining = entry->second->GetSize() + offset - entry->first; |
||||
|
if (length > remaining) { |
||||
|
return entry->second->Read(data, remaining, offset - entry->first) + |
||||
|
Read(data + remaining, length - remaining, offset + remaining); |
||||
|
} |
||||
|
|
||||
|
return entry->second->Read(data, length, offset - entry->first); |
||||
|
} |
||||
|
|
||||
|
size_t ConcatenatedVfsFile::Write(const u8* data, size_t length, size_t offset) { |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
bool ConcatenatedVfsFile::Rename(std::string_view name) { |
||||
|
return false; |
||||
|
} |
||||
|
} // namespace FileSys
|
||||
@ -0,0 +1,41 @@ |
|||||
|
// Copyright 2018 yuzu emulator team |
||||
|
// Licensed under GPLv2 or any later version |
||||
|
// Refer to the license.txt file included. |
||||
|
|
||||
|
#pragma once |
||||
|
|
||||
|
#include <memory> |
||||
|
#include <string_view> |
||||
|
#include <boost/container/flat_map.hpp> |
||||
|
#include "core/file_sys/vfs.h" |
||||
|
|
||||
|
namespace FileSys { |
||||
|
|
||||
|
// Wrapper function to allow for more efficient handling of files.size() == 0, 1 cases. |
||||
|
VirtualFile ConcatenateFiles(std::vector<VirtualFile> files, std::string_view name = ""); |
||||
|
|
||||
|
// Class that wraps multiple vfs files and concatenates them, making reads seamless. Currently |
||||
|
// read-only. |
||||
|
class ConcatenatedVfsFile : public VfsFile { |
||||
|
friend VirtualFile ConcatenateFiles(std::vector<VirtualFile> files, std::string_view name); |
||||
|
|
||||
|
ConcatenatedVfsFile(std::vector<VirtualFile> files, std::string_view name); |
||||
|
|
||||
|
public: |
||||
|
std::string GetName() const override; |
||||
|
size_t GetSize() const override; |
||||
|
bool Resize(size_t new_size) override; |
||||
|
std::shared_ptr<VfsDirectory> GetContainingDirectory() const override; |
||||
|
bool IsWritable() const override; |
||||
|
bool IsReadable() const override; |
||||
|
size_t Read(u8* data, size_t length, size_t offset) const override; |
||||
|
size_t Write(const u8* data, size_t length, size_t offset) override; |
||||
|
bool Rename(std::string_view name) override; |
||||
|
|
||||
|
private: |
||||
|
// Maps starting offset to file -- more efficient. |
||||
|
boost::container::flat_map<u64, VirtualFile> files; |
||||
|
std::string name; |
||||
|
}; |
||||
|
|
||||
|
} // namespace FileSys |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue