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