First
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
#pragma once
|
||||
|
||||
#include <tl/optional.h>
|
||||
#include <tl/span.h>
|
||||
#include "fs/Error.h"
|
||||
#include "fs/Api.h"
|
||||
|
||||
namespace fs
|
||||
{
|
||||
|
||||
class FS_API IStreamSink
|
||||
{
|
||||
public:
|
||||
IStreamSink() = default;
|
||||
virtual ~IStreamSink() = default;
|
||||
|
||||
IStreamSink(IStreamSink&&) = default;
|
||||
IStreamSink& operator=(IStreamSink&&) = default;
|
||||
|
||||
//This will return the last generated error AND CLEAR IT AFTERWARDS.
|
||||
virtual tl::optional<Error> getLastError() const = 0;
|
||||
|
||||
//writes size bytes from the buffer to the sink at the current cursor position.
|
||||
//the sink size is increased if the sinks reaches the end
|
||||
virtual size_t write(tl::span<const uint8_t> data) = 0;
|
||||
|
||||
//returns the size of the sink. Always >= tell
|
||||
virtual uint64_t getSize() const = 0;
|
||||
|
||||
// The preferred buffer size for writes. Use this buffer size for optimal performance
|
||||
// If zero, use whatever you want
|
||||
virtual size_t getPreferredBufferSize() const = 0;
|
||||
};
|
||||
|
||||
template<typename T, bool isEnum>
|
||||
struct StreamSinkSerializationHelperWrite_Internal;
|
||||
|
||||
template<typename T>
|
||||
struct StreamSinkSerializationHelperWrite_Internal<T, false>
|
||||
{
|
||||
static IStreamSink& write(IStreamSink& s, const T& val)
|
||||
{
|
||||
static_assert(std::is_standard_layout_v<T> && !std::is_pointer_v<T> && !std::is_array_v<T>, "You need a specialized write for T");
|
||||
s.write({ reinterpret_cast<const uint8_t*>(&val), sizeof(T) });
|
||||
return s;
|
||||
}
|
||||
|
||||
static IStreamSink& write(IStreamSink& s, tl::span<const T> val)
|
||||
{
|
||||
const uint32_t count = static_cast<uint32_t>(val.size());
|
||||
s.write({ reinterpret_cast<const uint8_t*>(&count), sizeof(count) });
|
||||
for(const T& v : val)
|
||||
s.write( { reinterpret_cast<const uint8_t*>(&v), sizeof(T) });
|
||||
return s;
|
||||
}
|
||||
};
|
||||
|
||||
// specialization to read enums
|
||||
template<typename EnumType>
|
||||
struct StreamSinkSerializationHelperWrite_Internal<EnumType, true>
|
||||
{
|
||||
static IStreamSink& write(IStreamSink& s, const EnumType& val)
|
||||
{
|
||||
// first read into the temporary of the underlying type
|
||||
using underlying_t = std::underlying_type_t<EnumType>;
|
||||
underlying_t underlyingValue = static_cast<underlying_t>(val);
|
||||
|
||||
IStreamSink& ret = StreamSinkSerializationHelperWrite_Internal<underlying_t, false>::write(s, underlyingValue);
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct SimpleStreamSerializationHelperWrite : StreamSinkSerializationHelperWrite_Internal<T, std::is_enum_v<std::remove_reference_t<T>>>
|
||||
{
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
IStreamSink& operator<<(IStreamSink& s, const T& val)
|
||||
{
|
||||
return SimpleStreamSerializationHelperWrite<T>::write(s, val);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
IStreamSink& operator<<(IStreamSink& s, tl::span<const T> val)
|
||||
{
|
||||
return SimpleStreamSerializationHelperWrite<T>::write(s, val);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user