serializationinfo.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2005-2008 by Dr. Marc Boris Duerner
3  * Copyright (C) 2011 by Tommi Maekitalo
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * As a special exception, you may use this file as part of a free
11  * software library without restriction. Specifically, if other files
12  * instantiate templates or use macros or inline functions from this
13  * file, or you compile this file and link it with other files to
14  * produce an executable, this file does not by itself cause the
15  * resulting executable to be covered by the GNU General Public
16  * License. This exception does not however invalidate any other
17  * reasons why the executable file might be covered by the GNU Library
18  * General Public License.
19  *
20  * This library is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23  * Lesser General Public License for more details.
24  *
25  * You should have received a copy of the GNU Lesser General Public
26  * License along with this library; if not, write to the Free Software
27  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
28  */
29 #ifndef cxxtools_SerializationInfo_h
30 #define cxxtools_SerializationInfo_h
31 
32 #include <cxxtools/api.h>
33 #include <cxxtools/string.h>
34 #include <cxxtools/convert.h>
36 #include <vector>
37 #include <set>
38 #include <map>
39 #include <list>
40 #include <deque>
41 #include <limits>
42 #include <typeinfo>
43 #include <cxxtools/config.h>
44 
45 namespace cxxtools
46 {
47 
51 {
52  typedef std::vector<SerializationInfo> Nodes;
53 
54  public:
55  enum Category {
56  Void = 0, Value = 1, Object = 2, Array = 6
57  };
58 
59  class Iterator;
61 
62 #ifdef HAVE_LONG_LONG
63  typedef long long int_type;
64 #else
65  typedef long int_type;
66 #endif
67 #ifdef HAVE_UNSIGNED_LONG_LONG
68  typedef unsigned long long unsigned_type;
69 #else
70  typedef unsigned long unsigned_type;
71 #endif
72 
73  public:
75 
77 
79  { _releaseValue(); }
80 
81  void reserve(size_t n);
82 
83  Category category() const
84  {
85  return _category;
86  }
87 
88  void setCategory(Category cat)
89  {
90  _category = cat;
91  }
92 
94  {
95  return _parent;
96  }
97 
98  const SerializationInfo* parent() const
99  {
100  return _parent;
101  }
102 
103  const std::string& typeName() const
104  {
105  return _type;
106  }
107 
108  void setTypeName(const std::string& type)
109  {
110  _type = type;
111  }
112 
113  const std::string& name() const
114  {
115  return _name;
116  }
117 
118  void setName(const std::string& name)
119  {
120  _name = name;
121  }
122 
125  void setValue(const String& value) { _setString(value); }
126  void setValue(const std::string& value) { _setString8(value); }
127  void setValue(const char* value) { _setString8(value); }
128  void setValue(Char value) { _setString(String(1, value)); }
129  void setValue(wchar_t value) { _setString(String(1, value)); }
130  void setValue(bool value) { _setBool(value) ; }
131  void setValue(char value) { _setChar(value) ; }
132  void setValue(unsigned char value) { _setUInt(value) ; }
133  void setValue(short value) { _setInt(value) ; }
134  void setValue(unsigned short value) { _setUInt(value) ; }
135  void setValue(int value) { _setInt(value) ; }
136  void setValue(unsigned int value) { _setUInt(value) ; }
137  void setValue(long value) { _setInt(value) ; }
138  void setValue(unsigned long value) { _setUInt(value) ; }
139 #ifdef HAVE_LONG_LONG
140  void setValue(long long value) { _setInt(value) ; }
141 #endif
142 #ifdef HAVE_UNSIGNED_LONG_LONG
143  void setValue(unsigned long long value) { _setUInt(value) ; }
144 #endif
145 
146  void setValue(float value) { _setFloat(value); }
147  void setValue(double value) { _setFloat(value); }
148  void setValue(long double value) { _setFloat(value); }
149  void setNull();
150 
153  void getValue(String& value) const;
154  void getValue(std::string& value) const;
155  void getValue(Char& value) const { value = _getWChar(); }
156  void getValue(wchar_t& value) const { value = _getWChar(); }
157  void getValue(bool& value) const { value = _getBool(); }
158  void getValue(char& value) const { value = _getChar(); }
159  void getValue(signed char& value) const
160  { value = static_cast<signed char>(_getInt("signed char", std::numeric_limits<signed char>::min(), std::numeric_limits<signed char>::max())); }
161  void getValue(unsigned char& value) const
162  { value = static_cast<signed char>(_getUInt("unsigned char", std::numeric_limits<unsigned char>::max())); }
163  void getValue(short& value) const
164  { value = static_cast<short>(_getInt("short", std::numeric_limits<short>::min(), std::numeric_limits<short>::max())); }
165  void getValue(unsigned short& value) const
166  { value = static_cast<unsigned short>(_getUInt("unsigned short", std::numeric_limits<unsigned short>::max())); }
167  void getValue(int& value) const
168  { value = static_cast<int>(_getInt("int", std::numeric_limits<int>::min(), std::numeric_limits<int>::max())); }
169  void getValue(unsigned int& value) const
170  { value = static_cast<unsigned int>(_getUInt("unsigned int", std::numeric_limits<unsigned int>::max())); }
171  void getValue(long& value) const
172  { value = static_cast<long>(_getInt("long", std::numeric_limits<long>::min(), std::numeric_limits<long>::max())); }
173  void getValue(unsigned long& value) const
174  { value = static_cast<unsigned long>(_getUInt("unsigned long", std::numeric_limits<unsigned long>::max())); }
175 #ifdef HAVE_LONG_LONG
176  void getValue(long long& value) const
177  { value = static_cast<long long>(_getInt("long long", std::numeric_limits<long long>::min(), std::numeric_limits<long long>::max())); }
178 #endif
179 #ifdef HAVE_UNSIGNED_LONG_LONG
180  void getValue(unsigned long long& value) const
181  { value = static_cast<unsigned long long>(_getUInt("unsigned long long", std::numeric_limits<unsigned long long>::max())); }
182 #endif
183  void getValue(float& value) const
184  { value = static_cast<float>(_getFloat("float", static_cast<long double>(std::numeric_limits<float>::max())*1.0000000000001)); }
185  void getValue(double& value) const
186  { value = static_cast<double>(_getFloat("double", static_cast<long double>(std::numeric_limits<double>::max())*1.0000000000001)); }
187  void getValue(long double& value) const
188  { value = static_cast<long double>(_getFloat("long double", std::numeric_limits<long double>::max())); }
189 
192  template <typename T>
193  SerializationInfo& addValue(const std::string& name, const T& value)
194  {
195  SerializationInfo& info = this->addMember(name);
196  info.setValue(value);
197  return info;
198  }
199 
202  SerializationInfo& addMember(const std::string& name);
203 
208  const SerializationInfo& getMember(const std::string& name) const;
209 
214  const SerializationInfo& getMember(unsigned idx) const;
215 
221  template <typename T>
222  bool getMember(const std::string& name, T& value) const
223  {
224  const SerializationInfo* si = findMember(name);
225  if (si == 0)
226  return false;
227  *si >>= value;
228  return true;
229  }
230 
236  const SerializationInfo* findMember(const std::string& name) const;
237 
243  SerializationInfo* findMember(const std::string& name);
244 
245  size_t memberCount() const
246  {
247  return _nodes.size();
248  }
249 
250  Iterator begin();
251 
252  Iterator end();
253 
254  ConstIterator begin() const;
255 
256  ConstIterator end() const;
257 
258  SerializationInfo& operator =(const SerializationInfo& si);
259 
260  void clear();
261 
262  void swap(SerializationInfo& si);
263 
264  bool isNull() const { return _t == t_none && _category == Void; }
265  bool isString() const { return _t == t_string; }
266  bool isString8() const { return _t == t_string8; }
267  bool isChar() const { return _t == t_char; }
268  bool isBool() const { return _t == t_bool; }
269  bool isInt() const { return _t == t_int; }
270  bool isUInt() const { return _t == t_uint; }
271  bool isFloat() const { return _t == t_float; }
272 
273  void dump(std::ostream& out, const std::string& praefix = std::string()) const;
274 
275  protected:
276  void setParent(SerializationInfo& si)
277  { _parent = &si; }
278 
279  private:
280  SerializationInfo* _parent;
281  Category _category;
282  std::string _name;
283  std::string _type;
284 
285  void _releaseValue();
286  void _setString(const String& value);
287  void _setString8(const std::string& value);
288  void _setString8(const char* value);
289  void _setChar(char value);
290  void _setBool(bool value);
291  void _setInt(int_type value);
292  void _setUInt(unsigned_type value);
293  void _setFloat(long double value);
294 
295  bool _getBool() const;
296  wchar_t _getWChar() const;
297  char _getChar() const;
298  int_type _getInt(const char* type, int_type min, int_type max) const;
299  unsigned_type _getUInt(const char* type, unsigned_type max) const;
300  long double _getFloat(const char* type, long double max) const;
301 
302  union U
303  {
304  char _s[sizeof(String) >= sizeof(std::string) ? sizeof(String) : sizeof(std::string)];
305  char _c;
306  bool _b;
307  int_type _i;
308  unsigned_type _u;
309  long double _f;
310  } _u;
311 
312  String* _StringPtr() { return reinterpret_cast<String*>(_u._s); }
313  String& _String() { return *_StringPtr(); }
314  const String* _StringPtr() const { return reinterpret_cast<const String*>(_u._s); }
315  const String& _String() const { return *_StringPtr(); }
316  std::string* _String8Ptr() { return reinterpret_cast<std::string*>(_u._s); }
317  std::string& _String8() { return *_String8Ptr(); }
318  const std::string* _String8Ptr() const { return reinterpret_cast<const std::string*>(_u._s); }
319  const std::string& _String8() const { return *_String8Ptr(); }
320 
321  enum T
322  {
323  t_none,
324  t_string,
325  t_string8,
326  t_char,
327  t_bool,
328  t_int,
329  t_uint,
330  t_float
331  } _t;
332 
333  Nodes _nodes; // objects/arrays
334 };
335 
336 
338 {
339  public:
340  Iterator();
341 
342  Iterator(const Iterator& other);
343 
345 
346  Iterator& operator=(const Iterator& other);
347 
348  Iterator& operator++();
349 
351 
353 
354  bool operator!=(const Iterator& other) const;
355 
356  bool operator==(const Iterator& other) const;
357 
358  private:
359  SerializationInfo* _info;
360 };
361 
362 
364 {
365  public:
366  ConstIterator();
367 
368  ConstIterator(const ConstIterator& other);
369 
370  ConstIterator(const SerializationInfo* info);
371 
372  ConstIterator& operator=(const ConstIterator& other);
373 
375 
376  const SerializationInfo& operator*() const;
377 
378  const SerializationInfo* operator->() const;
379 
380  bool operator!=(const ConstIterator& other) const;
381 
382  bool operator==(const ConstIterator& other) const;
383 
384  private:
385  const SerializationInfo* _info;
386 };
387 
388 
390 : _info(0)
391 {}
392 
393 
395 : _info(other._info)
396 {}
397 
398 
400 : _info(info)
401 {}
402 
403 
405 {
406  _info = other._info;
407  return *this;
408 }
409 
410 
412 {
413  ++_info;
414  return *this;
415 }
416 
417 
419 {
420  return *_info;
421 }
422 
423 
425 {
426  return _info;
427 }
428 
429 
430 inline bool SerializationInfo::Iterator::operator!=(const Iterator& other) const
431 {
432  return _info != other._info;
433 }
434 
435 
436 inline bool SerializationInfo::Iterator::operator==(const Iterator& other) const
437 {
438  return _info == other._info;
439 }
440 
441 
443 : _info(0)
444 {}
445 
446 
448 : _info(other._info)
449 {}
450 
451 
453 : _info(info)
454 {}
455 
456 
458 {
459  _info = other._info;
460  return *this;
461 }
462 
463 
465 {
466  ++_info;
467  return *this;
468 }
469 
470 
472 {
473  return *_info;
474 }
475 
476 
478 {
479  return _info;
480 }
481 
482 
484 {
485  return _info != other._info;
486 }
487 
488 
490 {
491  return _info == other._info;
492 }
493 
494 
496 {
497  ssi = si;
498 }
499 
500 
502 {
503  si = ssi;
504 }
505 
506 
507 inline void operator >>=(const SerializationInfo& si, bool& n)
508 {
509  si.getValue(n);
510 }
511 
512 
513 inline void operator <<=(SerializationInfo& si, bool n)
514 {
515  si.setValue(n);
516  si.setTypeName("bool");
517 }
518 
519 
520 inline void operator >>=(const SerializationInfo& si, signed char& n)
521 {
522  si.getValue(n);
523 }
524 
525 
526 inline void operator <<=(SerializationInfo& si, signed char n)
527 {
528  si.setValue(n);
529  si.setTypeName("char");
530 }
531 
532 
533 inline void operator >>=(const SerializationInfo& si, unsigned char& n)
534 {
535  si.getValue(n);
536 }
537 
538 
539 inline void operator <<=(SerializationInfo& si, unsigned char n)
540 {
541  si.setValue(n);
542  si.setTypeName("char");
543 }
544 
545 
546 inline void operator >>=(const SerializationInfo& si, char& n)
547 {
548  si.getValue(n);
549 }
550 
551 
552 inline void operator <<=(SerializationInfo& si, char n)
553 {
554  si.setValue(n);
555  si.setTypeName("char");
556 }
557 
558 
559 inline void operator >>=(const SerializationInfo& si, short& n)
560 {
561  si.getValue(n);
562 }
563 
564 
565 inline void operator <<=(SerializationInfo& si, short n)
566 {
567  si.setValue(n);
568  si.setTypeName("int");
569 }
570 
571 
572 inline void operator >>=(const SerializationInfo& si, unsigned short& n)
573 {
574  si.getValue(n);
575 }
576 
577 
578 inline void operator <<=(SerializationInfo& si, unsigned short n)
579 {
580  si.setValue(n);
581  si.setTypeName("int");
582 }
583 
584 
585 inline void operator >>=(const SerializationInfo& si, int& n)
586 {
587  si.getValue(n);
588 }
589 
590 
591 inline void operator <<=(SerializationInfo& si, int n)
592 {
593  si.setValue(n);
594  si.setTypeName("int");
595 }
596 
597 
598 inline void operator >>=(const SerializationInfo& si, unsigned int& n)
599 {
600  si.getValue(n);
601 }
602 
603 
604 inline void operator <<=(SerializationInfo& si, unsigned int n)
605 {
606  si.setValue(n);
607  si.setTypeName("int");
608 }
609 
610 
611 inline void operator >>=(const SerializationInfo& si, long& n)
612 {
613  si.getValue(n);
614 }
615 
616 
617 inline void operator <<=(SerializationInfo& si, long n)
618 {
619  si.setValue(n);
620  si.setTypeName("int");
621 }
622 
623 
624 inline void operator >>=(const SerializationInfo& si, unsigned long& n)
625 {
626  si.getValue(n);
627 }
628 
629 
630 inline void operator <<=(SerializationInfo& si, unsigned long n)
631 {
632  si.setValue(n);
633  si.setTypeName("int");
634 }
635 
636 
637 #ifdef HAVE_LONG_LONG
638 
639 inline void operator >>=(const SerializationInfo& si, long long& n)
640 {
641  si.getValue(n);
642 }
643 
644 
645 inline void operator <<=(SerializationInfo& si, long long n)
646 {
647  si.setValue(n);
648  si.setTypeName("int");
649 }
650 
651 #endif
652 
653 
654 #ifdef HAVE_UNSIGNED_LONG_LONG
655 
656 inline void operator >>=(const SerializationInfo& si, unsigned long long& n)
657 {
658  si.getValue(n);
659 }
660 
661 
662 inline void operator <<=(SerializationInfo& si, unsigned long long n)
663 {
664  si.setValue(n);
665  si.setTypeName("int");
666 }
667 
668 #endif
669 
670 
671 inline void operator >>=(const SerializationInfo& si, float& n)
672 {
673  si.getValue(n);
674 }
675 
676 
677 inline void operator <<=(SerializationInfo& si, float n)
678 {
679  si.setValue(n);
680  si.setTypeName("double");
681 }
682 
683 
684 inline void operator >>=(const SerializationInfo& si, double& n)
685 {
686  si.getValue(n);
687 }
688 
689 
690 inline void operator <<=(SerializationInfo& si, double n)
691 {
692  si.setValue(n);
693  si.setTypeName("double");
694 }
695 
696 
697 inline void operator >>=(const SerializationInfo& si, std::string& n)
698 {
699  si.getValue(n);
700 }
701 
702 
703 inline void operator <<=(SerializationInfo& si, const std::string& n)
704 {
705  si.setValue(n);
706  si.setTypeName("string");
707 }
708 
709 
710 inline void operator <<=(SerializationInfo& si, const char* n)
711 {
712  si.setValue(n);
713  si.setTypeName("string");
714 }
715 
716 
718 {
719  si.getValue(n);
720 }
721 
722 
724 {
725  si.setValue(n);
726  si.setTypeName("string");
727 }
728 
729 
730 template <typename T, typename A>
731 inline void operator >>=(const SerializationInfo& si, std::vector<T, A>& vec)
732 {
733  vec.clear();
734  vec.reserve(si.memberCount());
735  for(SerializationInfo::ConstIterator it = si.begin(); it != si.end(); ++it)
736  {
737  vec.resize( vec.size() + 1 );
738  *it >>= vec.back();
739  }
740 }
741 
742 
743 template <typename T, typename A>
744 inline void operator <<=(SerializationInfo& si, const std::vector<T, A>& vec)
745 {
746  typename std::vector<T, A>::const_iterator it;
747 
748  si.reserve(vec.size());
749  for(it = vec.begin(); it != vec.end(); ++it)
750  {
751  SerializationInfo& newSi = si.addMember(std::string());
752  newSi <<= *it;
753  }
754 
755  si.setTypeName("array");
756  si.setCategory(SerializationInfo::Array);
757 }
758 
759 
760 inline void operator >>=(const SerializationInfo& si, std::vector<int>& vec)
761 {
762  vec.clear();
763  for(SerializationInfo::ConstIterator it = si.begin(); it != si.end(); ++it)
764  {
765  vec.resize( vec.size() + 1 );
766  *it >>= vec.back();
767  }
768 }
769 
770 inline void operator <<=(SerializationInfo& si, const std::vector<int>& vec)
771 {
772  std::vector<int>::const_iterator it;
773 
774  for(it = vec.begin(); it != vec.end(); ++it)
775  {
776  SerializationInfo& newSi = si.addMember(std::string());
777  newSi <<= *it;
778  }
779 
780  si.setTypeName("array");
781  si.setCategory(SerializationInfo::Array);
782 }
783 
784 
785 template <typename T, typename A>
786 inline void operator >>=(const SerializationInfo& si, std::list<T, A>& list)
787 {
788  list.clear();
789  for(SerializationInfo::ConstIterator it = si.begin(); it != si.end(); ++it)
790  {
791  list.resize( list.size() + 1 );
792  *it >>= list.back();
793  }
794 }
795 
796 
797 template <typename T, typename A>
798 inline void operator <<=(SerializationInfo& si, const std::list<T, A>& list)
799 {
800  typename std::list<T, A>::const_iterator it;
801 
802  for(it = list.begin(); it != list.end(); ++it)
803  {
804  SerializationInfo& newSi = si.addMember(std::string());
805  newSi <<= *it;
806  }
807 
808  si.setTypeName("list");
809  si.setCategory(SerializationInfo::Array);
810 }
811 
812 
813 template <typename T, typename A>
814 inline void operator >>=(const SerializationInfo& si, std::deque<T, A>& deque)
815 {
816  deque.clear();
817  for(SerializationInfo::ConstIterator it = si.begin(); it != si.end(); ++it)
818  {
819  deque.resize( deque.size() + 1 );
820  *it >>= deque.back();
821  }
822 }
823 
824 
825 template <typename T, typename A>
826 inline void operator <<=(SerializationInfo& si, const std::deque<T, A>& deque)
827 {
828  typename std::deque<T, A>::const_iterator it;
829 
830  for(it = deque.begin(); it != deque.end(); ++it)
831  {
832  SerializationInfo& newSi = si.addMember(std::string());
833  newSi <<= *it;
834  }
835 
836  si.setTypeName("deque");
837  si.setCategory(SerializationInfo::Array);
838 }
839 
840 
841 template <typename T, typename C, typename A>
842 inline void operator >>=(const SerializationInfo& si, std::set<T, C, A>& set)
843 {
844  set.clear();
845  for(SerializationInfo::ConstIterator it = si.begin(); it != si.end(); ++it)
846  {
847  T t;
848  *it >>= t;
849  set.insert(t);
850  }
851 }
852 
853 
854 template <typename T, typename C, typename A>
855 inline void operator <<=(SerializationInfo& si, const std::set<T, C, A>& set)
856 {
857  typename std::set<T, C, A>::const_iterator it;
858 
859  for(it = set.begin(); it != set.end(); ++it)
860  {
861  SerializationInfo& newSi = si.addMember(std::string());
862  newSi <<= *it;
863  }
864 
865  si.setTypeName("set");
866  si.setCategory(SerializationInfo::Array);
867 }
868 
869 
870 template <typename T, typename C, typename A>
871 inline void operator >>=(const SerializationInfo& si, std::multiset<T, C, A>& multiset)
872 {
873  multiset.clear();
874  for(SerializationInfo::ConstIterator it = si.begin(); it != si.end(); ++it)
875  {
876  T t;
877  *it >>= t;
878  multiset.insert(t);
879  }
880 }
881 
882 
883 template <typename T, typename C, typename A>
884 inline void operator <<=(SerializationInfo& si, const std::multiset<T, C, A>& multiset)
885 {
886  typename std::multiset<T, C, A>::const_iterator it;
887 
888  for(it = multiset.begin(); it != multiset.end(); ++it)
889  {
890  SerializationInfo& newSi = si.addMember(std::string());
891  newSi <<= *it;
892  }
893 
894  si.setTypeName("multiset");
895  si.setCategory(SerializationInfo::Array);
896 }
897 
898 
899 template <typename A, typename B>
900 inline void operator >>=(const SerializationInfo& si, std::pair<A, B>& p)
901 {
902  si.getMember("first") >>= p.first;
903  si.getMember("second") >>= p.second;
904 }
905 
906 
907 template <typename A, typename B>
908 inline void operator <<=(SerializationInfo& si, const std::pair<A, B>& p)
909 {
910  si.setTypeName("pair");
911  si.addMember("first") <<= p.first;
912  si.addMember("second") <<= p.second;
913 }
914 
915 
916 template <typename K, typename V, typename P, typename A>
917 inline void operator >>=(const SerializationInfo& si, std::map<K, V, P, A>& map)
918 {
919  map.clear();
920  for(SerializationInfo::ConstIterator it = si.begin(); it != si.end(); ++it)
921  {
922  typename std::pair<K, V> v;
923  *it >>= v;
924  map.insert(v);
925  }
926 }
927 
928 
929 template <typename K, typename V, typename P, typename A>
930 inline void operator <<=(SerializationInfo& si, const std::map<K, V, P, A>& map)
931 {
932  typename std::map<K, V, P, A>::const_iterator it;
933 
934  for(it = map.begin(); it != map.end(); ++it)
935  {
936  SerializationInfo& newSi = si.addMember(std::string());
937  newSi <<= *it;
938  }
939 
940  si.setTypeName("map");
941  si.setCategory(SerializationInfo::Array);
942 }
943 
944 
945 template <typename K, typename V, typename P, typename A>
946 inline void operator >>=(const SerializationInfo& si, std::multimap<K, V, P, A>& multimap)
947 {
948  multimap.clear();
949  for(SerializationInfo::ConstIterator it = si.begin(); it != si.end(); ++it)
950  {
951  typename std::pair<K, V> v;
952  *it >>= v;
953  multimap.insert(v);
954  }
955 }
956 
957 
958 template <typename T, typename C, typename P, typename A>
959 inline void operator <<=(SerializationInfo& si, const std::multimap<T, C, P, A>& multimap)
960 {
961  typename std::multimap<T, C, P, A>::const_iterator it;
962 
963  for(it = multimap.begin(); it != multimap.end(); ++it)
964  {
965  SerializationInfo& newSi = si.addMember(std::string());
966  newSi <<= *it;
967  }
968 
969  si.setTypeName("multimap");
970  si.setCategory(SerializationInfo::Array);
971 }
972 
973 
974 inline std::ostream& operator<< (std::ostream& out, const SerializationInfo& si)
975 {
976  si.dump(out);
977  return out;
978 }
979 
980 } // namespace cxxtools
981 
982 
983 #endif