ezEngine  Milestone 9
Stream_inl.h
1 #pragma once
2 
3 #if EZ_ENABLED(EZ_PLATFORM_BIG_ENDIAN)
4 
5 template <typename T>
7 {
8  EZ_CHECK_AT_COMPILETIME(sizeof(T) == sizeof(ezUInt16));
9 
10  ezUInt16 uiTemp;
11 
12  const ezUInt32 uiRead = ReadBytes(reinterpret_cast<ezUInt8*>(&uiTemp), sizeof(T));
13 
14  *reinterpret_cast<ezUInt16*>(pWordValue) = ezEndianHelper::Switch(uiTemp);
15 
16  return (uiRead == sizeof(T)) ? EZ_SUCCESS : EZ_FAILURE;
17 }
18 
19 template <typename T>
21 {
22  EZ_CHECK_AT_COMPILETIME(sizeof(T) == sizeof(ezUInt32));
23 
24  ezUInt32 uiTemp;
25 
26  const ezUInt32 uiRead = ReadBytes(reinterpret_cast<ezUInt8*>(&uiTemp), sizeof(T));
27 
28  *reinterpret_cast<ezUInt32*>(pDWordValue) = ezEndianHelper::Switch(uiTemp);
29 
30  return (uiRead == sizeof(T)) ? EZ_SUCCESS : EZ_FAILURE;
31 }
32 
33 template <typename T>
35 {
36  EZ_CHECK_AT_COMPILETIME(sizeof(T) == sizeof(ezUInt64));
37 
38  ezUInt64 uiTemp;
39 
40  const ezUInt32 uiRead = ReadBytes(reinterpret_cast<ezUInt8*>(&uiTemp), sizeof(T));
41 
42  *reinterpret_cast<ezUInt64*>(pQWordValue) = ezEndianHelper::Switch(uiTemp);
43 
44  return (uiRead == sizeof(T)) ? EZ_SUCCESS : EZ_FAILURE;
45 }
46 
47 
48 
49 template <typename T>
50 ezResult ezStreamWriter::WriteWordValue(const T* pWordValue)
51 {
52  EZ_CHECK_AT_COMPILETIME(sizeof(T) == sizeof(ezUInt16));
53 
54  ezUInt16 uiTemp = *reinterpret_cast<const ezUInt16*>(pWordValue);
55  uiTemp = ezEndianHelper::Switch(uiTemp);
56 
57  return WriteBytes(reinterpret_cast<ezUInt8*>(&uiTemp), sizeof(T));
58 }
59 
60 template <typename T>
61 ezResult ezStreamWriter::WriteDWordValue(const T* pDWordValue)
62 {
63  EZ_CHECK_AT_COMPILETIME(sizeof(T) == sizeof(ezUInt32));
64 
65  ezUInt32 uiTemp = *reinterpret_cast<const ezUInt16*>(pDWordValue);
66  uiTemp = ezEndianHelper::Switch(uiTemp);
67 
68  return WriteBytes(reinterpret_cast<ezUInt8*>(&uiTemp), sizeof(T));
69 }
70 
71 template <typename T>
72 ezResult ezStreamWriter::WriteQWordValue(const T* pQWordValue)
73 {
74  EZ_CHECK_AT_COMPILETIME(sizeof(T) == sizeof(ezUInt64));
75 
76  ezUInt64 uiTemp = *reinterpret_cast<const ezUInt64*>(pQWordValue);
77  uiTemp = ezEndianHelper::Switch(uiTemp);
78 
79  return WriteBytes(reinterpret_cast<ezUInt8*>(&uiTemp), sizeof(T));
80 }
81 
82 #else
83 
84 template <typename T>
86 {
87  EZ_CHECK_AT_COMPILETIME(sizeof(T) == sizeof(ezUInt16));
88 
89  if (ReadBytes(reinterpret_cast<ezUInt8*>(pWordValue), sizeof(T)) != sizeof(T))
90  return EZ_FAILURE;
91 
92  return EZ_SUCCESS;
93 }
94 
95 template <typename T>
97 {
98  EZ_CHECK_AT_COMPILETIME(sizeof(T) == sizeof(ezUInt32));
99 
100  if (ReadBytes(reinterpret_cast<ezUInt8*>(pDWordValue), sizeof(T)) != sizeof(T))
101  return EZ_FAILURE;
102 
103  return EZ_SUCCESS;
104 }
105 
106 template <typename T>
108 {
109  EZ_CHECK_AT_COMPILETIME(sizeof(T) == sizeof(ezUInt64));
110 
111  if (ReadBytes(reinterpret_cast<ezUInt8*>(pQWordValue), sizeof(T)) != sizeof(T))
112  return EZ_FAILURE;
113 
114  return EZ_SUCCESS;
115 }
116 
117 template <typename T>
119 {
120  EZ_CHECK_AT_COMPILETIME(sizeof(T) == sizeof(ezUInt16));
121 
122  return WriteBytes(reinterpret_cast<const ezUInt8*>(pWordValue), sizeof(T));
123 }
124 
125 template <typename T>
127 {
128  EZ_CHECK_AT_COMPILETIME(sizeof(T) == sizeof(ezUInt32));
129 
130  return WriteBytes(reinterpret_cast<const ezUInt8*>(pDWordValue), sizeof(T));
131 }
132 
133 template <typename T>
135 {
136  EZ_CHECK_AT_COMPILETIME(sizeof(T) == sizeof(ezUInt64));
137 
138  return WriteBytes(reinterpret_cast<const ezUInt8*>(pQWordValue), sizeof(T));
139 }
140 
141 #endif
142 
143 ezTypeVersion ezStreamReader::ReadVersion(ezTypeVersion uiExpectedMaxVersion)
144 {
145  ezTypeVersion v;
146  ReadWordValue(&v);
147 
148  EZ_ASSERT_ALWAYS(v <= uiExpectedMaxVersion, "Read version ({0}) is larger than expected max version ({1}).", v, uiExpectedMaxVersion);
149 
150  return v;
151 }
152 
153 void ezStreamWriter::WriteVersion(ezTypeVersion uiVersion)
154 {
155  WriteWordValue(&uiVersion);
156 }
157 
158 
159 namespace ezStreamWriterUtil
160 {
161  template <class T>
162  auto SerializeImpl(ezStreamWriter& Stream, const T& Obj, int) -> decltype(Stream << Obj, ezResult(EZ_SUCCESS))
163  {
164  Stream << Obj;
165 
166  return EZ_SUCCESS;
167  }
168 
169  template <class T>
170  auto SerializeImpl(ezStreamWriter& Stream, const T& Obj, long) -> decltype(Obj.Serialize(Stream), ezResult(EZ_SUCCESS))
171  {
172  return ezToResult(Obj.Serialize(Stream));
173  }
174 
175  template <class T>
176  auto SerializeImpl(ezStreamWriter& Stream, const T& Obj, float) -> decltype(Obj.serialize(Stream), ezResult(EZ_SUCCESS))
177  {
178  return ezToResult(Obj.serialize(Stream));
179  }
180 
181  template <class T>
182  auto Serialize(ezStreamWriter& Stream, const T& Obj) -> decltype(SerializeImpl(Stream, Obj, 0), ezResult(EZ_SUCCESS))
183  {
184  return SerializeImpl(Stream, Obj, 0);
185  }
186 } // namespace ezStreamWriterUtil
187 
188 template <typename ArrayType, typename ValueType>
190 {
191  const ezUInt64 uiCount = Array.GetCount();
192  WriteQWordValue(&uiCount);
193 
194  for (ezUInt32 i = 0; i < static_cast<ezUInt32>(uiCount); ++i)
195  {
196  EZ_SUCCEED_OR_RETURN(ezStreamWriterUtil::Serialize<ValueType>(*this, Array[i]));
197  }
198 
199  return EZ_SUCCESS;
200 }
201 
202 template <typename ValueType, ezUInt32 uiSize>
203 ezResult ezStreamWriter::WriteArray(const ValueType (&Array)[uiSize])
204 {
205  const ezUInt64 uiWriteSize = uiSize;
206  WriteQWordValue(&uiWriteSize);
207 
208  for (ezUInt32 i = 0; i < static_cast<ezUInt32>(uiSize); ++i)
209  {
210  EZ_SUCCEED_OR_RETURN(ezStreamWriterUtil::Serialize<ValueType>(*this, Array[i]));
211  }
212 
213  return EZ_SUCCESS;
214 }
215 
216 template <typename KeyType, typename Comparer>
218 {
219  const ezUInt64 uiWriteSize = Set.GetCount();
220  WriteQWordValue(&uiWriteSize);
221 
222  for (const auto& item : Set)
223  {
224  EZ_SUCCEED_OR_RETURN(ezStreamWriterUtil::Serialize<KeyType>(*this, item));
225  }
226 
227  return EZ_SUCCESS;
228 }
229 
230 template <typename KeyType, typename ValueType, typename Comparer>
232 {
233  const ezUInt64 uiWriteSize = Map.GetCount();
234  WriteQWordValue(&uiWriteSize);
235 
236  for (auto It = Map.GetIterator(); It.IsValid(); ++It)
237  {
238  EZ_SUCCEED_OR_RETURN(ezStreamWriterUtil::Serialize<KeyType>(*this, It.Key()));
239  EZ_SUCCEED_OR_RETURN(ezStreamWriterUtil::Serialize<ValueType>(*this, It.Value()));
240  }
241 
242  return EZ_SUCCESS;
243 }
244 
245 namespace ezStreamReaderUtil
246 {
247  template <class T>
248  auto DeserializeImpl(ezStreamReader& Stream, T& Obj, int) -> decltype(Stream >> Obj, ezResult(EZ_SUCCESS))
249  {
250  Stream >> Obj;
251 
252  return EZ_SUCCESS;
253  }
254 
255  template <class T>
256  auto DeserializeImpl(ezStreamReader& Stream, T& Obj, long) -> decltype(Obj.Deserialize(Stream), ezResult(EZ_SUCCESS))
257  {
258  return ezToResult(Obj.Deserialize(Stream));
259  }
260 
261  template <class T>
262  auto DeserializeImpl(ezStreamReader& Stream, T& Obj, float) -> decltype(Obj.deserialize(Stream), ezResult(EZ_SUCCESS))
263  {
264  return ezToResult(Obj.deserialize(Stream));
265  }
266 
267  template <class T>
268  auto Deserialize(ezStreamReader& Stream, T& Obj) -> decltype(DeserializeImpl(Stream, Obj, 0), ezResult(EZ_SUCCESS))
269  {
270  return DeserializeImpl(Stream, Obj, 0);
271  }
272 } // namespace ezStreamReaderUtil
273 
274 template <typename ArrayType, typename ValueType>
276 {
277  ezUInt64 uiCount = 0;
278  ReadQWordValue(&uiCount);
279 
280  EZ_ASSERT_DEV(uiCount < std::numeric_limits<ezUInt32>::max(),
281  "Containers currently use 32 bit for counts internally. Value from file is too large.");
282 
283  Array.Clear();
284 
285  if (uiCount > 0)
286  {
287  static_cast<ArrayType&>(Array).Reserve(uiCount);
288 
289  for (ezUInt32 i = 0; i < static_cast<ezUInt32>(uiCount); ++i)
290  {
291  EZ_SUCCEED_OR_RETURN(ezStreamReaderUtil::Deserialize<ValueType>(*this, Array.ExpandAndGetRef()));
292  }
293  }
294 
295  return EZ_SUCCESS;
296 }
297 
298 template <typename ValueType, ezUInt32 uiSize>
299 ezResult ezStreamReader::ReadArray(ValueType (&Array)[uiSize])
300 {
301  ezUInt64 uiCount = 0;
302  ReadQWordValue(&uiCount);
303 
304  EZ_ASSERT_DEV(uiCount < std::numeric_limits<ezUInt32>::max(),
305  "Containers currently use 32 bit for counts internally. Value from file is too large.");
306 
307  if (static_cast<ezUInt32>(uiCount) != uiSize)
308  return EZ_FAILURE;
309 
310  for (ezUInt32 i = 0; i < static_cast<ezUInt32>(uiCount); ++i)
311  {
312  EZ_SUCCEED_OR_RETURN(ezStreamReaderUtil::Deserialize<ValueType>(*this, Array[i]));
313  }
314 
315  return EZ_SUCCESS;
316 }
317 
318 template <typename KeyType, typename Comparer>
320 {
321  ezUInt64 uiCount = 0;
322  ReadQWordValue(&uiCount);
323 
324  EZ_ASSERT_DEV(uiCount < std::numeric_limits<ezUInt32>::max(),
325  "Containers currently use 32 bit for counts internally. Value from file is too large.");
326 
327  Set.Clear();
328 
329  for (ezUInt32 i = 0; i < static_cast<ezUInt32>(uiCount); ++i)
330  {
331  KeyType Item;
332  EZ_SUCCEED_OR_RETURN(ezStreamReaderUtil::Deserialize(*this, Item));
333 
334  Set.Insert(std::move(Item));
335  }
336 
337  return EZ_SUCCESS;
338 }
339 
340 template <typename KeyType, typename ValueType, typename Comparer>
342 {
343  ezUInt64 uiCount = 0;
344  ReadQWordValue(&uiCount);
345 
346  EZ_ASSERT_DEV(uiCount < std::numeric_limits<ezUInt32>::max(),
347  "Containers currently use 32 bit for counts internally. Value from file is too large.");
348 
349  Map.Clear();
350 
351  for (ezUInt32 i = 0; i < static_cast<ezUInt32>(uiCount); ++i)
352  {
353  KeyType Key;
354  ValueType Value;
355  EZ_SUCCEED_OR_RETURN(ezStreamReaderUtil::Deserialize(*this, Key));
356  EZ_SUCCEED_OR_RETURN(ezStreamReaderUtil::Deserialize(*this, Value));
357 
358  Map.Insert(std::move(Key), std::move(Value));
359  }
360 
361  return EZ_SUCCESS;
362 }
363 
static EZ_ALWAYS_INLINE ezUInt16 Switch(ezUInt16 uiWord)
Returns a single switched word (16 bit value).
Definition: EndianHelper.h:45
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:481
ezResult WriteSet(const ezSetBase< KeyType, Comparer > &Set)
Writes a set.
Definition: Stream_inl.h:217
ezResult WriteDWordValue(const T *pDWordValue)
Helper method to write a dword value correctly (copes with potentially different endianess) ...
Definition: Stream_inl.h:126
ezUInt32 GetCount() const
Returns the number of elements currently stored in the set. O(1) operation.
Definition: Set_inl.h:193
#define EZ_ASSERT_ALWAYS(bCondition, szErrorMsg,...)
Macro to raise an error, if a condition is not met. Allows to write a message using printf style...
Definition: Assert.h:60
Interface for binary in (read) streams.
Definition: Stream.h:14
ezResult WriteQWordValue(const T *pQWordValue)
Helper method to write a qword value correctly (copes with potentially different endianess) ...
Definition: Stream_inl.h:134
ezResult ReadDWordValue(T *pDWordValue)
Helper method to read a dword value correctly (copes with potentially different endianess) ...
Definition: Stream_inl.h:96
Iterator Insert(CompatibleKeyType &&key)
Inserts the key into the tree and returns an Iterator to it. O(log n) operation.
Definition: Set_inl.h:386
Definition: Stream_inl.h:245
#define EZ_ASSERT_DEV(bCondition, szErrorMsg,...)
Macro to raise an error, if a condition is not met.
Definition: Assert.h:116
ezResult ReadMap(ezMapBase< KeyType, ValueType, Comparer > &Map)
Reads a map.
Definition: Stream_inl.h:341
virtual ezUInt64 ReadBytes(void *pReadBuffer, ezUInt64 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:86
ezResult ReadArray(ezArrayBase< ValueType, ArrayType > &Array)
Reads an array of elements from the stream.
Definition: Stream_inl.h:275
Base class for all array containers. Implements all the basic functionality that only requires a poin...
Definition: ArrayBase.h:12
void Clear()
Destroys all elements in the map and resets its size to zero.
Definition: Map_inl.h:163
ezResult WriteMap(const ezMapBase< KeyType, ValueType, Comparer > &Map)
Writes a map.
Definition: Stream_inl.h:231
A set container that only stores whether an element resides in it or not. Similar to STL::set...
Definition: Set.h:12
Definition: Stream_inl.h:159
ezResult WriteWordValue(const T *pWordValue)
Helper method to write a word value correctly (copes with potentially different endianess) ...
Definition: Stream_inl.h:118
ezResult ReadSet(ezSetBase< KeyType, Comparer > &Set)
Reads a set.
Definition: Stream_inl.h:319
An associative container. Similar to STL::map.
Definition: Map.h:17
Iterator GetIterator()
Returns an Iterator to the very first element.
Definition: Map_inl.h:195
ezResult ReadWordValue(T *pWordValue)
Helper method to read a word value correctly (copes with potentially different endianess) ...
Definition: Stream_inl.h:85
ezUInt32 GetCount() const
Returns the number of elements currently stored in the map. O(1) operation.
Definition: Map_inl.h:188
void Clear()
Destroys all elements in the set and resets its size to zero.
Definition: Set_inl.h:168
Default enum for returning failure or success, instead of using a bool.
Definition: Types.h:51
ezResult WriteArray(const ezArrayBase< ValueType, ArrayType > &Array)
Writes an array of elements to the stream.
Definition: Stream_inl.h:189
virtual ezResult WriteBytes(const void *pWriteBuffer, ezUInt64 uiBytesToWrite)=0
Writes a raw number of bytes from the buffer, this is the only method which has to be implemented to ...
ezResult ReadQWordValue(T *pQWordValue)
Helper method to read a qword value correctly (copes with potentially different endianess) ...
Definition: Stream_inl.h:107
EZ_ALWAYS_INLINE void WriteVersion(ezTypeVersion uiVersion)
Writes a type version to the stream.
Definition: Stream_inl.h:153