1 | //************************************ bs::framework - Copyright 2018 Marko Pintera **************************************// |
2 | //*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********// |
3 | #pragma once |
4 | |
5 | #include "Allocators/BsMemoryAllocator.h" |
6 | #include "Prerequisites/BsFwdDeclUtil.h" // For TIDs |
7 | #include "Prerequisites/BsTypes.h" // For UINT32 |
8 | |
9 | #include <limits> |
10 | #include <type_traits> // For std::is_pod |
11 | #include <utility> // For std::pair |
12 | #include <vector> |
13 | |
14 | namespace bs |
15 | { |
16 | /** @addtogroup Utility |
17 | * @{ |
18 | */ |
19 | |
20 | /** @addtogroup RTTI |
21 | * @{ |
22 | */ |
23 | |
24 | /** |
25 | * Template that you may specialize with a class if you want to provide simple serialization for it. |
26 | * |
27 | * Any type that uses the "plain" field in the RTTI system must specialize this class. |
28 | * |
29 | * @note |
30 | * Normally you will want to implement IReflectable interface if you want to provide serialization |
31 | * as that interface properly handles versioning, nested objects, pointer handling and more. |
32 | * |
33 | * @note |
34 | * This class is useful for types you can easily serialize using a memcpy (built-in types like int/float/etc), or |
35 | * types you cannot modify so they implement IReflectable interface (like std::string or std::vector). |
36 | * |
37 | * @see RTTITypeBase |
38 | * @see RTTIField |
39 | */ |
40 | template<class T> |
41 | struct RTTIPlainType |
42 | { |
43 | static_assert(std::is_pod<T>::value, |
44 | "Provided type isn't plain-old-data. You need to specialize RTTIPlainType template in order to serialize this type. " \ |
45 | " (Or call BS_ALLOW_MEMCPY_SERIALIZATION(type) macro if you are sure the type can be properly serialized using just memcpy.)" ); |
46 | |
47 | enum { id = 0 /**< Unique id for the serializable type. */ }; |
48 | enum { hasDynamicSize = 0 /**< 0 (Object has static size less than 255 bytes, for example int) or 1 (Dynamic size with no size restriction, for example string) */ }; |
49 | |
50 | /** Serializes the provided object into the provided pre-allocated memory buffer. */ |
51 | static void toMemory(const T& data, char* memory) |
52 | { |
53 | memcpy(memory, &data, sizeof(T)); |
54 | } |
55 | |
56 | /** |
57 | * Deserializes a previously allocated object from the provided memory buffer. Return the number of bytes read |
58 | * from the memory buffer. |
59 | */ |
60 | static UINT32 fromMemory(T& data, char* memory) |
61 | { |
62 | memcpy(&data, memory, sizeof(T)); |
63 | return sizeof(T); |
64 | } |
65 | |
66 | /** Returns the size of the provided object. (Works for both static and dynamic size types) */ |
67 | static UINT32 getDynamicSize(const T& data) |
68 | { |
69 | return sizeof(T); |
70 | } |
71 | }; |
72 | |
73 | /** |
74 | * Helper method when serializing known data types that have valid |
75 | * RTTIPlainType specialization. |
76 | * |
77 | * Returns the size of the element. If elements serializable type is |
78 | * specialized with hasDynamicSize == true, the dynamic size is calculated, |
79 | * otherwise sizeof() is used. |
80 | */ |
81 | template<class ElemType> |
82 | UINT32 rttiGetElemSize(const ElemType& data) |
83 | { |
84 | if(RTTIPlainType<ElemType>::hasDynamicSize == 1) |
85 | return RTTIPlainType<ElemType>::getDynamicSize(data); |
86 | else |
87 | return sizeof(ElemType); |
88 | } |
89 | |
90 | /** |
91 | * Helper method when serializing known data types that have valid |
92 | * RTTIPlainType specialization. |
93 | * |
94 | * Writes the specified data into memory, advances the memory pointer by the |
95 | * bytes written and returns pointer to new memory. |
96 | */ |
97 | template<class ElemType> |
98 | char* rttiWriteElem(const ElemType& data, char* memory) |
99 | { |
100 | RTTIPlainType<ElemType>::toMemory(data, memory); |
101 | |
102 | return memory + rttiGetElemSize(data); |
103 | } |
104 | |
105 | /** |
106 | * Helper method when serializing known data types that have valid |
107 | * RTTIPlainType specialization. |
108 | * |
109 | * Writes the specified data into memory, advances the memory pointer by the |
110 | * bytes written and returns pointer to new memory. Also increases the size |
111 | * value by the size of the written element. |
112 | */ |
113 | template<class ElemType> |
114 | char* rttiWriteElem(const ElemType& data, char* memory, UINT32& size) |
115 | { |
116 | RTTIPlainType<ElemType>::toMemory(data, memory); |
117 | |
118 | UINT32 elemSize = rttiGetElemSize(data); |
119 | size += elemSize; |
120 | |
121 | return memory + elemSize; |
122 | } |
123 | |
124 | /** |
125 | * Helper method when serializing known data types that have valid |
126 | * RTTIPlainType specialization. |
127 | * |
128 | * Reads the specified data into memory, advances the memory pointer by the |
129 | * bytes read and returns pointer to new memory. |
130 | */ |
131 | template<class ElemType> |
132 | char* rttiReadElem(ElemType& data, char* memory) |
133 | { |
134 | UINT32 size = RTTIPlainType<ElemType>::fromMemory(data, memory); |
135 | |
136 | return memory + size; |
137 | } |
138 | |
139 | /** |
140 | * Helper method when serializing known data types that have valid |
141 | * RTTIPlainType specialization. |
142 | * |
143 | * Reads the specified data into memory, advances the memory pointer by the |
144 | * bytes read and returns pointer to new memory. Also increases the size |
145 | * value by the size of the read element. |
146 | */ |
147 | template<class ElemType> |
148 | char* rttiReadElem(ElemType& data, char* memory, UINT32& size) |
149 | { |
150 | UINT32 elemSize = RTTIPlainType<ElemType>::fromMemory(data, memory); |
151 | |
152 | size += elemSize; |
153 | return memory + elemSize; |
154 | } |
155 | |
156 | /** Helper for checking for existance of rttiEnumFields method on a class. */ |
157 | template <class T> |
158 | struct has_rttiEnumFields |
159 | { |
160 | struct dummy {}; |
161 | |
162 | template <typename C, typename P> |
163 | static auto test(P* p) -> decltype(std::declval<C>().rttiEnumFields(*p), std::true_type()); |
164 | |
165 | template <typename, typename> |
166 | static std::false_type test(...); |
167 | |
168 | typedef decltype(test<T, dummy>(nullptr)) type; |
169 | static const bool value = std::is_same<std::true_type, decltype(test<T, dummy>(nullptr))>::value; |
170 | }; |
171 | |
172 | /** |
173 | * Notify the RTTI system that the specified type may be serialized just by using a memcpy. |
174 | * |
175 | * @note Internally this creates a basic RTTIPlainType<T> specialization for the type. |
176 | * |
177 | * @see RTTIPlainType<T> |
178 | */ |
179 | #define BS_ALLOW_MEMCPY_SERIALIZATION(type) \ |
180 | static_assert (std::is_trivially_copyable<type>()==true, \ |
181 | #type " is not trivially copyable"); \ |
182 | template<> struct RTTIPlainType<type> \ |
183 | { enum { id=0 }; enum { hasDynamicSize = 0 }; \ |
184 | static void toMemory(const type& data, char* memory) \ |
185 | { memcpy(memory, &data, sizeof(type)); } \ |
186 | static UINT32 fromMemory(type& data, char* memory) \ |
187 | { memcpy(&data, memory, sizeof(type)); return sizeof(type); } \ |
188 | static UINT32 getDynamicSize(const type& data) \ |
189 | { return sizeof(type); } \ |
190 | }; |
191 | |
192 | /** @cond SPECIALIZATIONS */ |
193 | |
194 | /** |
195 | * RTTIPlainType for std::vector. |
196 | * |
197 | * @see RTTIPlainType |
198 | */ |
199 | template<class T> struct RTTIPlainType<std::vector<T, StdAlloc<T>>> |
200 | { |
201 | enum { id = TID_Vector }; enum { hasDynamicSize = 1 }; |
202 | |
203 | /** @copydoc RTTIPlainType::toMemory */ |
204 | static void toMemory(const std::vector<T, StdAlloc<T>>& data, char* memory) |
205 | { |
206 | UINT32 size = sizeof(UINT32); |
207 | char* memoryStart = memory; |
208 | memory += sizeof(UINT32); |
209 | |
210 | UINT32 numElements = (UINT32)data.size(); |
211 | memcpy(memory, &numElements, sizeof(UINT32)); |
212 | memory += sizeof(UINT32); |
213 | size += sizeof(UINT32); |
214 | |
215 | for(const auto& item : data) |
216 | { |
217 | UINT32 elementSize = rttiGetElemSize(item); |
218 | RTTIPlainType<T>::toMemory(item, memory); |
219 | |
220 | memory += elementSize; |
221 | size += elementSize; |
222 | } |
223 | |
224 | memcpy(memoryStart, &size, sizeof(UINT32)); |
225 | } |
226 | |
227 | /** @copydoc RTTIPlainType::fromMemory */ |
228 | static UINT32 fromMemory(std::vector<T, StdAlloc<T>>& data, char* memory) |
229 | { |
230 | UINT32 size = 0; |
231 | memcpy(&size, memory, sizeof(UINT32)); |
232 | memory += sizeof(UINT32); |
233 | |
234 | UINT32 numElements; |
235 | memcpy(&numElements, memory, sizeof(UINT32)); |
236 | memory += sizeof(UINT32); |
237 | |
238 | data.clear(); |
239 | for(UINT32 i = 0; i < numElements; i++) |
240 | { |
241 | T element; |
242 | UINT32 elementSize = RTTIPlainType<T>::fromMemory(element, memory); |
243 | data.push_back(element); |
244 | |
245 | memory += elementSize; |
246 | } |
247 | |
248 | return size; |
249 | } |
250 | |
251 | /** @copydoc RTTIPlainType::getDynamicSize */ |
252 | static UINT32 getDynamicSize(const std::vector<T, StdAlloc<T>>& data) |
253 | { |
254 | UINT64 dataSize = sizeof(UINT32) * 2; |
255 | |
256 | for(const auto& item : data) |
257 | dataSize += rttiGetElemSize(item); |
258 | |
259 | assert(dataSize <= std::numeric_limits<UINT32>::max()); |
260 | |
261 | return (UINT32)dataSize; |
262 | } |
263 | }; |
264 | |
265 | /** |
266 | * RTTIPlainType for std::list. |
267 | * |
268 | * @see RTTIPlainType |
269 | */ |
270 | template<class T> struct RTTIPlainType<std::list<T, StdAlloc<T>>> |
271 | { |
272 | enum { id = TID_List }; enum { hasDynamicSize = 1 }; |
273 | |
274 | /** @copydoc RTTIPlainType::toMemory */ |
275 | static void toMemory(const std::list<T, StdAlloc<T>>& data, char* memory) |
276 | { |
277 | UINT32 size = sizeof(UINT32); |
278 | char* memoryStart = memory; |
279 | memory += sizeof(UINT32); |
280 | |
281 | UINT32 numElements = (UINT32)data.size(); |
282 | memcpy(memory, &numElements, sizeof(UINT32)); |
283 | memory += sizeof(UINT32); |
284 | size += sizeof(UINT32); |
285 | |
286 | for(const auto& item : data) |
287 | { |
288 | UINT32 elementSize = rttiGetElemSize(item); |
289 | RTTIPlainType<T>::toMemory(item, memory); |
290 | |
291 | memory += elementSize; |
292 | size += elementSize; |
293 | } |
294 | |
295 | memcpy(memoryStart, &size, sizeof(UINT32)); |
296 | } |
297 | |
298 | /** @copydoc RTTIPlainType::fromMemory */ |
299 | static UINT32 fromMemory(std::list<T, StdAlloc<T>>& data, char* memory) |
300 | { |
301 | UINT32 size = 0; |
302 | memcpy(&size, memory, sizeof(UINT32)); |
303 | memory += sizeof(UINT32); |
304 | |
305 | UINT32 numElements; |
306 | memcpy(&numElements, memory, sizeof(UINT32)); |
307 | memory += sizeof(UINT32); |
308 | |
309 | for(UINT32 i = 0; i < numElements; i++) |
310 | { |
311 | T element; |
312 | UINT32 elementSize = RTTIPlainType<T>::fromMemory(element, memory); |
313 | data.push_back(element); |
314 | |
315 | memory += elementSize; |
316 | } |
317 | |
318 | return size; |
319 | } |
320 | |
321 | /** @copydoc RTTIPlainType::getDynamicSize */ |
322 | static UINT32 getDynamicSize(const std::list<T, StdAlloc<T>>& data) |
323 | { |
324 | UINT64 dataSize = sizeof(UINT32) * 2; |
325 | |
326 | for(const auto& item : data) |
327 | dataSize += rttiGetElemSize(item); |
328 | |
329 | assert(dataSize <= std::numeric_limits<UINT32>::max()); |
330 | |
331 | return (UINT32)dataSize; |
332 | } |
333 | }; |
334 | |
335 | /** |
336 | * RTTIPlainType for std::set. |
337 | * |
338 | * @see RTTIPlainType |
339 | */ |
340 | template<class T> struct RTTIPlainType<std::set<T, std::less<T>, StdAlloc<T>>> |
341 | { |
342 | enum { id = TID_Set }; enum { hasDynamicSize = 1 }; |
343 | |
344 | /** @copydoc RTTIPlainType::toMemory */ |
345 | static void toMemory(const std::set<T, std::less<T>, StdAlloc<T>>& data, char* memory) |
346 | { |
347 | UINT32 size = sizeof(UINT32); |
348 | char* memoryStart = memory; |
349 | memory += sizeof(UINT32); |
350 | |
351 | UINT32 numElements = (UINT32)data.size(); |
352 | memcpy(memory, &numElements, sizeof(UINT32)); |
353 | memory += sizeof(UINT32); |
354 | size += sizeof(UINT32); |
355 | |
356 | for(const auto& item : data) |
357 | { |
358 | UINT32 elementSize = rttiGetElemSize(item); |
359 | RTTIPlainType<T>::toMemory(item, memory); |
360 | |
361 | memory += elementSize; |
362 | size += elementSize; |
363 | } |
364 | |
365 | memcpy(memoryStart, &size, sizeof(UINT32)); |
366 | } |
367 | |
368 | /** @copydoc RTTIPlainType::fromMemory */ |
369 | static UINT32 fromMemory(std::set<T, std::less<T>, StdAlloc<T>>& data, char* memory) |
370 | { |
371 | UINT32 size = 0; |
372 | memcpy(&size, memory, sizeof(UINT32)); |
373 | memory += sizeof(UINT32); |
374 | |
375 | UINT32 numElements; |
376 | memcpy(&numElements, memory, sizeof(UINT32)); |
377 | memory += sizeof(UINT32); |
378 | |
379 | for(UINT32 i = 0; i < numElements; i++) |
380 | { |
381 | T element; |
382 | UINT32 elementSize = RTTIPlainType<T>::fromMemory(element, memory); |
383 | data.insert(element); |
384 | |
385 | memory += elementSize; |
386 | } |
387 | |
388 | return size; |
389 | } |
390 | |
391 | /** @copydoc RTTIPlainType::getDynamicSize */ |
392 | static UINT32 getDynamicSize(const std::set<T, std::less<T>, StdAlloc<T>>& data) |
393 | { |
394 | UINT64 dataSize = sizeof(UINT32) * 2; |
395 | |
396 | for(const auto& item : data) |
397 | dataSize += rttiGetElemSize(item); |
398 | |
399 | assert(dataSize <= std::numeric_limits<UINT32>::max()); |
400 | |
401 | return (UINT32)dataSize; |
402 | } |
403 | }; |
404 | |
405 | /** |
406 | * RTTIPlainType for std::map. |
407 | * |
408 | * @see RTTIPlainType |
409 | */ |
410 | template<class Key, class Value> struct RTTIPlainType<std::map<Key, Value, std::less<Key>, StdAlloc<std::pair<const Key, Value>>>> |
411 | { |
412 | enum { id = TID_Map }; enum { hasDynamicSize = 1 }; |
413 | |
414 | /** @copydoc RTTIPlainType::toMemory */ |
415 | static void toMemory(const std::map<Key, Value, std::less<Key>, StdAlloc<std::pair<const Key, Value>>>& data, char* memory) |
416 | { |
417 | UINT32 size = sizeof(UINT32); |
418 | char* memoryStart = memory; |
419 | memory += sizeof(UINT32); |
420 | |
421 | UINT32 numElements = (UINT32)data.size(); |
422 | memcpy(memory, &numElements, sizeof(UINT32)); |
423 | memory += sizeof(UINT32); |
424 | size += sizeof(UINT32); |
425 | |
426 | for(const auto& item : data) |
427 | { |
428 | UINT32 keySize = rttiGetElemSize(item.first); |
429 | RTTIPlainType<Key>::toMemory(item.first, memory); |
430 | |
431 | memory += keySize; |
432 | size += keySize; |
433 | |
434 | UINT32 valueSize = rttiGetElemSize(item.second); |
435 | RTTIPlainType<Value>::toMemory(item.second, memory); |
436 | |
437 | memory += valueSize; |
438 | size += valueSize; |
439 | } |
440 | |
441 | memcpy(memoryStart, &size, sizeof(UINT32)); |
442 | } |
443 | |
444 | /** @copydoc RTTIPlainType::fromMemory */ |
445 | static UINT32 fromMemory(std::map<Key, Value, std::less<Key>, StdAlloc<std::pair<const Key, Value>>>& data, char* memory) |
446 | { |
447 | UINT32 size = 0; |
448 | memcpy(&size, memory, sizeof(UINT32)); |
449 | memory += sizeof(UINT32); |
450 | |
451 | UINT32 numElements; |
452 | memcpy(&numElements, memory, sizeof(UINT32)); |
453 | memory += sizeof(UINT32); |
454 | |
455 | for(UINT32 i = 0; i < numElements; i++) |
456 | { |
457 | Key key; |
458 | UINT32 keySize = RTTIPlainType<Key>::fromMemory(key, memory); |
459 | memory += keySize; |
460 | |
461 | Value value; |
462 | UINT32 valueSize = RTTIPlainType<Value>::fromMemory(value, memory); |
463 | memory += valueSize; |
464 | |
465 | data[key] = value; |
466 | } |
467 | |
468 | return size; |
469 | } |
470 | |
471 | /** @copydoc RTTIPlainType::getDynamicSize */ |
472 | static UINT32 getDynamicSize(const std::map<Key, Value, std::less<Key>, StdAlloc<std::pair<const Key, Value>>>& data) |
473 | { |
474 | UINT64 dataSize = sizeof(UINT32) * 2; |
475 | |
476 | for(const auto& item : data) |
477 | { |
478 | dataSize += rttiGetElemSize(item.first); |
479 | dataSize += rttiGetElemSize(item.second); |
480 | } |
481 | |
482 | assert(dataSize <= std::numeric_limits<UINT32>::max()); |
483 | |
484 | return (UINT32)dataSize; |
485 | } |
486 | }; |
487 | |
488 | /** |
489 | * RTTIPlainType for std::unordered_map. |
490 | * |
491 | * @see RTTIPlainType |
492 | */ |
493 | template<class Key, class Value> |
494 | struct RTTIPlainType<std::unordered_map<Key, Value, std::hash<Key>, std::equal_to<Key>, StdAlloc<std::pair<const Key, Value>>>> |
495 | { |
496 | enum { id = TID_UnorderedMap }; enum { hasDynamicSize = 1 }; |
497 | |
498 | typedef std::unordered_map<Key, Value, std::hash<Key>, std::equal_to<Key>, StdAlloc<std::pair<const Key, Value>>> MapType; |
499 | |
500 | /** @copydoc RTTIPlainType::toMemory */ |
501 | static void toMemory(const MapType& data, char* memory) |
502 | { |
503 | UINT32 size = sizeof(UINT32); |
504 | char* memoryStart = memory; |
505 | memory += sizeof(UINT32); |
506 | |
507 | UINT32 numElements = (UINT32)data.size(); |
508 | memcpy(memory, &numElements, sizeof(UINT32)); |
509 | memory += sizeof(UINT32); |
510 | size += sizeof(UINT32); |
511 | |
512 | for(const auto& item : data) |
513 | { |
514 | UINT32 keySize = rttiGetElemSize(item.first); |
515 | RTTIPlainType<Key>::toMemory(item.first, memory); |
516 | |
517 | memory += keySize; |
518 | size += keySize; |
519 | |
520 | UINT32 valueSize = rttiGetElemSize(item.second); |
521 | RTTIPlainType<Value>::toMemory(item.second, memory); |
522 | |
523 | memory += valueSize; |
524 | size += valueSize; |
525 | } |
526 | |
527 | memcpy(memoryStart, &size, sizeof(UINT32)); |
528 | } |
529 | |
530 | /** @copydoc RTTIPlainType::fromMemory */ |
531 | static UINT32 fromMemory(MapType& data, char* memory) |
532 | { |
533 | UINT32 size = 0; |
534 | memcpy(&size, memory, sizeof(UINT32)); |
535 | memory += sizeof(UINT32); |
536 | |
537 | UINT32 numElements; |
538 | memcpy(&numElements, memory, sizeof(UINT32)); |
539 | memory += sizeof(UINT32); |
540 | |
541 | for (UINT32 i = 0; i < numElements; i++) |
542 | { |
543 | Key key; |
544 | UINT32 keySize = RTTIPlainType<Key>::fromMemory(key, memory); |
545 | memory += keySize; |
546 | |
547 | Value value; |
548 | UINT32 valueSize = RTTIPlainType<Value>::fromMemory(value, memory); |
549 | memory += valueSize; |
550 | |
551 | data[key] = value; |
552 | } |
553 | |
554 | return size; |
555 | } |
556 | |
557 | /** @copydoc RTTIPlainType::getDynamicSize */ |
558 | static UINT32 getDynamicSize(const MapType& data) |
559 | { |
560 | UINT64 dataSize = sizeof(UINT32)* 2; |
561 | |
562 | for(const auto& item : data) |
563 | { |
564 | dataSize += RTTIPlainType<Key>::getDynamicSize(item.first); |
565 | dataSize += RTTIPlainType<Value>::getDynamicSize(item.second); |
566 | } |
567 | |
568 | assert(dataSize <= std::numeric_limits<UINT32>::max()); |
569 | |
570 | return (UINT32)dataSize; |
571 | } |
572 | }; |
573 | |
574 | /** |
575 | * RTTIPlainType for std::unordered_set. |
576 | * |
577 | * @see RTTIPlainType |
578 | */ |
579 | template<class Key> |
580 | struct RTTIPlainType<std::unordered_set<Key, std::hash<Key>, std::equal_to<Key>, StdAlloc<Key>>> |
581 | { |
582 | enum { id = TID_UnorderedSet }; enum { hasDynamicSize = 1 }; |
583 | |
584 | typedef std::unordered_set<Key, std::hash<Key>, std::equal_to<Key>, StdAlloc<Key>> MapType; |
585 | |
586 | /** @copydoc RTTIPlainType::toMemory */ |
587 | static void toMemory(const MapType& data, char* memory) |
588 | { |
589 | UINT32 size = sizeof(UINT32); |
590 | char* memoryStart = memory; |
591 | memory += sizeof(UINT32); |
592 | |
593 | UINT32 numElements = (UINT32)data.size(); |
594 | memcpy(memory, &numElements, sizeof(UINT32)); |
595 | memory += sizeof(UINT32); |
596 | size += sizeof(UINT32); |
597 | |
598 | for(const auto& item : data) |
599 | { |
600 | UINT32 keySize = rttiGetElemSize(item); |
601 | RTTIPlainType<Key>::toMemory(item, memory); |
602 | |
603 | memory += keySize; |
604 | size += keySize; |
605 | } |
606 | |
607 | memcpy(memoryStart, &size, sizeof(UINT32)); |
608 | } |
609 | |
610 | /** @copydoc RTTIPlainType::fromMemory */ |
611 | static UINT32 fromMemory(MapType& data, char* memory) |
612 | { |
613 | UINT32 size = 0; |
614 | memcpy(&size, memory, sizeof(UINT32)); |
615 | memory += sizeof(UINT32); |
616 | |
617 | UINT32 numElements; |
618 | memcpy(&numElements, memory, sizeof(UINT32)); |
619 | memory += sizeof(UINT32); |
620 | |
621 | for (UINT32 i = 0; i < numElements; i++) |
622 | { |
623 | Key key; |
624 | UINT32 keySize = RTTIPlainType<Key>::fromMemory(key, memory); |
625 | memory += keySize; |
626 | |
627 | data.insert(key); |
628 | } |
629 | |
630 | return size; |
631 | } |
632 | |
633 | /** @copydoc RTTIPlainType::getDynamicSize */ |
634 | static UINT32 getDynamicSize(const MapType& data) |
635 | { |
636 | UINT64 dataSize = sizeof(UINT32)* 2; |
637 | |
638 | for(const auto& item : data) |
639 | { |
640 | dataSize += rttiGetElemSize(item); |
641 | } |
642 | |
643 | assert(dataSize <= std::numeric_limits<UINT32>::max()); |
644 | |
645 | return (UINT32)dataSize; |
646 | } |
647 | }; |
648 | |
649 | /** |
650 | * RTTIPlainType for std::pair. |
651 | * |
652 | * @see RTTIPlainType |
653 | */ |
654 | template<class A, class B> struct RTTIPlainType<std::pair<A, B>> |
655 | { |
656 | enum { id = TID_Pair }; enum { hasDynamicSize = 1 }; |
657 | |
658 | /** @copydoc RTTIPlainType::toMemory */ |
659 | static void toMemory(const std::pair<A, B>& data, char* memory) |
660 | { |
661 | UINT32 size = sizeof(UINT32); |
662 | char* memoryStart = memory; |
663 | memory += sizeof(UINT32); |
664 | |
665 | UINT32 firstSize = rttiGetElemSize(data.first); |
666 | RTTIPlainType<A>::toMemory(data.first, memory); |
667 | |
668 | memory += firstSize; |
669 | size += firstSize; |
670 | |
671 | UINT32 secondSize = rttiGetElemSize(data.second); |
672 | RTTIPlainType<B>::toMemory(data.second, memory); |
673 | |
674 | memory += secondSize; |
675 | size += secondSize; |
676 | |
677 | memcpy(memoryStart, &size, sizeof(UINT32)); |
678 | } |
679 | |
680 | /** @copydoc RTTIPlainType::fromMemory */ |
681 | static UINT32 fromMemory(std::pair<A, B>& data, char* memory) |
682 | { |
683 | UINT32 size = 0; |
684 | memcpy(&size, memory, sizeof(UINT32)); |
685 | memory += sizeof(UINT32); |
686 | |
687 | UINT32 firstSize = RTTIPlainType<A>::fromMemory(data.first, memory); |
688 | memory += firstSize; |
689 | |
690 | UINT32 secondSize = RTTIPlainType<B>::fromMemory(data.second, memory); |
691 | memory += secondSize; |
692 | |
693 | return size; |
694 | } |
695 | |
696 | /** @copydoc RTTIPlainType::getDynamicSize */ |
697 | static UINT32 getDynamicSize(const std::pair<A, B>& data) |
698 | { |
699 | UINT64 dataSize = sizeof(UINT32); |
700 | dataSize += rttiGetElemSize(data.first); |
701 | dataSize += rttiGetElemSize(data.second); |
702 | |
703 | assert(dataSize <= std::numeric_limits<UINT32>::max()); |
704 | |
705 | return (UINT32)dataSize; |
706 | } |
707 | }; |
708 | |
709 | /** @endcond */ |
710 | |
711 | /** @} */ |
712 | /** @} */ |
713 | } |
714 | |