mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-17 08:11:51 +00:00
fs::make_stream template
This commit is contained in:
parent
3356a76c9b
commit
9e39c8cd64
100
Utilities/File.h
100
Utilities/File.h
@ -6,6 +6,7 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
namespace fs
|
namespace fs
|
||||||
{
|
{
|
||||||
@ -469,4 +470,103 @@ namespace fs
|
|||||||
|
|
||||||
// Error code returned
|
// Error code returned
|
||||||
extern thread_local error g_tls_error;
|
extern thread_local error g_tls_error;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct container_stream final : file_base
|
||||||
|
{
|
||||||
|
// T can be a reference, but this is not recommended
|
||||||
|
using value_type = typename std::remove_reference_t<T>::value_type;
|
||||||
|
|
||||||
|
T obj;
|
||||||
|
u64 pos;
|
||||||
|
|
||||||
|
container_stream(T&& obj)
|
||||||
|
: obj(std::forward<T>(obj))
|
||||||
|
, pos(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~container_stream() override
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
stat_t stat() override
|
||||||
|
{
|
||||||
|
fmt::raw_error("fs::container_stream<>::stat(): not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool trunc(u64 length) override
|
||||||
|
{
|
||||||
|
obj.resize(length);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 read(void* buffer, u64 size) override
|
||||||
|
{
|
||||||
|
const u64 end = obj.size();
|
||||||
|
|
||||||
|
if (pos < end)
|
||||||
|
{
|
||||||
|
// Get readable size
|
||||||
|
if (const u64 max = std::min<u64>(size, end - pos))
|
||||||
|
{
|
||||||
|
std::copy(obj.cbegin() + pos, obj.cbegin() + pos + max, static_cast<value_type*>(buffer));
|
||||||
|
pos = pos + max;
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 write(const void* buffer, u64 size) override
|
||||||
|
{
|
||||||
|
const u64 old_size = obj.size();
|
||||||
|
|
||||||
|
if (old_size + size < old_size)
|
||||||
|
{
|
||||||
|
fmt::raw_error("fs::container_stream<>::write(): overflow");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pos > old_size)
|
||||||
|
{
|
||||||
|
// Fill gap if necessary (default-initialized)
|
||||||
|
obj.resize(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto src = static_cast<const value_type*>(buffer);
|
||||||
|
|
||||||
|
// Overwrite existing part
|
||||||
|
const u64 overlap = std::min<u64>(obj.size() - pos, size);
|
||||||
|
std::copy(src, src + overlap, obj.begin() + pos);
|
||||||
|
|
||||||
|
// Append new data
|
||||||
|
obj.insert(obj.end(), src + overlap, src + size);
|
||||||
|
pos += size;
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 seek(s64 offset, seek_mode whence) override
|
||||||
|
{
|
||||||
|
return
|
||||||
|
whence == fs::seek_set ? pos = offset :
|
||||||
|
whence == fs::seek_cur ? pos = offset + pos :
|
||||||
|
whence == fs::seek_end ? pos = offset + size() :
|
||||||
|
(fmt::raw_error("fs::container_stream<>::seek(): invalid whence"), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 size() override
|
||||||
|
{
|
||||||
|
return obj.size();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
file make_stream(T&& container = T{})
|
||||||
|
{
|
||||||
|
file result;
|
||||||
|
result.reset(std::make_unique<container_stream<T>>(std::forward<T>(container)));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user