Plasma Engine  2.0
Loading...
Searching...
No Matches
Stream_inl.h
1#pragma once
2
3#if PL_ENABLED(PL_PLATFORM_BIG_ENDIAN)
4
5template <typename T>
7{
8 static_assert(sizeof(T) == sizeof(plUInt16));
9
10 plUInt16 uiTemp;
11
12 const plUInt32 uiRead = ReadBytes(reinterpret_cast<plUInt8*>(&uiTemp), sizeof(T));
13
14 *reinterpret_cast<plUInt16*>(pWordValue) = plEndianHelper::Switch(uiTemp);
15
16 return (uiRead == sizeof(T)) ? PL_SUCCESS : PL_FAILURE;
17}
18
19template <typename T>
21{
22 static_assert(sizeof(T) == sizeof(plUInt32));
23
24 plUInt32 uiTemp;
25
26 const plUInt32 uiRead = ReadBytes(reinterpret_cast<plUInt8*>(&uiTemp), sizeof(T));
27
28 *reinterpret_cast<plUInt32*>(pDWordValue) = plEndianHelper::Switch(uiTemp);
29
30 return (uiRead == sizeof(T)) ? PL_SUCCESS : PL_FAILURE;
31}
32
33template <typename T>
35{
36 static_assert(sizeof(T) == sizeof(plUInt64));
37
38 plUInt64 uiTemp;
39
40 const plUInt32 uiRead = ReadBytes(reinterpret_cast<plUInt8*>(&uiTemp), sizeof(T));
41
42 *reinterpret_cast<plUInt64*>(pQWordValue) = plEndianHelper::Switch(uiTemp);
43
44 return (uiRead == sizeof(T)) ? PL_SUCCESS : PL_FAILURE;
45}
46
47
48
49template <typename T>
51{
52 static_assert(sizeof(T) == sizeof(plUInt16));
53
54 plUInt16 uiTemp = *reinterpret_cast<const plUInt16*>(pWordValue);
55 uiTemp = plEndianHelper::Switch(uiTemp);
56
57 return WriteBytes(reinterpret_cast<plUInt8*>(&uiTemp), sizeof(T));
58}
59
60template <typename T>
61plResult plStreamWriter::WriteDWordValue(const T* pDWordValue)
62{
63 static_assert(sizeof(T) == sizeof(plUInt32));
64
65 plUInt32 uiTemp = *reinterpret_cast<const plUInt32*>(pDWordValue);
66 uiTemp = plEndianHelper::Switch(uiTemp);
67
68 return WriteBytes(reinterpret_cast<plUInt8*>(&uiTemp), sizeof(T));
69}
70
71template <typename T>
72plResult plStreamWriter::WriteQWordValue(const T* pQWordValue)
73{
74 static_assert(sizeof(T) == sizeof(plUInt64));
75
76 plUInt64 uiTemp = *reinterpret_cast<const plUInt64*>(pQWordValue);
77 uiTemp = plEndianHelper::Switch(uiTemp);
78
79 return WriteBytes(reinterpret_cast<plUInt8*>(&uiTemp), sizeof(T));
80}
81
82#else
83
84template <typename T>
86{
87 static_assert(sizeof(T) == sizeof(plUInt16));
88
89 if (ReadBytes(reinterpret_cast<plUInt8*>(pWordValue), sizeof(T)) != sizeof(T))
90 return PL_FAILURE;
91
92 return PL_SUCCESS;
93}
94
95template <typename T>
97{
98 static_assert(sizeof(T) == sizeof(plUInt32));
99
100 if (ReadBytes(reinterpret_cast<plUInt8*>(pDWordValue), sizeof(T)) != sizeof(T))
101 return PL_FAILURE;
102
103 return PL_SUCCESS;
104}
105
106template <typename T>
108{
109 static_assert(sizeof(T) == sizeof(plUInt64));
110
111 if (ReadBytes(reinterpret_cast<plUInt8*>(pQWordValue), sizeof(T)) != sizeof(T))
112 return PL_FAILURE;
113
114 return PL_SUCCESS;
115}
116
117template <typename T>
119{
120 static_assert(sizeof(T) == sizeof(plUInt16));
121
122 return WriteBytes(reinterpret_cast<const plUInt8*>(pWordValue), sizeof(T));
123}
124
125template <typename T>
127{
128 static_assert(sizeof(T) == sizeof(plUInt32));
129
130 return WriteBytes(reinterpret_cast<const plUInt8*>(pDWordValue), sizeof(T));
131}
132
133template <typename T>
135{
136 static_assert(sizeof(T) == sizeof(plUInt64));
137
138 return WriteBytes(reinterpret_cast<const plUInt8*>(pQWordValue), sizeof(T));
139}
140
141#endif
142
143plTypeVersion plStreamReader::ReadVersion(plTypeVersion expectedMaxVersion)
144{
145 plTypeVersion v = 0;
147
148 PL_ASSERT_ALWAYS(v <= expectedMaxVersion, "Read version ({0}) is larger than expected max version ({1}).", v, expectedMaxVersion);
149 PL_ASSERT_ALWAYS(v > 0, "Invalid version.");
150
151 return v;
152}
153
154void plStreamWriter::WriteVersion(plTypeVersion version)
155{
156 PL_ASSERT_ALWAYS(version > 0, "Version cannot be zero.");
157
158 WriteWordValue(&version).IgnoreResult();
159}
160
161
162namespace plStreamWriterUtil
163{
164 // single element serialization
165
166 template <class T>
167 PL_ALWAYS_INLINE auto SerializeImpl(plStreamWriter& inout_stream, const T& obj, int) -> decltype(inout_stream << obj, plResult(PL_SUCCESS))
168 {
169 inout_stream << obj;
170
171 return PL_SUCCESS;
172 }
173
174 template <class T>
175 PL_ALWAYS_INLINE auto SerializeImpl(plStreamWriter& inout_stream, const T& obj, long) -> decltype(obj.Serialize(inout_stream).IgnoreResult(), plResult(PL_SUCCESS))
176 {
177 return plToResult(obj.Serialize(inout_stream));
178 }
179
180 template <class T>
181 PL_ALWAYS_INLINE auto SerializeImpl(plStreamWriter& inout_stream, const T& obj, float) -> decltype(obj.serialize(inout_stream).IgnoreResult(), plResult(PL_SUCCESS))
182 {
183 return plToResult(obj.serialize(inout_stream));
184 }
185
186 template <class T>
187 PL_ALWAYS_INLINE auto Serialize(plStreamWriter& inout_stream, const T& obj) -> decltype(SerializeImpl(inout_stream, obj, 0).IgnoreResult(), plResult(PL_SUCCESS))
188 {
189 return SerializeImpl(inout_stream, obj, 0);
190 }
191
192 // serialization of array
193
194#if PL_DISABLED(PL_PLATFORM_WINDOWS_UWP)
195 template <class T>
196 PL_ALWAYS_INLINE auto SerializeArrayImpl(plStreamWriter& inout_stream, const T* pArray, plUInt64 uiCount, int) -> decltype(SerializeArray(inout_stream, pArray, uiCount), plResult(PL_SUCCESS))
197 {
198 return SerializeArray(inout_stream, pArray, uiCount);
199 }
200#endif
201
202 template <class T>
203 plResult SerializeArrayImpl(plStreamWriter& inout_stream, const T* pArray, plUInt64 uiCount, long)
204 {
205 for (plUInt64 i = 0; i < uiCount; ++i)
206 {
207 PL_SUCCEED_OR_RETURN(plStreamWriterUtil::Serialize<T>(inout_stream, pArray[i]));
208 }
209
210 return PL_SUCCESS;
211 }
212
213 template <class T>
214 PL_ALWAYS_INLINE plResult SerializeArray(plStreamWriter& inout_stream, const T* pArray, plUInt64 uiCount)
215 {
216 return SerializeArrayImpl(inout_stream, pArray, uiCount, 0);
217 }
218} // namespace plStreamWriterUtil
219
220template <typename ArrayType, typename ValueType>
222{
223 const plUInt64 uiCount = array.GetCount();
224 PL_SUCCEED_OR_RETURN(WriteQWordValue(&uiCount));
225
226 return plStreamWriterUtil::SerializeArray<ValueType>(*this, array.GetData(), array.GetCount());
227}
228
229template <typename ValueType, plUInt16 uiSize>
231{
232 const plUInt32 uiCount = array.GetCount();
233 PL_SUCCEED_OR_RETURN(WriteDWordValue(&uiCount));
234
235 return plStreamWriterUtil::SerializeArray<ValueType>(*this, array.GetData(), array.GetCount());
236}
237
238template <typename ValueType, plUInt32 uiSize>
239plResult plStreamWriter::WriteArray(const ValueType (&array)[uiSize])
240{
241 const plUInt64 uiWriteSize = uiSize;
242 PL_SUCCEED_OR_RETURN(WriteQWordValue(&uiWriteSize));
243
244 return plStreamWriterUtil::SerializeArray<ValueType>(*this, array, uiSize);
245}
246
247template <typename KeyType, typename Comparer>
249{
250 const plUInt64 uiWriteSize = set.GetCount();
251 PL_SUCCEED_OR_RETURN(WriteQWordValue(&uiWriteSize));
252
253 for (const auto& item : set)
254 {
255 PL_SUCCEED_OR_RETURN(plStreamWriterUtil::Serialize<KeyType>(*this, item));
256 }
257
258 return PL_SUCCESS;
259}
260
261template <typename KeyType, typename ValueType, typename Comparer>
263{
264 const plUInt64 uiWriteSize = map.GetCount();
265 PL_SUCCEED_OR_RETURN(WriteQWordValue(&uiWriteSize));
266
267 for (auto It = map.GetIterator(); It.IsValid(); ++It)
268 {
269 PL_SUCCEED_OR_RETURN(plStreamWriterUtil::Serialize<KeyType>(*this, It.Key()));
270 PL_SUCCEED_OR_RETURN(plStreamWriterUtil::Serialize<ValueType>(*this, It.Value()));
271 }
272
273 return PL_SUCCESS;
274}
275
276template <typename KeyType, typename ValueType, typename Hasher>
278{
279 const plUInt64 uiWriteSize = hashTable.GetCount();
280 PL_SUCCEED_OR_RETURN(WriteQWordValue(&uiWriteSize));
281
282 for (auto It = hashTable.GetIterator(); It.IsValid(); ++It)
283 {
284 PL_SUCCEED_OR_RETURN(plStreamWriterUtil::Serialize<KeyType>(*this, It.Key()));
285 PL_SUCCEED_OR_RETURN(plStreamWriterUtil::Serialize<ValueType>(*this, It.Value()));
286 }
287
288 return PL_SUCCESS;
289}
290
291namespace plStreamReaderUtil
292{
293 template <class T>
294 PL_ALWAYS_INLINE auto DeserializeImpl(plStreamReader& inout_stream, T& ref_obj, int) -> decltype(inout_stream >> ref_obj, plResult(PL_SUCCESS))
295 {
296 inout_stream >> ref_obj;
297
298 return PL_SUCCESS;
299 }
300
301 template <class T>
302 PL_ALWAYS_INLINE auto DeserializeImpl(plStreamReader& inout_stream, T& inout_obj, long) -> decltype(inout_obj.Deserialize(inout_stream).IgnoreResult(), plResult(PL_SUCCESS))
303 {
304 return plToResult(inout_obj.Deserialize(inout_stream));
305 }
306
307 template <class T>
308 PL_ALWAYS_INLINE auto DeserializeImpl(plStreamReader& inout_stream, T& inout_obj, float) -> decltype(inout_obj.deserialize(inout_stream).IgnoreResult(), plResult(PL_SUCCESS))
309 {
310 return plToResult(inout_obj.deserialize(inout_stream));
311 }
312
313 template <class T>
314 PL_ALWAYS_INLINE auto Deserialize(plStreamReader& inout_stream, T& inout_obj) -> decltype(DeserializeImpl(inout_stream, inout_obj, 0).IgnoreResult(), plResult(PL_SUCCESS))
315 {
316 return DeserializeImpl(inout_stream, inout_obj, 0);
317 }
318
319 // serialization of array
320
321#if PL_DISABLED(PL_PLATFORM_WINDOWS_UWP)
322 template <class T>
323 PL_ALWAYS_INLINE auto DeserializeArrayImpl(plStreamReader& inout_stream, T* pArray, plUInt64 uiCount, int) -> decltype(DeserializeArray(inout_stream, pArray, uiCount), plResult(PL_SUCCESS))
324 {
325 return DeserializeArray(inout_stream, pArray, uiCount);
326 }
327#endif
328
329 template <class T>
330 plResult DeserializeArrayImpl(plStreamReader& inout_stream, T* pArray, plUInt64 uiCount, long)
331 {
332 for (plUInt64 i = 0; i < uiCount; ++i)
333 {
334 PL_SUCCEED_OR_RETURN(plStreamReaderUtil::Deserialize<T>(inout_stream, pArray[i]));
335 }
336
337 return PL_SUCCESS;
338 }
339
340 template <class T>
341 PL_ALWAYS_INLINE plResult DeserializeArray(plStreamReader& inout_stream, T* pArray, plUInt64 uiCount)
342 {
343 return DeserializeArrayImpl(inout_stream, pArray, uiCount, 0);
344 }
345
346} // namespace plStreamReaderUtil
347
348template <typename ArrayType, typename ValueType>
350{
351 plUInt64 uiCount = 0;
352 PL_SUCCEED_OR_RETURN(ReadQWordValue(&uiCount));
353
354 if (uiCount < plMath::MaxValue<plUInt32>())
355 {
356 inout_array.Clear();
357
358 if (uiCount > 0)
359 {
360 static_cast<ArrayType&>(inout_array).SetCount(static_cast<plUInt32>(uiCount));
361
362 PL_SUCCEED_OR_RETURN(plStreamReaderUtil::DeserializeArray<ValueType>(*this, inout_array.GetData(), uiCount));
363 }
364
365 return PL_SUCCESS;
366 }
367 else
368 {
369 // Containers currently use 32 bit for counts internally. Value from file is too large.
370 return PL_FAILURE;
371 }
372}
373
374template <typename ValueType, plUInt16 uiSize, typename AllocatorWrapper>
376{
377 plUInt32 uiCount = 0;
378 PL_SUCCEED_OR_RETURN(ReadDWordValue(&uiCount));
379
380 if (uiCount < plMath::MaxValue<plUInt16>())
381 {
382 ref_array.Clear();
383
384 if (uiCount > 0)
385 {
386 ref_array.SetCount(static_cast<plUInt16>(uiCount));
387
388 PL_SUCCEED_OR_RETURN(plStreamReaderUtil::DeserializeArray<ValueType>(*this, ref_array.GetData(), uiCount));
389 }
390
391 return PL_SUCCESS;
392 }
393 else
394 {
395 // Small array uses 16 bit for counts internally. Value from file is too large.
396 return PL_FAILURE;
397 }
398}
399
400template <typename ValueType, plUInt32 uiSize>
401plResult plStreamReader::ReadArray(ValueType (&array)[uiSize])
402{
403 plUInt64 uiCount = 0;
404 PL_SUCCEED_OR_RETURN(ReadQWordValue(&uiCount));
405
406 if (static_cast<plUInt32>(uiCount) != uiSize)
407 return PL_FAILURE;
408
409 if (uiCount < plMath::MaxValue<plUInt32>())
410 {
411 PL_SUCCEED_OR_RETURN(plStreamReaderUtil::DeserializeArray<ValueType>(*this, array, uiCount));
412
413 return PL_SUCCESS;
414 }
415
416 // Containers currently use 32 bit for counts internally. Value from file is too large.
417 return PL_FAILURE;
418}
419
420template <typename KeyType, typename Comparer>
422{
423 plUInt64 uiCount = 0;
424 PL_SUCCEED_OR_RETURN(ReadQWordValue(&uiCount));
425
426 if (uiCount < plMath::MaxValue<plUInt32>())
427 {
428 inout_set.Clear();
429
430 for (plUInt32 i = 0; i < static_cast<plUInt32>(uiCount); ++i)
431 {
432 KeyType Item;
433 PL_SUCCEED_OR_RETURN(plStreamReaderUtil::Deserialize(*this, Item));
434
435 inout_set.Insert(std::move(Item));
436 }
437
438 return PL_SUCCESS;
439 }
440 else
441 {
442 // Containers currently use 32 bit for counts internally. Value from file is too large.
443 return PL_FAILURE;
444 }
445}
446
447template <typename KeyType, typename ValueType, typename Comparer>
449{
450 plUInt64 uiCount = 0;
451 PL_SUCCEED_OR_RETURN(ReadQWordValue(&uiCount));
452
453 if (uiCount < plMath::MaxValue<plUInt32>())
454 {
455 inout_map.Clear();
456
457 for (plUInt32 i = 0; i < static_cast<plUInt32>(uiCount); ++i)
458 {
459 KeyType Key;
460 ValueType Value;
461 PL_SUCCEED_OR_RETURN(plStreamReaderUtil::Deserialize(*this, Key));
462 PL_SUCCEED_OR_RETURN(plStreamReaderUtil::Deserialize(*this, Value));
463
464 inout_map.Insert(std::move(Key), std::move(Value));
465 }
466
467 return PL_SUCCESS;
468 }
469 else
470 {
471 // Containers currently use 32 bit for counts internally. Value from file is too large.
472 return PL_FAILURE;
473 }
474}
475
476template <typename KeyType, typename ValueType, typename Hasher>
478{
479 plUInt64 uiCount = 0;
480 PL_SUCCEED_OR_RETURN(ReadQWordValue(&uiCount));
481
482 if (uiCount < plMath::MaxValue<plUInt32>())
483 {
484 inout_hashTable.Clear();
485 inout_hashTable.Reserve(static_cast<plUInt32>(uiCount));
486
487 for (plUInt32 i = 0; i < static_cast<plUInt32>(uiCount); ++i)
488 {
489 KeyType Key;
490 ValueType Value;
491 PL_SUCCEED_OR_RETURN(plStreamReaderUtil::Deserialize(*this, Key));
492 PL_SUCCEED_OR_RETURN(plStreamReaderUtil::Deserialize(*this, Value));
493
494 inout_hashTable.Insert(std::move(Key), std::move(Value));
495 }
496
497 return PL_SUCCESS;
498 }
499 else
500 {
501 // Containers currently use 32 bit for counts internally. Value from file is too large.
502 return PL_FAILURE;
503 }
504}
Base class for all array containers. Implements all the basic functionality that only requires a poin...
Definition ArrayBase.h:19
T * GetData()
Returns a pointer to the array data, or nullptr if the array is empty.
Definition ArrayBase_inl.h:423
void Clear()
Clears the array.
Definition ArrayBase_inl.h:184
plUInt32 GetCount() const
Returns the number of active elements in the array.
Definition ArrayBase_inl.h:172
Implementation of a hashtable which stores key/value pairs.
Definition HashTable.h:157
Iterator GetIterator()
Returns an Iterator to the very first element.
Definition HashTable_inl.h:625
plUInt32 GetCount() const
Returns the number of active entries in the table.
Definition HashTable_inl.h:343
bool Insert(CompatibleKeyType &&key, CompatibleValueType &&value, ValueType *out_pOldValue=nullptr)
Inserts the key value pair or replaces value if an entry with the given key already exists.
void Clear()
Clears the table.
Definition HashTable_inl.h:355
void Reserve(plUInt32 uiCapacity)
Expands the hashtable by over-allocating the internal storage so that the load factor is lower or equ...
Definition HashTable_inl.h:307
An associative container. Similar to STL::map.
Definition Map.h:193
void Clear()
Destroys all elements in the map and resets its size to zero.
Definition Map_inl.h:175
Iterator Insert(CompatibleKeyType &&key, CompatibleValueType &&value)
Inserts the key/value pair into the tree and returns an Iterator to it. O(log n) operation.
Definition Map_inl.h:535
plUInt32 GetCount() const
Returns the number of elements currently stored in the map. O(1) operation.
Definition Map_inl.h:200
Iterator GetIterator()
Returns an Iterator to the very first element.
Definition Map_inl.h:207
A set container that only stores whether an element resides in it or not. Similar to STL::set.
Definition Set.h:13
void Clear()
Destroys all elements in the set and resets its size to zero.
Definition Set_inl.h:133
Iterator Insert(CompatibleKeyType &&key)
Inserts the key into the tree and returns an Iterator to it. O(log n) operation.
Definition Set_inl.h:351
plUInt32 GetCount() const
Returns the number of elements currently stored in the set. O(1) operation.
Definition Set_inl.h:158
Implementation of a dynamically growing array with in-place storage and small memory overhead.
Definition SmallArray.h:17
void Clear()
Clears the array.
Definition SmallArray_inl.h:222
T * GetData()
Returns a pointer to the array data, or nullptr if the array is empty.
Definition SmallArray_inl.h:444
plUInt32 GetCount() const
Returns the number of active elements in the array.
Definition SmallArray_inl.h:210
Definition SmallArray.h:219
Interface for binary in (read) streams.
Definition Stream.h:22
plResult ReadArray(plArrayBase< ValueType, ArrayType > &inout_array)
Reads an array of elements from the stream.
Definition Stream_inl.h:349
plResult ReadWordValue(T *pWordValue)
Helper method to read a word value correctly (copes with potentially different endianess)
Definition Stream_inl.h:85
plResult ReadHashTable(plHashTableBase< KeyType, ValueType, Hasher > &inout_hashTable)
Read a hash table (note that the entry order is not stable)
Definition Stream_inl.h:477
plResult ReadQWordValue(T *pQWordValue)
Helper method to read a qword value correctly (copes with potentially different endianess)
Definition Stream_inl.h:107
plResult ReadMap(plMapBase< KeyType, ValueType, Comparer > &inout_map)
Reads a map.
Definition Stream_inl.h:448
plResult ReadSet(plSetBase< KeyType, Comparer > &inout_set)
Reads a set.
Definition Stream_inl.h:421
plResult ReadDWordValue(T *pDWordValue)
Helper method to read a dword value correctly (copes with potentially different endianess)
Definition Stream_inl.h:96
virtual plUInt64 ReadBytes(void *pReadBuffer, plUInt64 uiBytesToRead)=0
Reads a raw number of bytes into the read buffer, this is the only method which has to be implemented...
Interface for binary out (write) streams.
Definition Stream.h:107
plResult WriteSet(const plSetBase< KeyType, Comparer > &set)
Writes a set.
Definition Stream_inl.h:248
virtual plResult WriteBytes(const void *pWriteBuffer, plUInt64 uiBytesToWrite)=0
Writes a raw number of bytes from the buffer, this is the only method which has to be implemented to ...
plResult WriteDWordValue(const T *pDWordValue)
Helper method to write a dword value correctly (copes with potentially different endianess)
Definition Stream_inl.h:126
plResult WriteArray(const plArrayBase< ValueType, ArrayType > &array)
Writes an array of elements to the stream.
Definition Stream_inl.h:221
PL_ALWAYS_INLINE void WriteVersion(plTypeVersion version)
Writes a type version to the stream.
Definition Stream_inl.h:154
plResult WriteMap(const plMapBase< KeyType, ValueType, Comparer > &map)
Writes a map.
Definition Stream_inl.h:262
plResult WriteWordValue(const T *pWordValue)
Helper method to write a word value correctly (copes with potentially different endianess)
Definition Stream_inl.h:118
plResult WriteHashTable(const plHashTableBase< KeyType, ValueType, Hasher > &hashTable)
Writes a hash table (note that the entry order might change on read)
Definition Stream_inl.h:277
plResult WriteQWordValue(const T *pQWordValue)
Helper method to write a qword value correctly (copes with potentially different endianess)
Definition Stream_inl.h:134
constexpr TYPE MaxValue()
Returns the largest possible positive value (that is not infinity).
static PL_ALWAYS_INLINE plUInt16 Switch(plUInt16 uiWord)
Returns a single switched word (16 bit value).
Definition EndianHelper.h:45
Default enum for returning failure or success, instead of using a bool.
Definition Types.h:54
PL_ALWAYS_INLINE void IgnoreResult()
Used to silence compiler warnings, when success or failure doesn't matter.
Definition Types.h:69