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 // Is T type a built-in data type (e.g. float, int, ...)?
550 if (std::is_class<T>::value == false)
551 {
552 // Is T is not a pointer type
553 if (std::is_pointer<T>::value == false)
554 {
555 if (prependType)
556 {
557 write_type(os, Type::LITERAL);
558 }
559 return write_internal(os, (const char*)&t_, sizeof(t_));
560 }
561 else
562 {
563 // Can't write pointers to built-in type
564 raiseError(ParsingError::INVALID_INPUT, __LINE__, __FILE__);
565 os.setstate(std::ios::failbit);
566 return os;
567 }
568 }
569 // Else T type is a user defined data type (e.g. MyData)
570 else
571 {
572 return write(os, (serialize::I*)&t_);
573 }
574 }
575
581 template <class T>
582 std::ostream& write(std::ostream& os, std::vector<T>& container)
583 {
584 static_assert(!serialize_traits::is_shared_ptr<T>::value, "Type T must not be a shared_ptr type");
585
586 uint16_t size = static_cast<uint16_t>(container.size());
587 write_type(os, Type::VECTOR);
588 write(os, size, false);
589 if (check_stream(os) && check_container_size(os, size))
590 {
591 for (const auto& item : container)
592 {
593 write(os, item, false);
594 }
595 }
596 return os;
597 }
598
604 template <class T>
605 std::istream& read(std::istream& is, std::vector<T>& container)
606 {
607 static_assert(!serialize_traits::is_shared_ptr<T>::value, "Type T must not be a shared_ptr type");
608
609 if (check_stop_parse(is))
610 return is;
611
612 container.clear();
613 if (read_type(is, Type::VECTOR))
614 {
615 uint16_t size = 0;
616 read(is, size, false);
617 if (check_stream(is) && check_container_size(is, size))
618 {
619 parseStatus(typeid(container), size);
620 for (uint16_t i = 0; i < size; ++i)
621 {
622 T t;
623 read(is, t, false);
624 container.push_back(t);
625 }
626 }
627 }
628 return is;
629 }
630
636 template <class T>
637 std::ostream& write(std::ostream& os, std::vector<T*>& container)
638 {
639 static_assert(std::is_base_of<serialize::I, T>::value, "Type T must be derived from serialize::I");
640
641 uint16_t size = static_cast<uint16_t>(container.size());
642 write_type(os, Type::VECTOR);
643 write(os, size, false);
644
645 if (check_stream(os) && check_container_size(os, size))
646 {
647 for (auto* ptr : container)
648 {
649 if (ptr != nullptr)
650 {
651 bool notNULL = true;
652 write(os, notNULL, false);
653
654 auto* i = static_cast<I*>(ptr);
655 write(os, i);
656 }
657 else
658 {
659 bool notNULL = false;
660 write(os, notNULL, false);
661 }
662 }
663
664 }
665 return os;
666 }
667
673 template <class T>
674 std::istream& read(std::istream& is, std::vector<T*>& container)
675 {
676 static_assert(std::is_base_of<serialize::I, T>::value, "Type T must be derived from serialize::I");
677
678 if (check_stop_parse(is))
679 return is;
680
681 container.clear();
682 if (read_type(is, Type::VECTOR))
683 {
684 uint16_t size = 0;
685 read(is, size, false);
686 if (check_stream(is) && check_container_size(is, size))
687 {
688 parseStatus(typeid(container), size);
689 for (uint16_t i = 0; i < size; ++i)
690 {
691 bool notNULL = false;
692 read(is, notNULL, false);
693
694 if (notNULL)
695 {
696 T *object = new T;
697 auto *i = static_cast<I*>(object);
698 read(is, i);
699 container.push_back(object);
700 }
701 else
702 {
703 container.push_back(nullptr);
704 }
705 }
706 }
707 }
708 return is;
709 }
710
716 template <class K, class V, class P>
717 std::ostream& write(std::ostream& os, std::map<K, V, P>& container)
718 {
719 static_assert(!serialize_traits::is_shared_ptr<V>::value, "Type V must not be a shared_ptr type");
720
721 uint16_t size = static_cast<uint16_t>(container.size());
722 write_type(os, Type::MAP);
723 write(os, size, false);
724 if (check_stream(os) && check_container_size(os, size))
725 {
726 for (const auto& entry : container)
727 {
728 write(os, entry.first, false);
729 write(os, entry.second, false);
730 }
731 }
732 return os;
733 }
734
740 template <class K, class V, class P>
741 std::istream& read(std::istream& is, std::map<K, V, P>& container)
742 {
743 static_assert(!serialize_traits::is_shared_ptr<V>::value, "Type V must not be a shared_ptr type");
744
745 if (check_stop_parse(is))
746 return is;
747
748 container.clear();
749 if (read_type(is, Type::MAP))
750 {
751 uint16_t size = 0;
752 read(is, size, false);
753 if (check_stream(is) && check_container_size(is, size))
754 {
755 parseStatus(typeid(container), size);
756 for (uint16_t i = 0; i < size; ++i)
757 {
758 K key;
759 V value;
760 read(is, key, false);
761
762 read(is, value, false);
763 container[key] = value;
764 }
765 }
766 }
767 return is;
768 }
769
775 template <class K, class V, class P>
776 std::ostream& write(std::ostream& os, std::map<K, V*, P>& container)
777 {
778 static_assert(std::is_base_of<serialize::I, V>::value, "Type V must be derived from serialize::I");
779
780 uint16_t size = static_cast<uint16_t>(container.size());
781 write_type(os, Type::MAP);
782 write(os, size, false);
783
784 if (check_stream(os) && check_container_size(os, size))
785 {
786 for (auto& entry : container)
787 {
788 write(os, entry.first, false);
789
790 if (entry.second != nullptr)
791 {
792 bool notNULL = true;
793 write(os, notNULL, false);
794
795 auto* i = static_cast<I*>(entry.second);
796 write(os, i);
797 }
798 else
799 {
800 bool notNULL = false;
801 write(os, notNULL, false);
802 }
803 }
804 }
805 return os;
806 }
807
813 template <class K, class V, class P>
814 std::istream& read(std::istream& is, std::map<K, V*, P>& container)
815 {
816 static_assert(std::is_base_of<serialize::I, V>::value, "Type V must be derived from serialize::I");
817
818 if (check_stop_parse(is))
819 return is;
820
821 container.clear();
822 if (read_type(is, Type::MAP))
823 {
824 uint16_t size = 0;
825 read(is, size, false);
826 if (check_stream(is) && check_container_size(is, size))
827 {
828 parseStatus(typeid(container), size);
829 for (uint16_t i = 0; i < size; ++i)
830 {
831 K key;
832 read(is, key, false);
833 bool notNULL;
834 read(is, notNULL, false);
835 if (notNULL)
836 {
837 V *object = new V;
838 auto *i = static_cast<I*>(object);
839 read(is, i);
840 container[key] = (V*) object;
841 }
842 else
843 {
844 container[key] = nullptr;
845 }
846 }
847 }
848 }
849 return is;
850 }
851
857 template <class T, class P>
858 std::ostream& write(std::ostream& os, std::set<T, P>& container)
859 {
860 static_assert(!serialize_traits::is_shared_ptr<T>::value, "Type T must not be a shared_ptr type");
861
862 uint16_t size = static_cast<uint16_t>(container.size());
863 write_type(os, Type::SET);
864 write(os, size, false);
865
866 if (check_stream(os) && check_container_size(os, size))
867 {
868 for (const auto& item : container)
869 {
870 write(os, item, false);
871 }
872 }
873 return os;
874 }
875
881 template <class T, class P>
882 std::istream& read(std::istream& is, std::set<T, P>& container)
883 {
884 static_assert(!serialize_traits::is_shared_ptr<T>::value, "Type T must not be a shared_ptr type");
885
886 if (check_stop_parse(is))
887 return is;
888
889 container.clear();
890 if (read_type(is, Type::SET))
891 {
892 uint16_t size = 0;
893 read(is, size, false);
894 if (check_stream(is) && check_container_size(is, size))
895 {
896 parseStatus(typeid(container), size);
897 for (uint16_t i = 0; i < size; ++i)
898 {
899 T t;
900 read(is, t, false);
901 container.insert(t);
902 }
903 }
904 }
905 return is;
906 }
907
913 template <class T, class P>
914 std::ostream& write(std::ostream& os, std::set<T*, P>& container)
915 {
916 static_assert(std::is_base_of<serialize::I, T>::value, "Type T must be derived from serialize::I");
917
918 uint16_t size = static_cast<uint16_t>(container.size());
919 write_type(os, Type::SET);
920 write(os, size, false);
921 if (check_stream(os) && check_container_size(os, size))
922 {
923 for (auto ptr : container)
924 {
925 if (ptr != nullptr)
926 {
927 bool notNULL = true;
928 write(os, notNULL, false);
929
930 auto* i = static_cast<I*>(ptr);
931 write(os, i);
932 }
933 else
934 {
935 bool notNULL = false;
936 write(os, notNULL, false);
937 }
938 }
939 }
940 return os;
941 }
942
948 template <class T, class P>
949 std::istream& read(std::istream& is, std::set<T*, P>& container)
950 {
951 static_assert(std::is_base_of<serialize::I, T>::value, "Type T must be derived from serialize::I");
952
953 if (check_stop_parse(is))
954 return is;
955
956 container.clear();
957 if (read_type(is, Type::SET))
958 {
959 uint16_t size = 0;
960 read(is, size, false);
961 if (check_stream(is) && check_container_size(is, size))
962 {
963 parseStatus(typeid(container), size);
964 for (uint16_t i = 0; i < size; ++i)
965 {
966 bool notNULL = false;
967 read(is, notNULL, false);
968 if (notNULL)
969 {
970 T *object = new T;
971 auto *i = static_cast<I*>(object);
972 read(is, i);
973 container.insert(object);
974 }
975 else
976 {
977 container.insert(nullptr);
978 }
979 }
980 }
981 }
982 return is;
983 }
984
990 template <class T>
991 std::ostream& write(std::ostream& os, std::list<T>& container)
992 {
993 static_assert(!serialize_traits::is_shared_ptr<T>::value, "Type T must not be a shared_ptr type");
994
995 uint16_t size = static_cast<uint16_t>(container.size());
996 write_type(os, Type::LIST);
997 write(os, size, false);
998
999 if (check_stream(os) && check_container_size(os, size))
1000 {
1001 for (const auto& item : container)
1002 {
1003 write(os, item, false);
1004 }
1005 }
1006 return os;
1007 }
1008
1014 template <class T>
1015 std::istream& read(std::istream& is, std::list<T>& container)
1016 {
1017 static_assert(!serialize_traits::is_shared_ptr<T>::value, "Type T must not be a shared_ptr type");
1018
1019 if (check_stop_parse(is))
1020 return is;
1021
1022 container.clear();
1023 if (read_type(is, Type::LIST))
1024 {
1025 uint16_t size = 0;
1026 read(is, size, false);
1027 if (check_stream(is) && check_container_size(is, size))
1028 {
1029 parseStatus(typeid(container), size);
1030 for (uint16_t i = 0; i < size; ++i)
1031 {
1032 T t;
1033 read(is, t, false);
1034 container.push_back(t);
1035 }
1036 }
1037 }
1038 return is;
1039 }
1040
1046 template <class T>
1047 std::ostream& write(std::ostream& os, std::list<T*>& container)
1048 {
1049 static_assert(std::is_base_of<serialize::I, T>::value, "Type T must be derived from serialize::I");
1050
1051 uint16_t size = static_cast<uint16_t>(container.size());
1052 write_type(os, Type::LIST);
1053 write(os, size, false);
1054
1055 if (check_stream(os) && check_container_size(os, size))
1056 {
1057 for (auto* ptr : container)
1058 {
1059 if (ptr != nullptr)
1060 {
1061 bool notNULL = true;
1062 write(os, notNULL, false);
1063
1064 auto* i = static_cast<I*>(ptr);
1065 write(os, i);
1066 }
1067 else
1068 {
1069 bool notNULL = false;
1070 write(os, notNULL, false);
1071 }
1072 }
1073 }
1074 return os;
1075 }
1076
1082 template <class T>
1083 std::istream& read(std::istream& is, std::list<T*>& container)
1084 {
1085 static_assert(std::is_base_of<serialize::I, T>::value, "Type T must be derived from serialize::I");
1086
1087 if (check_stop_parse(is))
1088 return is;
1089
1090 container.clear();
1091 if (read_type(is, Type::LIST))
1092 {
1093 uint16_t size = 0;
1094 read(is, size, false);
1095 if (check_stream(is) && check_container_size(is, size))
1096 {
1097 parseStatus(typeid(container), size);
1098 for (uint16_t i = 0; i < size; ++i)
1099 {
1100 bool notNULL = false;
1101 read(is, notNULL, false);
1102 if (notNULL)
1103 {
1104 T *object = new T;
1105 auto *i = static_cast<I*>(object);
1106 read(is, i);
1107 container.push_back(object);
1108 }
1109 else
1110 {
1111 container.push_back(nullptr);
1112 }
1113 }
1114 }
1115 }
1116 return is;
1117 }
1118
1119 typedef void (*ErrorHandler)(ParsingError error, int line, const char* file);
1120 void setErrorHandler(ErrorHandler error_handler_)
1121 {
1122 error_handler = error_handler_;
1123 }
1124
1125 ParsingError getLastError() const { return lastError; }
1126 void clearLastError() { lastError = ParsingError::NONE; }
1127
1128 typedef void (*ParseHandler)(const std::type_info& typeId, size_t size);
1129 void setParseHandler(ParseHandler parse_handler_)
1130 {
1131 parse_handler = parse_handler_;
1132 }
1133
1134private:
1142 std::istream& read_internal(std::istream& is, char* p, uint32_t size, bool no_swap = false)
1143 {
1144 if (check_stop_parse(is))
1145 {
1146 return is;
1147 }
1148
1149 if (!check_pointer(is, p))
1150 {
1151 return is;
1152 }
1153 if (LE() && !no_swap)
1154 {
1155 // If little endian, read as little endian
1156 for (int i = size - 1; i >= 0; --i)
1157 {
1158 is.read(p + i, 1);
1159 }
1160 }
1161 else
1162 {
1163 // Read as big endian
1164 is.read(p, size);
1165 }
1166
1167 return is;
1168 }
1169
1177 std::ostream& write_internal(std::ostream& os, const char* p, uint32_t size, bool no_swap = false)
1178 {
1179 if (!check_pointer(os, p))
1180 {
1181 return os;
1182 }
1183 if (LE() && !no_swap)
1184 {
1185 // If little endian, write as little endian
1186 for (int i = size - 1; i >= 0; --i)
1187 {
1188 os.write(p + i, 1);
1189 }
1190 }
1191 else
1192 {
1193 // Write as big endian
1194 os.write(p, size);
1195 }
1196 return os;
1197 }
1198
1199 // Maximum sizes allowed by parser
1200 static const uint16_t MAX_STRING_SIZE = 256;
1201 static const uint16_t MAX_CONTAINER_SIZE = 200;
1202
1203 // Keep wchar_t serialize size consistent on any platform
1204 static const size_t WCHAR_SIZE = 2;
1205
1206 // Used to stop parsing early if not enough data to continue
1207 std::list<std::streampos> stopParsePosStack;
1208
1209 ErrorHandler error_handler = nullptr;
1210 ParsingError lastError = ParsingError::NONE;
1211 void raiseError(ParsingError error, int line, const char* file)
1212 {
1213 lastError = error;
1214 if (error_handler)
1215 error_handler(error, line, file);
1216 }
1217
1218 ParseHandler parse_handler = nullptr;
1219 void parseStatus(const std::type_info& typeId, size_t size = 0)
1220 {
1221 if (parse_handler)
1222 parse_handler(typeId, size);
1223 }
1224
1225 void write_type(std::ostream& os, Type type_)
1226 {
1227 uint8_t type = static_cast<uint8_t>(type_);
1228 write_internal(os, (const char*) &type, sizeof(type));
1229 }
1230
1231 bool read_type(std::istream& is, Type type_)
1232 {
1233 Type type = static_cast<Type>(is.peek());
1234 if (type == type_)
1235 {
1236 uint8_t typeByte = 0;
1237 read_internal(is, (char*) &typeByte, sizeof(typeByte));
1238 return true;
1239 }
1240 else
1241 {
1242 raiseError(ParsingError::TYPE_MISMATCH, __LINE__, __FILE__);
1243 is.setstate(std::ios::failbit);
1244 return false;
1245 }
1246 }
1247
1248 bool check_stream(std::ios& stream)
1249 {
1250 if (!stream.good())
1251 {
1252 raiseError(ParsingError::STREAM_ERROR, __LINE__, __FILE__);
1253 stream.setstate(std::ios::failbit);
1254 }
1255 return stream.good();
1256 }
1257
1258 bool check_slength(std::ios& stream, int stringSize)
1259 {
1260 bool sizeOk = stringSize <= MAX_STRING_SIZE;
1261 if (!sizeOk)
1262 {
1263 raiseError(ParsingError::STRING_TOO_LONG, __LINE__, __FILE__);
1264 stream.setstate(std::ios::failbit);
1265 }
1266 if (stringSize == 0)
1267 return false;
1268 return sizeOk;
1269 }
1270
1271 bool check_container_size(std::ios& stream, int containerSize)
1272 {
1273 bool sizeOk = containerSize <= MAX_CONTAINER_SIZE;
1274 if (!sizeOk)
1275 {
1276 raiseError(ParsingError::CONTAINER_TOO_MANY, __LINE__, __FILE__);
1277 stream.setstate(std::ios::failbit);
1278 }
1279 return sizeOk;
1280 }
1281
1282 bool check_pointer(std::ios& stream, const void* ptr)
1283 {
1284 if (!ptr)
1285 {
1286 raiseError(ParsingError::INVALID_INPUT, __LINE__, __FILE__);
1287 stream.setstate(std::ios::failbit);
1288 }
1289 return ptr != NULL;
1290 }
1291
1292 void push_stop_parse_pos(std::streampos stopParsePos)
1293 {
1294 stopParsePosStack.push_front(stopParsePos);
1295 }
1296
1297 std::streampos pop_stop_parse_pos()
1298 {
1299 std::streampos stopParsePos = stopParsePosStack.front();
1300 stopParsePosStack.pop_front();
1301 return stopParsePos;
1302 }
1303
1304 bool check_stop_parse(std::istream& is)
1305 {
1306 if (is.eof())
1307 {
1308 raiseError(ParsingError::END_OF_FILE, __LINE__, __FILE__);
1309 return true;
1310 }
1311 if (stopParsePosStack.size() > 0)
1312 {
1313 std::streampos stopParsePos = stopParsePosStack.front();
1314 if (is.tellg() >= stopParsePos)
1315 {
1316 return true;
1317 }
1318 }
1319 return false;
1320 }
1321};
1322
1323#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:858
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:814
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:776
void setParseHandler(ParseHandler parse_handler_)
Definition msg_serialize.h:1129
std::ostream & write(std::ostream &os, const std::string &s)
Definition msg_serialize.h:380
void clearLastError()
Definition msg_serialize.h:1126
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:637
std::istream & read(std::istream &is, std::set< T, P > &container)
Definition msg_serialize.h:882
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:1083
std::ostream & write(std::ostream &os, std::vector< T > &container)
Definition msg_serialize.h:582
std::ostream & write(std::ostream &os, std::list< T > &container)
Definition msg_serialize.h:991
std::ostream & write(std::ostream &os, std::set< T *, P > &container)
Definition msg_serialize.h:914
Type
Definition msg_serialize.h:131
std::ostream & write(std::ostream &os, std::map< K, V, P > &container)
Definition msg_serialize.h:717
void setErrorHandler(ErrorHandler error_handler_)
Definition msg_serialize.h:1120
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:949
std::istream & read(std::istream &is, std::vector< T > &container)
Definition msg_serialize.h:605
std::ostream & write(std::ostream &os, std::list< T * > &container)
Definition msg_serialize.h:1047
void(*) ParseHandler(const std::type_info &typeId, size_t size)
Definition msg_serialize.h:1128
ParsingError getLastError() const
Definition msg_serialize.h:1125
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:1119
ParsingError
Definition msg_serialize.h:145
std::istream & read(std::istream &is, std::vector< T * > &container)
Definition msg_serialize.h:674
std::istream & read(std::istream &is, std::map< K, V, P > &container)
Definition msg_serialize.h:741
std::istream & read(std::istream &is, std::list< T > &container)
Definition msg_serialize.h:1015
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