DelegateMQ
Loading...
Searching...
No Matches
msg_serialize.h
Go to the documentation of this file.
1
4
5#ifndef _MSG_SERIALIZE_H
6#define _MSG_SERIALIZE_H
7
8#include <stdint.h>
9#include <string.h>
10#include <type_traits>
11#include <typeinfo>
12#include <iostream>
13#include <memory>
14#include <vector>
15#include <list>
16#include <map>
17#include <set>
18#include <string>
19
21{
22 template <typename T>
23 struct is_shared_ptr : std::false_type {};
24
25 template <typename T>
26 struct is_shared_ptr<std::shared_ptr<T>> : std::true_type {};
27
28 template <typename U>
29 struct is_unsupported_container : std::false_type {};
30}
31
32// Define to enable compile-time checking of unsupported container types
33// Undefine for less compile-time include file dependencies
34#define CHECK_UNSUPPORTED_CONTAINER
35#ifdef CHECK_UNSUPPORTED_CONTAINER
36
37#include <deque>
38#include <forward_list>
39#include <queue>
40#include <stack>
41#include <unordered_set>
42#include <unordered_map>
43
44 template <typename U>
45 struct serialize_traits::is_unsupported_container<std::multiset<U>> : std::true_type {};
46
47 template <typename U, typename V>
48 struct serialize_traits::is_unsupported_container<std::pair<U, V>> : std::true_type {};
49
50 template <typename T, typename Alloc>
51 struct serialize_traits::is_unsupported_container<std::deque<T, Alloc>> : std::true_type {};
52
53 template <typename T, typename Alloc>
54 struct serialize_traits::is_unsupported_container<std::forward_list<T, Alloc>> : std::true_type {};
55
56 template <typename T, typename Alloc>
57 struct serialize_traits::is_unsupported_container<std::priority_queue<T, std::vector<T, Alloc>>> : std::true_type {};
58
59 template <typename T, typename Alloc>
60 struct serialize_traits::is_unsupported_container<std::queue<T, Alloc>> : std::true_type {};
61
62 template <typename T, typename Alloc>
63 struct serialize_traits::is_unsupported_container<std::stack<T, Alloc>> : std::true_type {};
64
65 template <typename T, typename Hash, typename KeyEqual, typename Alloc>
66 struct serialize_traits::is_unsupported_container<std::unordered_multiset<T, Hash, KeyEqual, Alloc>> : std::true_type {};
67
68 template <typename Key, typename T, typename Hash, typename KeyEqual, typename Alloc>
69 struct serialize_traits::is_unsupported_container<std::unordered_map<Key, T, Hash, KeyEqual, Alloc>> : std::true_type {};
70
71 template <typename Key, typename T, typename Hash, typename KeyEqual, typename Alloc>
72 struct serialize_traits::is_unsupported_container<std::unordered_multimap<Key, T, Hash, KeyEqual, Alloc>> : std::true_type {};
73#endif // CHECK_UNSUPPORTED_CONTAINER
74
105{
106public:
108 class I
109 {
110 public:
118 virtual std::ostream& write(serialize& ms, std::ostream& os) = 0;
119
127 virtual std::istream& read(serialize& ms, std::istream& is) = 0;
128 };
129
130 enum class Type
131 {
132 UNKNOWN = 0,
133 LITERAL = 1,
134 STRING = 8,
135 WSTRING = 9,
136 VECTOR = 20,
137 MAP = 21,
138 LIST = 22,
139 SET = 23,
140 ENDIAN = 30,
141 USER_DEFINED = 31,
142 };
143
154
155 serialize() = default;
156 ~serialize() = default;
157
160 bool LE()
161 {
162 const static int n = 1;
163 const static bool le= (* (char *)&n == 1);
164 return le;
165 }
166
170 std::istream& readEndian(std::istream& is, bool& littleEndian)
171 {
172 if (read_type(is, Type::ENDIAN))
173 {
174 is.read((char*) &littleEndian, sizeof(littleEndian));
175 }
176 return is;
177 }
178
181 void writeEndian(std::ostream& os)
182 {
183 bool littleEndian = LE();
184 write_type(os, Type::ENDIAN);
185 os.write((const char*) &littleEndian, sizeof(littleEndian));
186 }
187
195 std::istream& read (std::istream& is, I* t_)
196 {
197 if (check_stop_parse(is))
198 return is;
199
200 if (check_pointer(is, t_))
201 {
202 if (read_type(is, Type::USER_DEFINED))
203 {
204 uint16_t size = 0;
205 std::streampos startPos = is.tellg();
206
207 read(is, size, false);
208
209 // Save the stop parsing position to prevent parsing overrun
210 push_stop_parse_pos(startPos + std::streampos(size));
211
212 t_->read(*this, is);
213
214 pop_stop_parse_pos();
215
216 if (is.good())
217 {
218 std::streampos endPos = is.tellg();
219 uint16_t rcvdSize = static_cast<uint16_t>(endPos - startPos);
220
221 // Did sender send a larger object than what receiver parsed?
222 if (rcvdSize < size)
223 {
224 // Skip over the extra received data
225 uint16_t seekOffset = size - rcvdSize;
226 is.seekg(seekOffset, std::ios_base::cur);
227 }
228 }
229 return is;
230 }
231 }
232 return is;
233 }
234
239 std::istream& read (std::istream& is, std::string& s)
240 {
241 if (check_stop_parse(is))
242 return is;
243
244 if (read_type(is, Type::STRING))
245 {
246 uint16_t size = 0;
247 read(is, size, false);
248 if (check_stream(is) && check_slength(is, size))
249 {
250 s.resize(size);
251 parseStatus(typeid(s), s.size());
252 read_internal(is, const_cast<char*>(s.c_str()), size, true);
253 }
254 }
255 return is;
256 }
257
262 std::istream& read (std::istream& is, std::wstring& s)
263 {
264 if (check_stop_parse(is))
265 return is;
266
267 if (read_type(is, Type::WSTRING))
268 {
269 uint16_t size = 0;
270 read(is, size, false);
271 if (check_stream(is) && check_slength(is, size))
272 {
273 s.resize(size);
274 parseStatus(typeid(s), s.size());
275 for (uint16_t ii = 0; ii < size; ii++)
276 {
277 wchar_t c;
278 int offset = sizeof(wchar_t) - WCHAR_SIZE;
279 read_internal(is, reinterpret_cast<char*>(&c) + offset, WCHAR_SIZE);
280 s[ii] = c;
281 }
282 }
283 }
284 return is;
285 }
286
291 std::istream& read (std::istream& is, char* str)
292 {
293 if (check_stop_parse(is))
294 return is;
295
296 if (read_type(is, Type::STRING))
297 {
298 uint16_t size = 0;
299 read(is, size, false);
300 if (check_stream(is) && check_slength(is, size))
301 {
302 if (check_pointer(is, str))
303 {
304 parseStatus(typeid(str), size);
305 read_internal(is, str, size, true);
306 }
307 }
308 }
309 return is;
310 }
311
320 std::istream& read (std::istream& is, std::vector<bool>& container)
321 {
322 if (check_stop_parse(is))
323 return is;
324
325 container.clear();
326 if (read_type(is, Type::VECTOR))
327 {
328 uint16_t size = 0;
329 read(is, size, false);
330 if (check_stream(is) && check_container_size(is, size))
331 {
332 parseStatus(typeid(container), size);
333 for (uint16_t i = 0; i < size; ++i)
334 {
335 bool t;
336 read(is, t);
337 container.push_back(t);
338 }
339 }
340 }
341 return is;
342 }
343
349 std::ostream& write (std::ostream& os, I* t_)
350 {
351 if (check_pointer(os, t_))
352 {
353 uint16_t elementSize = 0;
354
355 write_type(os, Type::USER_DEFINED);
356 std::streampos elementSizePos = os.tellp();
357 write(os, elementSize, false);
358
359 // Write user defined object
360 t_->write(*this, os);
361
362 if (os.good())
363 {
364 // Write user defined object size into stream
365 std::streampos currentPos = os.tellp();
366 os.seekp(elementSizePos);
367 elementSize = static_cast<uint16_t>(currentPos - elementSizePos);
368 write(os, elementSize, false);
369 os.seekp(currentPos);
370 }
371 return os;
372 }
373 return os;
374 }
375
380 std::ostream& write(std::ostream& os, const std::string& s)
381 {
382 uint16_t size = static_cast<uint16_t>(s.size());
383 write_type(os, Type::STRING);
384 write(os, size, false);
385 if (check_stream(os) && check_slength(os, size))
386 {
387 write_internal(os, s.c_str(), size, true);
388 }
389 return os;
390 }
391
396 std::ostream& write(std::ostream& os, std::string& s)
397 {
398 return write(os, static_cast<const std::string&>(s));
399 }
400
405 std::ostream& write (std::ostream& os, const std::wstring& s)
406 {
407 uint16_t size = static_cast<uint16_t>(s.size());
408 write_type(os, Type::WSTRING);
409 write(os, size, false);
410 if (check_stream(os) && check_slength(os, size))
411 {
412 for (uint16_t ii = 0; ii < size; ii++)
413 {
414 wchar_t c = s[ii];
415 int offset = sizeof(wchar_t) - WCHAR_SIZE;
416 write_internal(os, reinterpret_cast<char*>(&c) + offset, WCHAR_SIZE);
417 }
418 }
419 return os;
420 }
421
426 std::ostream& write (std::ostream& os, std::wstring& s)
427 {
428 return write(os, static_cast<const std::wstring&>(s));
429 }
430
435 std::ostream& write(std::ostream& os, char* str)
436 {
437 return write(os, static_cast<const char*>(str));
438 }
439
444 std::ostream& write (std::ostream& os, const char* str)
445 {
446 if (check_pointer(os, str))
447 {
448 uint16_t size = static_cast<uint16_t>(strlen(str)) + 1;
449 write_type(os, Type::STRING);
450 write(os, size, false);
451 if (check_stream(os) && check_slength(os, size))
452 {
453 write_internal (os, str, size, true);
454 }
455 }
456 return os;
457 }
458
467 std::ostream& write (std::ostream& os, std::vector<bool>& container)
468 {
469 uint16_t size = static_cast<uint16_t>(container.size());
470 write_type(os, Type::VECTOR);
471 write(os, size, false);
472 if (check_stream(os) && check_container_size(os, size))
473 {
474 for (const bool& c : container)
475 {
476 write(os, c);
477 }
478 }
479 return os;
480 }
481
486 template<typename T>
487 std::istream& read(std::istream& is, T &t_, bool readPrependedType = true)
488 {
489 static_assert(!serialize_traits::is_unsupported_container<T>::value, "Unsupported C++ container type");
490
491 static_assert(!(std::is_pointer<T>::value &&
492 (std::is_arithmetic<typename std::remove_pointer<T>::type>::value ||
493 std::is_class<typename std::remove_pointer<T>::type>::value)),
494 "T cannot be a pointer to a built-in or custom data type");
495
496 if (check_stop_parse(is))
497 return is;
498
499 // Is T a built-in data type (e.g. float, int, ...)?
500 if (std::is_class<T>::value == false)
501 {
502 // Is T is not a pointer type
503 if (std::is_pointer<T>::value == false)
504 {
505 if (readPrependedType)
506 {
507 if(!read_type(is, Type::LITERAL))
508 {
509 return is;
510 }
511 }
512
513 if (readPrependedType)
514 parseStatus(typeid(t_));
515 read_internal(is, (char*)&t_, sizeof (t_));
516 return is;
517 }
518 else
519 {
520 // Can't read pointers to built-in type
521 raiseError(ParsingError::INVALID_INPUT, __LINE__, __FILE__);
522 is.setstate(std::ios::failbit);
523 return is;
524 }
525 }
526 // Else T is a user defined data type (e.g. MyData)
527 else
528 {
529 parseStatus(typeid(t_));
530 read(is, (serialize::I*)&t_);
531 return is;
532 }
533 }
534
539 template<typename T>
540 std::ostream& write(std::ostream& os, T &t_, bool prependType = true)
541 {
542 static_assert(!serialize_traits::is_unsupported_container<T>::value, "Unsupported C++ container type");
543
544 static_assert(!(std::is_pointer<T>::value &&
545 (std::is_arithmetic<typename std::remove_pointer<T>::type>::value ||
546 std::is_class<typename std::remove_pointer<T>::type>::value)),
547 "T cannot be a pointer to a built-in or custom data type");
548
549 // If C++17 or higher
550#if defined(_MSVC_LANG) && _MSVC_LANG >= 201703L || __cplusplus >= 201703L
551 // Check if T is a user-defined class
552 if constexpr (std::is_class<T>::value)
553 {
554 // Ensure that the class T inherits from serialize::I
555 static_assert(std::is_base_of<serialize::I, T>::value, "T must inherit from serialize::I");
556
557 // Proceed with serialization for user-defined type
558 return write(os, (serialize::I*)&t_);
559 }
560 else
561 {
562 // If T is not a class, handle built-in data types
563 if (std::is_pointer<T>::value == false)
564 {
565 if (prependType)
566 {
567 write_type(os, Type::LITERAL);
568 }
569 return write_internal(os, (const char*)&t_, sizeof(t_));
570 }
571 else
572 {
573 // Can't write pointers to built-in types
574 raiseError(ParsingError::INVALID_INPUT, __LINE__, __FILE__);
575 os.setstate(std::ios::failbit);
576 return os;
577 }
578 }
579#else
580 // Is T type a built-in data type (e.g. float, int, ...)?
581 if (std::is_class<T>::value == false)
582 {
583 // Is T is not a pointer type
584 if (std::is_pointer<T>::value == false)
585 {
586 if (prependType)
587 {
588 write_type(os, Type::LITERAL);
589 }
590 return write_internal(os, (const char*)&t_, sizeof(t_));
591 }
592 else
593 {
594 // Can't write pointers to built-in type
595 raiseError(ParsingError::INVALID_INPUT, __LINE__, __FILE__);
596 os.setstate(std::ios::failbit);
597 return os;
598 }
599 }
600 // Else T type is a user defined data type (e.g. MyData)
601 else
602 {
603 return write(os, (serialize::I*)&t_);
604 }
605#endif
606 }
607
613 template <class T>
614 std::ostream& write(std::ostream& os, std::vector<T>& container)
615 {
616 static_assert(!serialize_traits::is_shared_ptr<T>::value, "Type T must not be a shared_ptr type");
617
618 uint16_t size = static_cast<uint16_t>(container.size());
619 write_type(os, Type::VECTOR);
620 write(os, size, false);
621 if (check_stream(os) && check_container_size(os, size))
622 {
623 for (const auto& item : container)
624 {
625 write(os, item, false);
626 }
627 }
628 return os;
629 }
630
636 template <class T>
637 std::istream& read(std::istream& is, std::vector<T>& container)
638 {
639 static_assert(!serialize_traits::is_shared_ptr<T>::value, "Type T must not be a shared_ptr type");
640
641 if (check_stop_parse(is))
642 return is;
643
644 container.clear();
645 if (read_type(is, Type::VECTOR))
646 {
647 uint16_t size = 0;
648 read(is, size, false);
649 if (check_stream(is) && check_container_size(is, size))
650 {
651 parseStatus(typeid(container), size);
652 for (uint16_t i = 0; i < size; ++i)
653 {
654 T t;
655 read(is, t, false);
656 container.push_back(t);
657 }
658 }
659 }
660 return is;
661 }
662
668 template <class T>
669 std::ostream& write(std::ostream& os, std::vector<T*>& container)
670 {
671 static_assert(std::is_base_of<serialize::I, T>::value, "Type T must be derived from serialize::I");
672
673 uint16_t size = static_cast<uint16_t>(container.size());
674 write_type(os, Type::VECTOR);
675 write(os, size, false);
676
677 if (check_stream(os) && check_container_size(os, size))
678 {
679 for (auto* ptr : container)
680 {
681 if (ptr != nullptr)
682 {
683 bool notNULL = true;
684 write(os, notNULL, false);
685
686 auto* i = static_cast<I*>(ptr);
687 write(os, i);
688 }
689 else
690 {
691 bool notNULL = false;
692 write(os, notNULL, false);
693 }
694 }
695
696 }
697 return os;
698 }
699
705 template <class T>
706 std::istream& read(std::istream& is, std::vector<T*>& container)
707 {
708 static_assert(std::is_base_of<serialize::I, T>::value, "Type T must be derived from serialize::I");
709
710 if (check_stop_parse(is))
711 return is;
712
713 container.clear();
714 if (read_type(is, Type::VECTOR))
715 {
716 uint16_t size = 0;
717 read(is, size, false);
718 if (check_stream(is) && check_container_size(is, size))
719 {
720 parseStatus(typeid(container), size);
721 for (uint16_t i = 0; i < size; ++i)
722 {
723 bool notNULL = false;
724 read(is, notNULL, false);
725
726 if (notNULL)
727 {
728 T *object = new T;
729 auto *i = static_cast<I*>(object);
730 read(is, i);
731 container.push_back(object);
732 }
733 else
734 {
735 container.push_back(nullptr);
736 }
737 }
738 }
739 }
740 return is;
741 }
742
748 template <class K, class V, class P>
749 std::ostream& write(std::ostream& os, std::map<K, V, P>& container)
750 {
751 static_assert(!serialize_traits::is_shared_ptr<V>::value, "Type V must not be a shared_ptr type");
752
753 uint16_t size = static_cast<uint16_t>(container.size());
754 write_type(os, Type::MAP);
755 write(os, size, false);
756 if (check_stream(os) && check_container_size(os, size))
757 {
758 for (const auto& entry : container)
759 {
760 write(os, entry.first, false);
761 write(os, entry.second, false);
762 }
763 }
764 return os;
765 }
766
772 template <class K, class V, class P>
773 std::istream& read(std::istream& is, std::map<K, V, P>& container)
774 {
775 static_assert(!serialize_traits::is_shared_ptr<V>::value, "Type V must not be a shared_ptr type");
776
777 if (check_stop_parse(is))
778 return is;
779
780 container.clear();
781 if (read_type(is, Type::MAP))
782 {
783 uint16_t size = 0;
784 read(is, size, false);
785 if (check_stream(is) && check_container_size(is, size))
786 {
787 parseStatus(typeid(container), size);
788 for (uint16_t i = 0; i < size; ++i)
789 {
790 K key;
791 V value;
792 read(is, key, false);
793
794 read(is, value, false);
795 container[key] = value;
796 }
797 }
798 }
799 return is;
800 }
801
807 template <class K, class V, class P>
808 std::ostream& write(std::ostream& os, std::map<K, V*, P>& container)
809 {
810 static_assert(std::is_base_of<serialize::I, V>::value, "Type V must be derived from serialize::I");
811
812 uint16_t size = static_cast<uint16_t>(container.size());
813 write_type(os, Type::MAP);
814 write(os, size, false);
815
816 if (check_stream(os) && check_container_size(os, size))
817 {
818 for (auto& entry : container)
819 {
820 write(os, entry.first, false);
821
822 if (entry.second != nullptr)
823 {
824 bool notNULL = true;
825 write(os, notNULL, false);
826
827 auto* i = static_cast<I*>(entry.second);
828 write(os, i);
829 }
830 else
831 {
832 bool notNULL = false;
833 write(os, notNULL, false);
834 }
835 }
836 }
837 return os;
838 }
839
845 template <class K, class V, class P>
846 std::istream& read(std::istream& is, std::map<K, V*, P>& container)
847 {
848 static_assert(std::is_base_of<serialize::I, V>::value, "Type V must be derived from serialize::I");
849
850 if (check_stop_parse(is))
851 return is;
852
853 container.clear();
854 if (read_type(is, Type::MAP))
855 {
856 uint16_t size = 0;
857 read(is, size, false);
858 if (check_stream(is) && check_container_size(is, size))
859 {
860 parseStatus(typeid(container), size);
861 for (uint16_t i = 0; i < size; ++i)
862 {
863 K key;
864 read(is, key, false);
865 bool notNULL;
866 read(is, notNULL, false);
867 if (notNULL)
868 {
869 V *object = new V;
870 auto *i = static_cast<I*>(object);
871 read(is, i);
872 container[key] = (V*) object;
873 }
874 else
875 {
876 container[key] = nullptr;
877 }
878 }
879 }
880 }
881 return is;
882 }
883
889 template <class T, class P>
890 std::ostream& write(std::ostream& os, std::set<T, P>& container)
891 {
892 static_assert(!serialize_traits::is_shared_ptr<T>::value, "Type T must not be a shared_ptr type");
893
894 uint16_t size = static_cast<uint16_t>(container.size());
895 write_type(os, Type::SET);
896 write(os, size, false);
897
898 if (check_stream(os) && check_container_size(os, size))
899 {
900 for (const auto& item : container)
901 {
902 write(os, item, false);
903 }
904 }
905 return os;
906 }
907
913 template <class T, class P>
914 std::istream& read(std::istream& is, std::set<T, P>& container)
915 {
916 static_assert(!serialize_traits::is_shared_ptr<T>::value, "Type T must not be a shared_ptr type");
917
918 if (check_stop_parse(is))
919 return is;
920
921 container.clear();
922 if (read_type(is, Type::SET))
923 {
924 uint16_t size = 0;
925 read(is, size, false);
926 if (check_stream(is) && check_container_size(is, size))
927 {
928 parseStatus(typeid(container), size);
929 for (uint16_t i = 0; i < size; ++i)
930 {
931 T t;
932 read(is, t, false);
933 container.insert(t);
934 }
935 }
936 }
937 return is;
938 }
939
945 template <class T, class P>
946 std::ostream& write(std::ostream& os, std::set<T*, P>& container)
947 {
948 static_assert(std::is_base_of<serialize::I, T>::value, "Type T must be derived from serialize::I");
949
950 uint16_t size = static_cast<uint16_t>(container.size());
951 write_type(os, Type::SET);
952 write(os, size, false);
953 if (check_stream(os) && check_container_size(os, size))
954 {
955 for (auto ptr : container)
956 {
957 if (ptr != nullptr)
958 {
959 bool notNULL = true;
960 write(os, notNULL, false);
961
962 auto* i = static_cast<I*>(ptr);
963 write(os, i);
964 }
965 else
966 {
967 bool notNULL = false;
968 write(os, notNULL, false);
969 }
970 }
971 }
972 return os;
973 }
974
980 template <class T, class P>
981 std::istream& read(std::istream& is, std::set<T*, P>& container)
982 {
983 static_assert(std::is_base_of<serialize::I, T>::value, "Type T must be derived from serialize::I");
984
985 if (check_stop_parse(is))
986 return is;
987
988 container.clear();
989 if (read_type(is, Type::SET))
990 {
991 uint16_t size = 0;
992 read(is, size, false);
993 if (check_stream(is) && check_container_size(is, size))
994 {
995 parseStatus(typeid(container), size);
996 for (uint16_t i = 0; i < size; ++i)
997 {
998 bool notNULL = false;
999 read(is, notNULL, false);
1000 if (notNULL)
1001 {
1002 T *object = new T;
1003 auto *i = static_cast<I*>(object);
1004 read(is, i);
1005 container.insert(object);
1006 }
1007 else
1008 {
1009 container.insert(nullptr);
1010 }
1011 }
1012 }
1013 }
1014 return is;
1015 }
1016
1022 template <class T>
1023 std::ostream& write(std::ostream& os, std::list<T>& container)
1024 {
1025 static_assert(!serialize_traits::is_shared_ptr<T>::value, "Type T must not be a shared_ptr type");
1026
1027 uint16_t size = static_cast<uint16_t>(container.size());
1028 write_type(os, Type::LIST);
1029 write(os, size, false);
1030
1031 if (check_stream(os) && check_container_size(os, size))
1032 {
1033 for (const auto& item : container)
1034 {
1035 write(os, item, false);
1036 }
1037 }
1038 return os;
1039 }
1040
1046 template <class T>
1047 std::istream& read(std::istream& is, std::list<T>& container)
1048 {
1049 static_assert(!serialize_traits::is_shared_ptr<T>::value, "Type T must not be a shared_ptr type");
1050
1051 if (check_stop_parse(is))
1052 return is;
1053
1054 container.clear();
1055 if (read_type(is, Type::LIST))
1056 {
1057 uint16_t size = 0;
1058 read(is, size, false);
1059 if (check_stream(is) && check_container_size(is, size))
1060 {
1061 parseStatus(typeid(container), size);
1062 for (uint16_t i = 0; i < size; ++i)
1063 {
1064 T t;
1065 read(is, t, false);
1066 container.push_back(t);
1067 }
1068 }
1069 }
1070 return is;
1071 }
1072
1078 template <class T>
1079 std::ostream& write(std::ostream& os, std::list<T*>& container)
1080 {
1081 static_assert(std::is_base_of<serialize::I, T>::value, "Type T must be derived from serialize::I");
1082
1083 uint16_t size = static_cast<uint16_t>(container.size());
1084 write_type(os, Type::LIST);
1085 write(os, size, false);
1086
1087 if (check_stream(os) && check_container_size(os, size))
1088 {
1089 for (auto* ptr : container)
1090 {
1091 if (ptr != nullptr)
1092 {
1093 bool notNULL = true;
1094 write(os, notNULL, false);
1095
1096 auto* i = static_cast<I*>(ptr);
1097 write(os, i);
1098 }
1099 else
1100 {
1101 bool notNULL = false;
1102 write(os, notNULL, false);
1103 }
1104 }
1105 }
1106 return os;
1107 }
1108
1114 template <class T>
1115 std::istream& read(std::istream& is, std::list<T*>& container)
1116 {
1117 static_assert(std::is_base_of<serialize::I, T>::value, "Type T must be derived from serialize::I");
1118
1119 if (check_stop_parse(is))
1120 return is;
1121
1122 container.clear();
1123 if (read_type(is, Type::LIST))
1124 {
1125 uint16_t size = 0;
1126 read(is, size, false);
1127 if (check_stream(is) && check_container_size(is, size))
1128 {
1129 parseStatus(typeid(container), size);
1130 for (uint16_t i = 0; i < size; ++i)
1131 {
1132 bool notNULL = false;
1133 read(is, notNULL, false);
1134 if (notNULL)
1135 {
1136 T *object = new T;
1137 auto *i = static_cast<I*>(object);
1138 read(is, i);
1139 container.push_back(object);
1140 }
1141 else
1142 {
1143 container.push_back(nullptr);
1144 }
1145 }
1146 }
1147 }
1148 return is;
1149 }
1150
1151 typedef void (*ErrorHandler)(ParsingError error, int line, const char* file);
1152 void setErrorHandler(ErrorHandler error_handler_)
1153 {
1154 error_handler = error_handler_;
1155 }
1156
1157 ParsingError getLastError() const { return lastError; }
1158 void clearLastError() { lastError = ParsingError::NONE; }
1159
1160 typedef void (*ParseHandler)(const std::type_info& typeId, size_t size);
1161 void setParseHandler(ParseHandler parse_handler_)
1162 {
1163 parse_handler = parse_handler_;
1164 }
1165
1166private:
1174 std::istream& read_internal(std::istream& is, char* p, uint32_t size, bool no_swap = false)
1175 {
1176 if (check_stop_parse(is))
1177 {
1178 return is;
1179 }
1180
1181 if (!check_pointer(is, p))
1182 {
1183 return is;
1184 }
1185 if (LE() && !no_swap)
1186 {
1187 // If little endian, read as little endian
1188 for (int i = size - 1; i >= 0; --i)
1189 {
1190 is.read(p + i, 1);
1191 }
1192 }
1193 else
1194 {
1195 // Read as big endian
1196 is.read(p, size);
1197 }
1198
1199 return is;
1200 }
1201
1209 std::ostream& write_internal(std::ostream& os, const char* p, uint32_t size, bool no_swap = false)
1210 {
1211 if (!check_pointer(os, p))
1212 {
1213 return os;
1214 }
1215 if (LE() && !no_swap)
1216 {
1217 // If little endian, write as little endian
1218 for (int i = size - 1; i >= 0; --i)
1219 {
1220 os.write(p + i, 1);
1221 }
1222 }
1223 else
1224 {
1225 // Write as big endian
1226 os.write(p, size);
1227 }
1228 return os;
1229 }
1230
1231 // Maximum sizes allowed by parser
1232 static const uint16_t MAX_STRING_SIZE = 256;
1233 static const uint16_t MAX_CONTAINER_SIZE = 200;
1234
1235 // Keep wchar_t serialize size consistent on any platform
1236 static const size_t WCHAR_SIZE = 2;
1237
1238 // Used to stop parsing early if not enough data to continue
1239 std::list<std::streampos> stopParsePosStack;
1240
1241 ErrorHandler error_handler = nullptr;
1242 ParsingError lastError = ParsingError::NONE;
1243 void raiseError(ParsingError error, int line, const char* file)
1244 {
1245 lastError = error;
1246 if (error_handler)
1247 error_handler(error, line, file);
1248 }
1249
1250 ParseHandler parse_handler = nullptr;
1251 void parseStatus(const std::type_info& typeId, size_t size = 0)
1252 {
1253 if (parse_handler)
1254 parse_handler(typeId, size);
1255 }
1256
1257 void write_type(std::ostream& os, Type type_)
1258 {
1259 uint8_t type = static_cast<uint8_t>(type_);
1260 write_internal(os, (const char*) &type, sizeof(type));
1261 }
1262
1263 bool read_type(std::istream& is, Type type_)
1264 {
1265 Type type = static_cast<Type>(is.peek());
1266 if (type == type_)
1267 {
1268 uint8_t typeByte = 0;
1269 read_internal(is, (char*) &typeByte, sizeof(typeByte));
1270 return true;
1271 }
1272 else
1273 {
1274 raiseError(ParsingError::TYPE_MISMATCH, __LINE__, __FILE__);
1275 is.setstate(std::ios::failbit);
1276 return false;
1277 }
1278 }
1279
1280 bool check_stream(std::ios& stream)
1281 {
1282 if (!stream.good())
1283 {
1284 raiseError(ParsingError::STREAM_ERROR, __LINE__, __FILE__);
1285 stream.setstate(std::ios::failbit);
1286 }
1287 return stream.good();
1288 }
1289
1290 bool check_slength(std::ios& stream, int stringSize)
1291 {
1292 bool sizeOk = stringSize <= MAX_STRING_SIZE;
1293 if (!sizeOk)
1294 {
1295 raiseError(ParsingError::STRING_TOO_LONG, __LINE__, __FILE__);
1296 stream.setstate(std::ios::failbit);
1297 }
1298 if (stringSize == 0)
1299 return false;
1300 return sizeOk;
1301 }
1302
1303 bool check_container_size(std::ios& stream, int containerSize)
1304 {
1305 bool sizeOk = containerSize <= MAX_CONTAINER_SIZE;
1306 if (!sizeOk)
1307 {
1308 raiseError(ParsingError::CONTAINER_TOO_MANY, __LINE__, __FILE__);
1309 stream.setstate(std::ios::failbit);
1310 }
1311 return sizeOk;
1312 }
1313
1314 bool check_pointer(std::ios& stream, const void* ptr)
1315 {
1316 if (!ptr)
1317 {
1318 raiseError(ParsingError::INVALID_INPUT, __LINE__, __FILE__);
1319 stream.setstate(std::ios::failbit);
1320 }
1321 return ptr != NULL;
1322 }
1323
1324 void push_stop_parse_pos(std::streampos stopParsePos)
1325 {
1326 stopParsePosStack.push_front(stopParsePos);
1327 }
1328
1329 std::streampos pop_stop_parse_pos()
1330 {
1331 std::streampos stopParsePos = stopParsePosStack.front();
1332 stopParsePosStack.pop_front();
1333 return stopParsePos;
1334 }
1335
1336 bool check_stop_parse(std::istream& is)
1337 {
1338 if (is.eof())
1339 {
1340 raiseError(ParsingError::END_OF_FILE, __LINE__, __FILE__);
1341 return true;
1342 }
1343 if (stopParsePosStack.size() > 0)
1344 {
1345 std::streampos stopParsePos = stopParsePosStack.front();
1346 if (is.tellg() >= stopParsePos)
1347 {
1348 return true;
1349 }
1350 }
1351 return false;
1352 }
1353};
1354
1355#endif // _SERIALIZE_H
Abstract interface that all serialized user defined classes inherit.
Definition msg_serialize.h:109
virtual std::ostream & write(serialize &ms, std::ostream &os)=0
virtual std::istream & read(serialize &ms, std::istream &is)=0
The serialize class binary serializes and deserializes C++ objects.
Definition msg_serialize.h:105
std::ostream & write(std::ostream &os, char *str)
Definition msg_serialize.h:435
void writeEndian(std::ostream &os)
Definition msg_serialize.h:181
std::ostream & write(std::ostream &os, std::set< T, P > &container)
Definition msg_serialize.h:890
bool LE()
Definition msg_serialize.h:160
std::istream & read(std::istream &is, std::vector< bool > &container)
Definition msg_serialize.h:320
std::istream & read(std::istream &is, std::wstring &s)
Definition msg_serialize.h:262
std::istream & read(std::istream &is, std::map< K, V *, P > &container)
Definition msg_serialize.h:846
std::istream & read(std::istream &is, char *str)
Definition msg_serialize.h:291
std::ostream & write(std::ostream &os, const std::wstring &s)
Definition msg_serialize.h:405
std::ostream & write(std::ostream &os, std::map< K, V *, P > &container)
Definition msg_serialize.h:808
void setParseHandler(ParseHandler parse_handler_)
Definition msg_serialize.h:1161
std::ostream & write(std::ostream &os, const std::string &s)
Definition msg_serialize.h:380
void clearLastError()
Definition msg_serialize.h:1158
std::ostream & write(std::ostream &os, std::wstring &s)
Definition msg_serialize.h:426
~serialize()=default
std::ostream & write(std::ostream &os, std::vector< T * > &container)
Definition msg_serialize.h:669
std::istream & read(std::istream &is, std::set< T, P > &container)
Definition msg_serialize.h:914
std::ostream & write(std::ostream &os, T &t_, bool prependType=true)
Definition msg_serialize.h:540
std::istream & read(std::istream &is, std::list< T * > &container)
Definition msg_serialize.h:1115
std::ostream & write(std::ostream &os, std::vector< T > &container)
Definition msg_serialize.h:614
std::ostream & write(std::ostream &os, std::list< T > &container)
Definition msg_serialize.h:1023
std::ostream & write(std::ostream &os, std::set< T *, P > &container)
Definition msg_serialize.h:946
Type
Definition msg_serialize.h:131
std::ostream & write(std::ostream &os, std::map< K, V, P > &container)
Definition msg_serialize.h:749
void setErrorHandler(ErrorHandler error_handler_)
Definition msg_serialize.h:1152
std::ostream & write(std::ostream &os, std::vector< bool > &container)
Definition msg_serialize.h:467
std::istream & read(std::istream &is, T &t_, bool readPrependedType=true)
Definition msg_serialize.h:487
std::ostream & write(std::ostream &os, std::string &s)
Definition msg_serialize.h:396
std::istream & read(std::istream &is, std::set< T *, P > &container)
Definition msg_serialize.h:981
std::istream & read(std::istream &is, std::vector< T > &container)
Definition msg_serialize.h:637
std::ostream & write(std::ostream &os, std::list< T * > &container)
Definition msg_serialize.h:1079
void(*) ParseHandler(const std::type_info &typeId, size_t size)
Definition msg_serialize.h:1160
ParsingError getLastError() const
Definition msg_serialize.h:1157
std::istream & read(std::istream &is, std::string &s)
Definition msg_serialize.h:239
std::istream & read(std::istream &is, I *t_)
Definition msg_serialize.h:195
std::istream & readEndian(std::istream &is, bool &littleEndian)
Definition msg_serialize.h:170
std::ostream & write(std::ostream &os, I *t_)
Definition msg_serialize.h:349
void(*) ErrorHandler(ParsingError error, int line, const char *file)
Definition msg_serialize.h:1151
ParsingError
Definition msg_serialize.h:145
std::istream & read(std::istream &is, std::vector< T * > &container)
Definition msg_serialize.h:706
std::istream & read(std::istream &is, std::map< K, V, P > &container)
Definition msg_serialize.h:773
std::istream & read(std::istream &is, std::list< T > &container)
Definition msg_serialize.h:1047
std::ostream & write(std::ostream &os, const char *str)
Definition msg_serialize.h:444
serialize()=default
Definition msg_serialize.h:21
Definition msg_serialize.h:23
Definition msg_serialize.h:29