blob: 6447bb925258f9c35f3609726d8b0b52e73947db [file] [log] [blame] [edit]
/*
* Copyright 2025 Rive
*/
#pragma once
#include "rive/refcnt.hpp"
#include <cassert>
#include <deque>
namespace rive
{
// Stream for recording objects of a specific type, using C++-style "<<" ">>"
// operators.
template <typename T> class ObjectStream
{
public:
bool empty() const { return m_stream.empty(); }
ObjectStream& operator<<(T obj)
{
m_stream.push_back(std::move(obj));
return *this;
}
ObjectStream& operator>>(T& dst)
{
assert(!empty());
dst = std::move(m_stream.front());
m_stream.pop_front();
return *this;
}
private:
std::deque<T> m_stream;
};
// Stream for recording objects of any trivially-copyable type, using C++-style
// "<<" ">>" operators. Object types must be read back in the same order they
// were writen.
class PODStream
{
public:
bool empty() const { return m_byteStream.empty(); }
template <typename T> PODStream& operator<<(T obj)
{
static_assert(std::is_pod<T>(),
"PODStream only accepts plain-old-data types");
const char* data = reinterpret_cast<const char*>(&obj);
m_byteStream.insert(m_byteStream.end(), data, data + sizeof(T));
return *this;
}
template <typename T> PODStream& operator>>(T& dst)
{
static_assert(std::is_pod<T>(),
"PODStream only accepts plain-old-data types");
assert(m_byteStream.size() >= sizeof(T));
char* data = reinterpret_cast<char*>(&dst);
std::copy(m_byteStream.begin(), m_byteStream.begin() + sizeof(T), data);
m_byteStream.erase(m_byteStream.begin(),
m_byteStream.begin() + sizeof(T));
return *this;
}
template <typename T> PODStream& operator<<(rcp<T> obj)
{
return *this << obj.release();
}
template <typename T> PODStream& operator>>(rcp<T>& obj)
{
T* raw;
*this >> raw;
obj = rcp<T>(raw);
return *this;
}
private:
std::deque<char> m_byteStream;
};
}; // namespace rive