DelegateMQ
Loading...
Searching...
No Matches
msg_serialize.h
Go to the documentation of this file.
1
34
35#ifndef _MSG_SERIALIZE_H
36#define _MSG_SERIALIZE_H
37
38#include <stdint.h>
39#include <string.h>
40#include <type_traits>
41#include <typeinfo>
42#include <iostream>
43#include <memory>
44#include <vector>
45#include <list>
46#include <map>
47#include <set>
48#include <string>
49
51{
52 template <typename T>
53 struct is_shared_ptr : std::false_type {};
54
55 template <typename T>
56 struct is_shared_ptr<std::shared_ptr<T>> : std::true_type {};
57
58 template <typename U>
59 struct is_unsupported_container : std::false_type {};
60}
61
62// Define to enable compile-time checking of unsupported container types
63// Undefine for less compile-time include file dependencies
64#define CHECK_UNSUPPORTED_CONTAINER
65#ifdef CHECK_UNSUPPORTED_CONTAINER
66
67#include <deque>
68#include <forward_list>
69#include <queue>
70#include <stack>
71#include <unordered_set>
72#include <unordered_map>
73
74 template <typename U>
75 struct serialize_traits::is_unsupported_container<std::multiset<U>> : std::true_type {};
76
77 template <typename U, typename V>
78 struct serialize_traits::is_unsupported_container<std::pair<U, V>> : std::true_type {};
79
80 template <typename T, typename Alloc>
81 struct serialize_traits::is_unsupported_container<std::deque<T, Alloc>> : std::true_type {};
82
83 template <typename T, typename Alloc>
84 struct serialize_traits::is_unsupported_container<std::forward_list<T, Alloc>> : std::true_type {};
85
86 template <typename T, typename Alloc>
87 struct serialize_traits::is_unsupported_container<std::priority_queue<T, std::vector<T, Alloc>>> : std::true_type {};
88
89 template <typename T, typename Alloc>
90 struct serialize_traits::is_unsupported_container<std::queue<T, Alloc>> : std::true_type {};
91
92 template <typename T, typename Alloc>
93 struct serialize_traits::is_unsupported_container<std::stack<T, Alloc>> : std::true_type {};
94
95 template <typename T, typename Hash, typename KeyEqual, typename Alloc>
96 struct serialize_traits::is_unsupported_container<std::unordered_multiset<T, Hash, KeyEqual, Alloc>> : std::true_type {};
97
98 template <typename Key, typename T, typename Hash, typename KeyEqual, typename Alloc>
99 struct serialize_traits::is_unsupported_container<std::unordered_map<Key, T, Hash, KeyEqual, Alloc>> : std::true_type {};
100
101 template <typename Key, typename T, typename Hash, typename KeyEqual, typename Alloc>
102 struct serialize_traits::is_unsupported_container<std::unordered_multimap<Key, T, Hash, KeyEqual, Alloc>> : std::true_type {};
103#endif // CHECK_UNSUPPORTED_CONTAINER
104
135{
136public:
138 class I
139 {
140 public:
148 virtual std::ostream& write(serialize& ms, std::ostream& os) = 0;
149
157 virtual std::istream& read(serialize& ms, std::istream& is) = 0;
158 };
159
160 enum class Type
161 {
162 UNKNOWN = 0,
163 LITERAL = 1,
164 STRING = 8,
165 WSTRING = 9,
166 VECTOR = 20,
167 MAP = 21,
168 LIST = 22,
169 SET = 23,
170 ENDIAN = 30,
171 USER_DEFINED = 31,
172 };
173
184
185 serialize() = default;
186 ~serialize() = default;
187
190 bool LE()
191 {
192 const static int n = 1;
193 const static bool le= (* (char *)&n == 1);
194 return le;
195 }
196
200 std::istream& readEndian(std::istream& is, bool& littleEndian)
201 {
202 if (read_type(is, Type::ENDIAN))
203 {
204 is.read((char*) &littleEndian, sizeof(littleEndian));
205 }
206 return is;
207 }
208
211 void writeEndian(std::ostream& os)
212 {
213 bool littleEndian = LE();
214 write_type(os, Type::ENDIAN);
215 os.write((const char*) &littleEndian, sizeof(littleEndian));
216 }
217
225 std::istream& read (std::istream& is, I* t_)
226 {
227 if (check_stop_parse(is))
228 return is;
229
230 if (check_pointer(is, t_))
231 {
232 if (read_type(is, Type::USER_DEFINED))
233 {
234 uint16_t size = 0;
235 std::streampos startPos = is.tellg();
236
237 read(is, size, false);
238
239 // Save the stop parsing position to prevent parsing overrun
240 push_stop_parse_pos(startPos + std::streampos(size));
241
242 t_->read(*this, is);
243
244 pop_stop_parse_pos();
245
246 if (is.good())
247 {
248 std::streampos endPos = is.tellg();
249 uint16_t rcvdSize = static_cast<uint16_t>(endPos - startPos);
250
251 // Did sender send a larger object than what receiver parsed?
252 if (rcvdSize < size)
253 {
254 // Skip over the extra received data
255 uint16_t seekOffset = size - rcvdSize;
256 is.seekg(seekOffset, std::ios_base::cur);
257 }
258 }
259 return is;
260 }
261 }
262 return is;
263 }
264
269 std::istream& read (std::istream& is, std::string& s)
270 {
271 if (check_stop_parse(is))
272 return is;
273
274 if (read_type(is, Type::STRING))
275 {
276 uint16_t size = 0;
277 read(is, size, false);
278 if (check_stream(is) && check_slength(is, size))
279 {
280 s.resize(size);
281 parseStatus(typeid(s), s.size());
282 read_internal(is, const_cast<char*>(s.c_str()), size, true);
283 }
284 }
285 return is;
286 }
287
292 std::istream& read (std::istream& is, std::wstring& s)
293 {
294 if (check_stop_parse(is))
295 return is;
296
297 if (read_type(is, Type::WSTRING))
298 {
299 uint16_t size = 0;
300 read(is, size, false);
301 if (check_stream(is) && check_slength(is, size))
302 {
303 s.resize(size);
304 parseStatus(typeid(s), s.size());
305 for (uint16_t ii = 0; ii < size; ii++)
306 {
307 wchar_t c;
308 int offset = sizeof(wchar_t) - WCHAR_SIZE;
309 read_internal(is, reinterpret_cast<char*>(&c) + offset, WCHAR_SIZE);
310 s[ii] = c;
311 }
312 }
313 }
314 return is;
315 }
316
321 std::istream& read (std::istream& is, char* str)
322 {
323 if (check_stop_parse(is))
324 return is;
325
326 if (read_type(is, Type::STRING))
327 {
328 uint16_t size = 0;
329 read(is, size, false);
330 if (check_stream(is) && check_slength(is, size))
331 {
332 if (check_pointer(is, str))
333 {
334 parseStatus(typeid(str), size);
335 read_internal(is, str, size, true);
336 }
337 }
338 }
339 return is;
340 }
341
350 std::istream& read (std::istream& is, std::vector<bool>& container)
351 {
352 if (check_stop_parse(is))
353 return is;
354
355 container.clear();
356 if (read_type(is, Type::VECTOR))
357 {
358 uint16_t size = 0;
359 read(is, size, false);
360 if (check_stream(is) && check_container_size(is, size))
361 {
362 parseStatus(typeid(container), size);
363 for (uint16_t i = 0; i < size; ++i)
364 {
365 bool t;
366 read(is, t);
367 container.push_back(t);
368 }
369 }
370 }
371 return is;
372 }
373
379 std::ostream& write (std::ostream& os, I* t_)
380 {
381 if (check_pointer(os, t_))
382 {
383 uint16_t elementSize = 0;
384
385 write_type(os, Type::USER_DEFINED);
386 std::streampos elementSizePos = os.tellp();
387 write(os, elementSize, false);
388
389 // Write user defined object
390 t_->write(*this, os);
391
392 if (os.good())
393 {
394 // Write user defined object size into stream
395 std::streampos currentPos = os.tellp();
396 os.seekp(elementSizePos);
397 elementSize = static_cast<uint16_t>(currentPos - elementSizePos);
398 write(os, elementSize, false);
399 os.seekp(currentPos);
400 }
401 return os;
402 }
403 return os;
404 }
405
410 std::ostream& write(std::ostream& os, const std::string& s)
411 {
412 uint16_t size = static_cast<uint16_t>(s.size());
413 write_type(os, Type::STRING);
414 write(os, size, false);
415 if (check_stream(os) && check_slength(os, size))
416 {
417 write_internal(os, s.c_str(), size, true);
418 }
419 return os;
420 }
421
426 std::ostream& write(std::ostream& os, std::string& s)
427 {
428 return write(os, static_cast<const std::string&>(s));
429 }
430
435 std::ostream& write (std::ostream& os, const std::wstring& s)
436 {
437 uint16_t size = static_cast<uint16_t>(s.size());
438 write_type(os, Type::WSTRING);
439 write(os, size, false);
440 if (check_stream(os) && check_slength(os, size))
441 {
442 for (uint16_t ii = 0; ii < size; ii++)
443 {
444 wchar_t c = s[ii];
445 int offset = sizeof(wchar_t) - WCHAR_SIZE;
446 write_internal(os, reinterpret_cast<char*>(&c) + offset, WCHAR_SIZE);
447 }
448 }
449 return os;
450 }
451
456 std::ostream& write (std::ostream& os, std::wstring& s)
457 {
458 return write(os, static_cast<const std::wstring&>(s));
459 }
460
465 std::ostream& write(std::ostream& os, char* str)
466 {
467 return write(os, static_cast<const char*>(str));
468 }
469
474 std::ostream& write (std::ostream& os, const char* str)
475 {
476 if (check_pointer(os, str))
477 {
478 uint16_t size = static_cast<uint16_t>(strlen(str)) + 1;
479 write_type(os, Type::STRING);
480 write(os, size, false);
481 if (check_stream(os) && check_slength(os, size))
482 {
483 write_internal (os, str, size, true);
484 }
485 }
486 return os;
487 }
488
497 std::ostream& write (std::ostream& os, std::vector<bool>& container)
498 {
499 uint16_t size = static_cast<uint16_t>(container.size());
500 write_type(os, Type::VECTOR);
501 write(os, size, false);
502 if (check_stream(os) && check_container_size(os, size))
503 {
504 for (const bool& c : container)
505 {
506 write(os, c);
507 }
508 }
509 return os;
510 }
511
516 template<typename T>
517 std::istream& read(std::istream& is, T &t_, bool readPrependedType = true)
518 {
519 static_assert(!serialize_traits::is_unsupported_container<T>::value, "Unsupported C++ container type");
520
521 static_assert(!(std::is_pointer<T>::value &&
522 (std::is_arithmetic<typename std::remove_pointer<T>::type>::value ||
523 std::is_class<typename std::remove_pointer<T>::type>::value)),
524 "T cannot be a pointer to a built-in or custom data type");
525
526 if (check_stop_parse(is))
527 return is;
528
529 // Is T a built-in data type (e.g. float, int, ...)?
530 if (std::is_class<T>::value == false)
531 {
532 // Is T is not a pointer type
533 if (std::is_pointer<T>::value == false)
534 {
535 if (readPrependedType)
536 {
537 if(!read_type(is, Type::LITERAL))
538 {
539 return is;
540 }
541 }
542
543 if (readPrependedType)
544 parseStatus(typeid(t_));
545 read_internal(is, (char*)&t_, sizeof (t_));
546 return is;
547 }
548 else
549 {
550 // Can't read pointers to built-in type
551 raiseError(ParsingError::INVALID_INPUT, __LINE__, __FILE__);
552 is.setstate(std::ios::failbit);
553 return is;
554 }
555 }
556 // Else T is a user defined data type (e.g. MyData)
557 else
558 {
559 parseStatus(typeid(t_));
560 read(is, (serialize::I*)&t_);
561 return is;
562 }
563 }
564
569 template<typename T>
570 std::ostream& write(std::ostream& os, T &t_, bool prependType = true)
571 {
572 static_assert(!serialize_traits::is_unsupported_container<T>::value, "Unsupported C++ container type");
573
574 static_assert(!(std::is_pointer<T>::value &&
575 (std::is_arithmetic<typename std::remove_pointer<T>::type>::value ||
576 std::is_class<typename std::remove_pointer<T>::type>::value)),
577 "T cannot be a pointer to a built-in or custom data type");
578
579 // If C++17 or higher
580#if defined(_MSVC_LANG) && _MSVC_LANG >= 201703L || __cplusplus >= 201703L
581 // Check if T is a user-defined class
582 if constexpr (std::is_class<T>::value)
583 {
584 // Ensure that the class T inherits from serialize::I
585 static_assert(std::is_base_of<serialize::I, T>::value, "T must inherit from serialize::I");
586
587 // Proceed with serialization for user-defined type
588 return write(os, (serialize::I*)&t_);
589 }
590 else
591 {
592 // If T is not a class, handle built-in data types
593 if (std::is_pointer<T>::value == false)
594 {
595 if (prependType)
596 {
597 write_type(os, Type::LITERAL);
598 }
599 return write_internal(os, (const char*)&t_, sizeof(t_));
600 }
601 else
602 {
603 // Can't write pointers to built-in types
604 raiseError(ParsingError::INVALID_INPUT, __LINE__, __FILE__);
605 os.setstate(std::ios::failbit);
606 return os;
607 }
608 }
609#else
610 // Is T type a built-in data type (e.g. float, int, ...)?
611 if (std::is_class<T>::value == false)
612 {
613 // Is T is not a pointer type
614 if (std::is_pointer<T>::value == false)
615 {
616 if (prependType)
617 {
618 write_type(os, Type::LITERAL);
619 }
620 return write_internal(os, (const char*)&t_, sizeof(t_));
621 }
622 else
623 {
624 // Can't write pointers to built-in type
625 raiseError(ParsingError::INVALID_INPUT, __LINE__, __FILE__);
626 os.setstate(std::ios::failbit);
627 return os;
628 }
629 }
630 // Else T type is a user defined data type (e.g. MyData)
631 else
632 {
633 return write(os, (serialize::I*)&t_);
634 }
635#endif
636 }
637
643 template <class T>
644 std::ostream& write(std::ostream& os, std::vector<T>& container)
645 {
646 static_assert(!serialize_traits::is_shared_ptr<T>::value, "Type T must not be a shared_ptr type");
647
648 uint16_t size = static_cast<uint16_t>(container.size());
649 write_type(os, Type::VECTOR);
650 write(os, size, false);
651 if (check_stream(os) && check_container_size(os, size))
652 {
653 for (const auto& item : container)
654 {
655 write(os, item, false);
656 }
657 }
658 return os;
659 }
660
666 template <class T>
667 std::istream& read(std::istream& is, std::vector<T>& container)
668 {
669 static_assert(!serialize_traits::is_shared_ptr<T>::value, "Type T must not be a shared_ptr type");
670
671 if (check_stop_parse(is))
672 return is;
673
674 container.clear();
675 if (read_type(is, Type::VECTOR))
676 {
677 uint16_t size = 0;
678 read(is, size, false);
679 if (check_stream(is) && check_container_size(is, size))
680 {
681 parseStatus(typeid(container), size);
682 for (uint16_t i = 0; i < size; ++i)
683 {
684 T t;
685 read(is, t, false);
686 container.push_back(t);
687 }
688 }
689 }
690 return is;
691 }
692
698 template <class T>
699 std::ostream& write(std::ostream& os, std::vector<T*>& container)
700 {
701 static_assert(std::is_base_of<serialize::I, T>::value, "Type T must be derived from serialize::I");
702
703 uint16_t size = static_cast<uint16_t>(container.size());
704 write_type(os, Type::VECTOR);
705 write(os, size, false);
706
707 if (check_stream(os) && check_container_size(os, size))
708 {
709 for (auto* ptr : container)
710 {
711 if (ptr != nullptr)
712 {
713 bool notNULL = true;
714 write(os, notNULL, false);
715
716 auto* i = static_cast<I*>(ptr);
717 write(os, i);
718 }
719 else
720 {
721 bool notNULL = false;
722 write(os, notNULL, false);
723 }
724 }
725
726 }
727 return os;
728 }
729
735 template <class T>
736 std::istream& read(std::istream& is, std::vector<T*>& container)
737 {
738 static_assert(std::is_base_of<serialize::I, T>::value, "Type T must be derived from serialize::I");
739
740 if (check_stop_parse(is))
741 return is;
742
743 container.clear();
744 if (read_type(is, Type::VECTOR))
745 {
746 uint16_t size = 0;
747 read(is, size, false);
748 if (check_stream(is) && check_container_size(is, size))
749 {
750 parseStatus(typeid(container), size);
751 for (uint16_t i = 0; i < size; ++i)
752 {
753 bool notNULL = false;
754 read(is, notNULL, false);
755
756 if (notNULL)
757 {
758 T *object = new T;
759 auto *i = static_cast<I*>(object);
760 read(is, i);
761 container.push_back(object);
762 }
763 else
764 {
765 container.push_back(nullptr);
766 }
767 }
768 }
769 }
770 return is;
771 }
772
778 template <class K, class V, class P>
779 std::ostream& write(std::ostream& os, std::map<K, V, P>& container)
780 {
781 static_assert(!serialize_traits::is_shared_ptr<V>::value, "Type V must not be a shared_ptr type");
782
783 uint16_t size = static_cast<uint16_t>(container.size());
784 write_type(os, Type::MAP);
785 write(os, size, false);
786 if (check_stream(os) && check_container_size(os, size))
787 {
788 for (const auto& entry : container)
789 {
790 write(os, entry.first, false);
791 write(os, entry.second, false);
792 }
793 }
794 return os;
795 }
796
802 template <class K, class V, class P>
803 std::istream& read(std::istream& is, std::map<K, V, P>& container)
804 {
805 static_assert(!serialize_traits::is_shared_ptr<V>::value, "Type V must not be a shared_ptr type");
806
807 if (check_stop_parse(is))
808 return is;
809
810 container.clear();
811 if (read_type(is, Type::MAP))
812 {
813 uint16_t size = 0;
814 read(is, size, false);
815 if (check_stream(is) && check_container_size(is, size))
816 {
817 parseStatus(typeid(container), size);
818 for (uint16_t i = 0; i < size; ++i)
819 {
820 K key;
821 V value;
822 read(is, key, false);
823
824 read(is, value, false);
825 container[key] = value;
826 }
827 }
828 }
829 return is;
830 }
831
837 template <class K, class V, class P>
838 std::ostream& write(std::ostream& os, std::map<K, V*, P>& container)
839 {
840 static_assert(std::is_base_of<serialize::I, V>::value, "Type V must be derived from serialize::I");
841
842 uint16_t size = static_cast<uint16_t>(container.size());
843 write_type(os, Type::MAP);
844 write(os, size, false);
845
846 if (check_stream(os) && check_container_size(os, size))
847 {
848 for (auto& entry : container)
849 {
850 write(os, entry.first, false);
851
852 if (entry.second != nullptr)
853 {
854 bool notNULL = true;
855 write(os, notNULL, false);
856
857 auto* i = static_cast<I*>(entry.second);
858 write(os, i);
859 }
860 else
861 {
862 bool notNULL = false;
863 write(os, notNULL, false);
864 }
865 }
866 }
867 return os;
868 }
869
875 template <class K, class V, class P>
876 std::istream& read(std::istream& is, std::map<K, V*, P>& container)
877 {
878 static_assert(std::is_base_of<serialize::I, V>::value, "Type V must be derived from serialize::I");
879
880 if (check_stop_parse(is))
881 return is;
882
883 container.clear();
884 if (read_type(is, Type::MAP))
885 {
886 uint16_t size = 0;
887 read(is, size, false);
888 if (check_stream(is) && check_container_size(is, size))
889 {
890 parseStatus(typeid(container), size);
891 for (uint16_t i = 0; i < size; ++i)
892 {
893 K key;
894 read(is, key, false);
895 bool notNULL;
896 read(is, notNULL, false);
897 if (notNULL)
898 {
899 V *object = new V;
900 auto *i = static_cast<I*>(object);
901 read(is, i);
902 container[key] = (V*) object;
903 }
904 else
905 {
906 container[key] = nullptr;
907 }
908 }
909 }
910 }
911 return is;
912 }
913
919 template <class T, class P>
920 std::ostream& write(std::ostream& os, std::set<T, P>& container)
921 {
922 static_assert(!serialize_traits::is_shared_ptr<T>::value, "Type T must not be a shared_ptr type");
923
924 uint16_t size = static_cast<uint16_t>(container.size());
925 write_type(os, Type::SET);
926 write(os, size, false);
927
928 if (check_stream(os) && check_container_size(os, size))
929 {
930 for (const auto& item : container)
931 {
932 write(os, item, false);
933 }
934 }
935 return os;
936 }
937
943 template <class T, class P>
944 std::istream& read(std::istream& is, std::set<T, P>& container)
945 {
946 static_assert(!serialize_traits::is_shared_ptr<T>::value, "Type T must not be a shared_ptr type");
947
948 if (check_stop_parse(is))
949 return is;
950
951 container.clear();
952 if (read_type(is, Type::SET))
953 {
954 uint16_t size = 0;
955 read(is, size, false);
956 if (check_stream(is) && check_container_size(is, size))
957 {
958 parseStatus(typeid(container), size);
959 for (uint16_t i = 0; i < size; ++i)
960 {
961 T t;
962 read(is, t, false);
963 container.insert(t);
964 }
965 }
966 }
967 return is;
968 }
969
975 template <class T, class P>
976 std::ostream& write(std::ostream& os, std::set<T*, P>& container)
977 {
978 static_assert(std::is_base_of<serialize::I, T>::value, "Type T must be derived from serialize::I");
979
980 uint16_t size = static_cast<uint16_t>(container.size());
981 write_type(os, Type::SET);
982 write(os, size, false);
983 if (check_stream(os) && check_container_size(os, size))
984 {
985 for (auto ptr : container)
986 {
987 if (ptr != nullptr)
988 {
989 bool notNULL = true;
990 write(os, notNULL, false);
991
992 auto* i = static_cast<I*>(ptr);
993 write(os, i);
994 }
995 else
996 {
997 bool notNULL = false;
998 write(os, notNULL, false);
999 }
1000 }
1001 }
1002 return os;
1003 }
1004
1010 template <class T, class P>
1011 std::istream& read(std::istream& is, std::set<T*, P>& container)
1012 {
1013 static_assert(std::is_base_of<serialize::I, T>::value, "Type T must be derived from serialize::I");
1014
1015 if (check_stop_parse(is))
1016 return is;
1017
1018 container.clear();
1019 if (read_type(is, Type::SET))
1020 {
1021 uint16_t size = 0;
1022 read(is, size, false);
1023 if (check_stream(is) && check_container_size(is, size))
1024 {
1025 parseStatus(typeid(container), size);
1026 for (uint16_t i = 0; i < size; ++i)
1027 {
1028 bool notNULL = false;
1029 read(is, notNULL, false);
1030 if (notNULL)
1031 {
1032 T *object = new T;
1033 auto *i = static_cast<I*>(object);
1034 read(is, i);
1035 container.insert(object);
1036 }
1037 else
1038 {
1039 container.insert(nullptr);
1040 }
1041 }
1042 }
1043 }
1044 return is;
1045 }
1046
1052 template <class T>
1053 std::ostream& write(std::ostream& os, std::list<T>& container)
1054 {
1055 static_assert(!serialize_traits::is_shared_ptr<T>::value, "Type T must not be a shared_ptr type");
1056
1057 uint16_t size = static_cast<uint16_t>(container.size());
1058 write_type(os, Type::LIST);
1059 write(os, size, false);
1060
1061 if (check_stream(os) && check_container_size(os, size))
1062 {
1063 for (const auto& item : container)
1064 {
1065 write(os, item, false);
1066 }
1067 }
1068 return os;
1069 }
1070
1076 template <class T>
1077 std::istream& read(std::istream& is, std::list<T>& container)
1078 {
1079 static_assert(!serialize_traits::is_shared_ptr<T>::value, "Type T must not be a shared_ptr type");
1080
1081 if (check_stop_parse(is))
1082 return is;
1083
1084 container.clear();
1085 if (read_type(is, Type::LIST))
1086 {
1087 uint16_t size = 0;
1088 read(is, size, false);
1089 if (check_stream(is) && check_container_size(is, size))
1090 {
1091 parseStatus(typeid(container), size);
1092 for (uint16_t i = 0; i < size; ++i)
1093 {
1094 T t;
1095 read(is, t, false);
1096 container.push_back(t);
1097 }
1098 }
1099 }
1100 return is;
1101 }
1102
1108 template <class T>
1109 std::ostream& write(std::ostream& os, std::list<T*>& container)
1110 {
1111 static_assert(std::is_base_of<serialize::I, T>::value, "Type T must be derived from serialize::I");
1112
1113 uint16_t size = static_cast<uint16_t>(container.size());
1114 write_type(os, Type::LIST);
1115 write(os, size, false);
1116
1117 if (check_stream(os) && check_container_size(os, size))
1118 {
1119 for (auto* ptr : container)
1120 {
1121 if (ptr != nullptr)
1122 {
1123 bool notNULL = true;
1124 write(os, notNULL, false);
1125
1126 auto* i = static_cast<I*>(ptr);
1127 write(os, i);
1128 }
1129 else
1130 {
1131 bool notNULL = false;
1132 write(os, notNULL, false);
1133 }
1134 }
1135 }
1136 return os;
1137 }
1138
1144 template <class T>
1145 std::istream& read(std::istream& is, std::list<T*>& container)
1146 {
1147 static_assert(std::is_base_of<serialize::I, T>::value, "Type T must be derived from serialize::I");
1148
1149 if (check_stop_parse(is))
1150 return is;
1151
1152 container.clear();
1153 if (read_type(is, Type::LIST))
1154 {
1155 uint16_t size = 0;
1156 read(is, size, false);
1157 if (check_stream(is) && check_container_size(is, size))
1158 {
1159 parseStatus(typeid(container), size);
1160 for (uint16_t i = 0; i < size; ++i)
1161 {
1162 bool notNULL = false;
1163 read(is, notNULL, false);
1164 if (notNULL)
1165 {
1166 T *object = new T;
1167 auto *i = static_cast<I*>(object);
1168 read(is, i);
1169 container.push_back(object);
1170 }
1171 else
1172 {
1173 container.push_back(nullptr);
1174 }
1175 }
1176 }
1177 }
1178 return is;
1179 }
1180
1181 typedef void (*ErrorHandler)(ParsingError error, int line, const char* file);
1182 void setErrorHandler(ErrorHandler error_handler_)
1183 {
1184 error_handler = error_handler_;
1185 }
1186
1187 ParsingError getLastError() const { return lastError; }
1188 void clearLastError() { lastError = ParsingError::NONE; }
1189
1190 typedef void (*ParseHandler)(const std::type_info& typeId, size_t size);
1191 void setParseHandler(ParseHandler parse_handler_)
1192 {
1193 parse_handler = parse_handler_;
1194 }
1195
1196private:
1204 std::istream& read_internal(std::istream& is, char* p, uint32_t size, bool no_swap = false)
1205 {
1206 if (check_stop_parse(is))
1207 {
1208 return is;
1209 }
1210
1211 if (!check_pointer(is, p))
1212 {
1213 return is;
1214 }
1215 if (LE() && !no_swap)
1216 {
1217 // If little endian, read as little endian
1218 for (int i = size - 1; i >= 0; --i)
1219 {
1220 is.read(p + i, 1);
1221 }
1222 }
1223 else
1224 {
1225 // Read as big endian
1226 is.read(p, size);
1227 }
1228
1229 return is;
1230 }
1231
1239 std::ostream& write_internal(std::ostream& os, const char* p, uint32_t size, bool no_swap = false)
1240 {
1241 if (!check_pointer(os, p))
1242 {
1243 return os;
1244 }
1245 if (LE() && !no_swap)
1246 {
1247 // If little endian, write as little endian
1248 for (int i = size - 1; i >= 0; --i)
1249 {
1250 os.write(p + i, 1);
1251 }
1252 }
1253 else
1254 {
1255 // Write as big endian
1256 os.write(p, size);
1257 }
1258 return os;
1259 }
1260
1261 // Maximum sizes allowed by parser
1262 static const uint16_t MAX_STRING_SIZE = 256;
1263 static const uint16_t MAX_CONTAINER_SIZE = 200;
1264
1265 // Keep wchar_t serialize size consistent on any platform
1266 static const size_t WCHAR_SIZE = 2;
1267
1268 // Used to stop parsing early if not enough data to continue
1269 std::list<std::streampos> stopParsePosStack;
1270
1271 ErrorHandler error_handler = nullptr;
1272 ParsingError lastError = ParsingError::NONE;
1273 void raiseError(ParsingError error, int line, const char* file)
1274 {
1275 lastError = error;
1276 if (error_handler)
1277 error_handler(error, line, file);
1278 }
1279
1280 ParseHandler parse_handler = nullptr;
1281 void parseStatus(const std::type_info& typeId, size_t size = 0)
1282 {
1283 if (parse_handler)
1284 parse_handler(typeId, size);
1285 }
1286
1287 void write_type(std::ostream& os, Type type_)
1288 {
1289 uint8_t type = static_cast<uint8_t>(type_);
1290 write_internal(os, (const char*) &type, sizeof(type));
1291 }
1292
1293 bool read_type(std::istream& is, Type type_)
1294 {
1295 Type type = static_cast<Type>(is.peek());
1296 if (type == type_)
1297 {
1298 uint8_t typeByte = 0;
1299 read_internal(is, (char*) &typeByte, sizeof(typeByte));
1300 return true;
1301 }
1302 else
1303 {
1304 raiseError(ParsingError::TYPE_MISMATCH, __LINE__, __FILE__);
1305 is.setstate(std::ios::failbit);
1306 return false;
1307 }
1308 }
1309
1310 bool check_stream(std::ios& stream)
1311 {
1312 if (!stream.good())
1313 {
1314 raiseError(ParsingError::STREAM_ERROR, __LINE__, __FILE__);
1315 stream.setstate(std::ios::failbit);
1316 }
1317 return stream.good();
1318 }
1319
1320 bool check_slength(std::ios& stream, int stringSize)
1321 {
1322 bool sizeOk = stringSize <= MAX_STRING_SIZE;
1323 if (!sizeOk)
1324 {
1325 raiseError(ParsingError::STRING_TOO_LONG, __LINE__, __FILE__);
1326 stream.setstate(std::ios::failbit);
1327 }
1328 if (stringSize == 0)
1329 return false;
1330 return sizeOk;
1331 }
1332
1333 bool check_container_size(std::ios& stream, int containerSize)
1334 {
1335 bool sizeOk = containerSize <= MAX_CONTAINER_SIZE;
1336 if (!sizeOk)
1337 {
1338 raiseError(ParsingError::CONTAINER_TOO_MANY, __LINE__, __FILE__);
1339 stream.setstate(std::ios::failbit);
1340 }
1341 return sizeOk;
1342 }
1343
1344 bool check_pointer(std::ios& stream, const void* ptr)
1345 {
1346 if (!ptr)
1347 {
1348 raiseError(ParsingError::INVALID_INPUT, __LINE__, __FILE__);
1349 stream.setstate(std::ios::failbit);
1350 }
1351 return ptr != NULL;
1352 }
1353
1354 void push_stop_parse_pos(std::streampos stopParsePos)
1355 {
1356 stopParsePosStack.push_front(stopParsePos);
1357 }
1358
1359 std::streampos pop_stop_parse_pos()
1360 {
1361 std::streampos stopParsePos = stopParsePosStack.front();
1362 stopParsePosStack.pop_front();
1363 return stopParsePos;
1364 }
1365
1366 bool check_stop_parse(std::istream& is)
1367 {
1368 if (is.eof())
1369 {
1370 raiseError(ParsingError::END_OF_FILE, __LINE__, __FILE__);
1371 return true;
1372 }
1373 if (stopParsePosStack.size() > 0)
1374 {
1375 std::streampos stopParsePos = stopParsePosStack.front();
1376 if (is.tellg() >= stopParsePos)
1377 {
1378 return true;
1379 }
1380 }
1381 return false;
1382 }
1383};
1384
1385#endif // _SERIALIZE_H
Abstract interface that all serialized user defined classes inherit.
Definition msg_serialize.h:139
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:135
std::ostream & write(std::ostream &os, char *str)
Definition msg_serialize.h:465
void writeEndian(std::ostream &os)
Definition msg_serialize.h:211
std::ostream & write(std::ostream &os, std::set< T, P > &container)
Definition msg_serialize.h:920
bool LE()
Definition msg_serialize.h:190
std::istream & read(std::istream &is, std::vector< bool > &container)
Definition msg_serialize.h:350
std::istream & read(std::istream &is, std::wstring &s)
Definition msg_serialize.h:292
std::istream & read(std::istream &is, std::map< K, V *, P > &container)
Definition msg_serialize.h:876
std::istream & read(std::istream &is, char *str)
Definition msg_serialize.h:321
std::ostream & write(std::ostream &os, const std::wstring &s)
Definition msg_serialize.h:435
std::ostream & write(std::ostream &os, std::map< K, V *, P > &container)
Definition msg_serialize.h:838
void setParseHandler(ParseHandler parse_handler_)
Definition msg_serialize.h:1191
std::ostream & write(std::ostream &os, const std::string &s)
Definition msg_serialize.h:410
void clearLastError()
Definition msg_serialize.h:1188
std::ostream & write(std::ostream &os, std::wstring &s)
Definition msg_serialize.h:456
~serialize()=default
std::ostream & write(std::ostream &os, std::vector< T * > &container)
Definition msg_serialize.h:699
std::istream & read(std::istream &is, std::set< T, P > &container)
Definition msg_serialize.h:944
std::ostream & write(std::ostream &os, T &t_, bool prependType=true)
Definition msg_serialize.h:570
std::istream & read(std::istream &is, std::list< T * > &container)
Definition msg_serialize.h:1145
std::ostream & write(std::ostream &os, std::vector< T > &container)
Definition msg_serialize.h:644
std::ostream & write(std::ostream &os, std::list< T > &container)
Definition msg_serialize.h:1053
std::ostream & write(std::ostream &os, std::set< T *, P > &container)
Definition msg_serialize.h:976
Type
Definition msg_serialize.h:161
std::ostream & write(std::ostream &os, std::map< K, V, P > &container)
Definition msg_serialize.h:779
void setErrorHandler(ErrorHandler error_handler_)
Definition msg_serialize.h:1182
std::ostream & write(std::ostream &os, std::vector< bool > &container)
Definition msg_serialize.h:497
std::istream & read(std::istream &is, T &t_, bool readPrependedType=true)
Definition msg_serialize.h:517
std::ostream & write(std::ostream &os, std::string &s)
Definition msg_serialize.h:426
std::istream & read(std::istream &is, std::set< T *, P > &container)
Definition msg_serialize.h:1011
std::istream & read(std::istream &is, std::vector< T > &container)
Definition msg_serialize.h:667
std::ostream & write(std::ostream &os, std::list< T * > &container)
Definition msg_serialize.h:1109
void(*) ParseHandler(const std::type_info &typeId, size_t size)
Definition msg_serialize.h:1190
ParsingError getLastError() const
Definition msg_serialize.h:1187
std::istream & read(std::istream &is, std::string &s)
Definition msg_serialize.h:269
std::istream & read(std::istream &is, I *t_)
Definition msg_serialize.h:225
std::istream & readEndian(std::istream &is, bool &littleEndian)
Definition msg_serialize.h:200
std::ostream & write(std::ostream &os, I *t_)
Definition msg_serialize.h:379
void(*) ErrorHandler(ParsingError error, int line, const char *file)
Definition msg_serialize.h:1181
ParsingError
Definition msg_serialize.h:175
std::istream & read(std::istream &is, std::vector< T * > &container)
Definition msg_serialize.h:736
std::istream & read(std::istream &is, std::map< K, V, P > &container)
Definition msg_serialize.h:803
std::istream & read(std::istream &is, std::list< T > &container)
Definition msg_serialize.h:1077
std::ostream & write(std::ostream &os, const char *str)
Definition msg_serialize.h:474
serialize()=default
Definition msg_serialize.h:51
Definition msg_serialize.h:53
Definition msg_serialize.h:59