ECSTASY
All in the name
Loading...
Searching...
No Matches
RawSerializer.hpp
Go to the documentation of this file.
1
11
12#ifndef ECSTASY_SERIALIZATION_RAWSERIALIZER_HPP_
13#define ECSTASY_SERIALIZATION_RAWSERIALIZER_HPP_
14
15#include <cstdint>
16#include <sstream>
17#include <vector>
18
19#include "Serializer.hpp"
21
23{
24
39 class RawSerializer : public Serializer<RawSerializer> {
40 public:
47 RawSerializer() = default;
48
57 RawSerializer(const std::string &content)
58 {
59 importBytes(content);
60 }
61
70 explicit RawSerializer(const std::filesystem::path &filename)
71 {
72 importFile(filename);
73 }
74
83 {
84 importStream(stream);
85 }
86
93 ~RawSerializer() override = default;
94
96 void clear() override final
97 {
98 _stream.str("");
99 }
100
110 void resetCursors(bool read = true, bool write = true)
111 {
112 if (read)
114 if (write)
116 }
117
125 {
126 _stream.seekg(0);
127 }
128
136 {
137 _stream.seekp(0);
138 }
139
141 [[nodiscard]] size_t size() const override final
142 {
143 return _stream.str().size();
144 }
145
147 void importStream(std::istream &stream) override final
148 {
149 clear();
150 _stream << stream.rdbuf();
151 _stream.seekp(0);
152 }
153
155 void exportStream(std::ostream &stream) const override final
156 {
157 std::stringstream &s = const_cast<std::stringstream &>(_stream);
158 std::streampos pos = s.tellg();
159
160 // Read from the begining of the stream
161 s.seekg(0);
162 stream << s.rdbuf();
163 // Replace the read cursor at the original position
164 s.seekg(pos);
165 }
166
168 // clang-format off
169 template <typename T,
170 typename = typename std::enable_if<
171 (std::is_same_v<T, std::string> || std::is_same_v<T, std::string_view>) || // String
172 std::is_bounded_array_v<T> || // Bounded array
174 std::is_same_v<T, std::type_info> // std::type_info
175 , int>::type >
176 requires(!std::is_fundamental_v<T>)
177 // clang-format on
178 RawSerializer &saveImpl(const T &object)
179 {
180 if constexpr (std::is_same_v<T, std::string> || std::is_same_v<T, std::string_view>) {
181 save(static_cast<uint32_t>(object.size()));
182 _stream << object;
183 } else if constexpr (std::is_bounded_array_v<T>) {
184 for (size_t i = 0; i < std::extent_v<T>; i++)
185 save(object[i]);
186 } else if constexpr (util::meta::is_std_vector<T>::value) {
187 *this << object.size();
188 for (const auto &elem : object)
189 *this << elem;
190 } else if constexpr (std::is_same_v<T, std::type_info>) {
191 save(rtti::TypeRegistry::getInstance().get(object).getHash());
192 } else {
193 return Parent::save(object);
194 }
195 return *this;
196 }
197
199 template <typename U>
200 requires std::is_fundamental_v<U>
202 {
203 write(reinterpret_cast<const char *>(&object), sizeof(object));
204 return *this;
205 }
206
207 // clang-format off
209 template <typename U,
210 typename = typename std::enable_if<(
211 std::is_same_v<U, std::string> || // Load
212 std::is_bounded_array_v<U> || // Bounded array
214 ,
215 int>::type>
216 // clang-format on
218 {
219 if constexpr (std::is_same_v<U, std::string>)
220 object = load<U>();
221 else if constexpr (std::is_bounded_array_v<U>)
222 for (size_t i = 0; i < std::extent_v<U>; i++)
223 update(object[i]);
224 else if constexpr (util::meta::is_std_vector<U>::value) {
225 auto size = load<decltype(object.size())>();
226 object.clear();
227 object.reserve(size);
228 for (size_t i = 0; i < size; i++) {
229 if constexpr (is_constructible<typename U::value_type>)
230 object.emplace_back(*this);
231 else
232 object.push_back(std::move(load<typename U::value_type>()));
233 }
234 } else
235 return Parent::update(object);
236 return *this;
237 }
238
240 template <typename U>
241 requires std::is_fundamental_v<U> || std::is_same_v<U, std::string>
242 [[nodiscard]] U loadImpl()
243 {
244 if constexpr (std::is_fundamental_v<U>)
245 return loadRaw<U>();
246 else if constexpr (std::is_same<U, std::string>::value) {
247 uint32_t size = loadRaw<uint32_t>();
250
251 return std::string(_stream.view().data() + pos, size);
252 }
253 }
254
269 template <typename U>
270 RawSerializer &appendRaw(const U &object)
271 {
272 write(reinterpret_cast<const char *>(&object), sizeof(object));
273 return *this;
274 }
275
285 void write(const char *bytes, size_t size)
286 {
287 _stream.write(bytes, static_cast<std::streamsize>(size));
288 }
289
302 template <typename U>
303 [[nodiscard]] U loadRaw()
304 {
306 const U *result = reinterpret_cast<const U *>(_stream.view().data() + pos);
307 _stream.seekg(pos + std::streamoff(sizeof(U)));
308 return *result;
309 }
310
319 [[nodiscard]] std::stringstream &getStream() noexcept
320 {
321 return _stream;
322 }
323
324 private:
327
329 void afterSaveEntity([[maybe_unused]] RegistryEntity &entity) override final
330 {
331 // Notify the end of the entity
332 save<std::size_t>(0);
333 }
334
337 {
338 size_t hash = loadRaw<std::size_t>();
339
340 if (hash == 0)
341 return std::nullopt;
342
343 // Will raise an exception if the serializer is not registered
345 }
346 };
347} // namespace ecstasy::serialization
348
349#endif /* !ECSTASY_SERIALIZATION_RAWSERIALIZER_HPP_ */
Entity containing a reference to the registry.
ecstasy::serialization::IEntityComponentSerializer & getSerializer() const noexcept
Get a reference to the entity component serializer for the given serializer type.
Definition AType.hpp:175
static TypeRegistry & getInstance() noexcept
Get the Instance object.
AType & get(const T &target) const
Get a reference to the AType instance matching the target.
RawSerializer(std::istream &stream)
Construct a new Raw Serializer and import the content from a stream.
OptionalEntityComponentSerializer loadComponentSerializer() override final
Load the next component serializer from the stream.
U loadImpl()
Load an object from the serializer.
void resetWriteCursor()
Reset the write cursor to the begining of the stream.
std::stringstream _stream
Internal string stream used as a buffer.
RawSerializer & updateImpl(U &object)
Update an existing object from the serializer.
RawSerializer & saveImpl(const T &object)
Save an object to the serializer.
void resetCursors(bool read=true, bool write=true)
Reset the read and write cursor to the begining of the stream.
void clear() override final
Clear the serializer content.
RawSerializer & saveImpl(U object)
Save an object to the serializer.
void write(const char *bytes, size_t size)
Append a string to the serializer.
void resetReadCursor()
Reset the read cursor to the begining of the stream.
RawSerializer(const std::string &content)
Construct a new Raw Serializer and import the content from a string.
RawSerializer & appendRaw(const U &object)
Append a type to the serializer as it is in the memory.
RawSerializer(const std::filesystem::path &filename)
Construct a new Raw Serializer and import the content from a file.
U loadRaw()
Load a raw type from the serializer.
void importStream(std::istream &stream) override final
Import data from a stream into the serializer.
size_t size() const override final
Get the size of the serializer content (in bytes).
~RawSerializer() override=default
Destroy the RawSerializer.
void exportStream(std::ostream &stream) const override final
Export the serializer content to a stream.
void afterSaveEntity(RegistryEntity &entity) override final
Optional method triggered at the end of saveEntity.
std::stringstream & getStream() noexcept
Get the string stream of the serializer.
RawSerializer()=default
Construct a new Raw Serializer instance.
void importFile(const std::filesystem::path &filename) override
Import data from a file into the serializer.
RawSerializer & update(U &object)
Update an existing object from the serializer.
RawSerializer & save(const U &object)
Save an object to the serializer.
U load()
Load an object from the serializer.
void importBytes(const std::string &content) override
Import data from a string into the serializer.
Check if a type is a std::vector.
Namespace regrouping the serialization ecstasy classes.
Definition AType.hpp:26
T rdbuf(T... args)
T seekg(T... args)
T seekp(T... args)
T str(T... args)
Check if a type is a std::vector.
T tellg(T... args)
Serialize and deserialize objects.
T write(T... args)