github.com/platonnetwork/platon-go@v0.7.6/cases/tool/win/bls_win/include/cybozu/serializer.hpp (about)

     1  #pragma once
     2  /**
     3  	@file
     4  	@brief serializer for vector, list, map and so on
     5  
     6  	@author MITSUNARI Shigeo(@herumi)
     7  */
     8  #include <assert.h>
     9  #include <cybozu/stream.hpp>
    10  
    11  #ifdef _MSC_VER
    12  	#pragma warning(push)
    13  	#pragma warning(disable : 4127)
    14  #endif
    15  
    16  //#define CYBOZU_SERIALIZER_FIXED_SIZE_INTEGER
    17  
    18  namespace cybozu {
    19  
    20  namespace serializer_local {
    21  
    22  template<class T>
    23  union ci {
    24  	T i;
    25  	uint8_t c[sizeof(T)];
    26  };
    27  
    28  template<class S, void (S::*)(size_t)>
    29  struct HasMemFunc { };
    30  
    31  template<class T>
    32  void dispatch_reserve(T& t, size_t size, int, HasMemFunc<T, &T::reserve>* = 0)
    33  {
    34  	t.reserve(size);
    35  }
    36  
    37  template<class T>
    38  void dispatch_reserve(T&, size_t, int*)
    39  {
    40  }
    41  
    42  template<class T>
    43  void reserve_if_exists(T& t, size_t size)
    44  {
    45  	dispatch_reserve(t, size, 0);
    46  }
    47  
    48  } // serializer_local
    49  
    50  template<class InputStream, class T>
    51  void loadRange(T *p, size_t num, InputStream& is)
    52  {
    53  	cybozu::read(p, num * sizeof(T), is);
    54  }
    55  
    56  template<class OutputStream, class T>
    57  void saveRange(OutputStream& os, const T *p, size_t num)
    58  {
    59  	cybozu::write(os, p, num * sizeof(T));
    60  }
    61  
    62  template<class InputStream, class T>
    63  void loadPod(T& x, InputStream& is)
    64  {
    65  	serializer_local::ci<T> ci;
    66  	loadRange(ci.c, sizeof(ci.c), is);
    67  	x = ci.i;
    68  }
    69  
    70  template<class OutputStream, class T>
    71  void savePod(OutputStream& os, const T& x)
    72  {
    73  	serializer_local::ci<T> ci;
    74  	ci.i = x;
    75  	saveRange(os, ci.c, sizeof(ci.c));
    76  }
    77  
    78  template<class InputStream, class T>
    79  void load(T& x, InputStream& is)
    80  {
    81  	x.load(is);
    82  }
    83  
    84  template<class OutputStream, class T>
    85  void save(OutputStream& os, const T& x)
    86  {
    87  	x.save(os);
    88  }
    89  
    90  #define CYBOZU_SERIALIZER_MAKE_SERIALIZER_F(type) \
    91  template<class InputStream>void load(type& x, InputStream& is) { loadPod(x, is); } \
    92  template<class OutputStream>void save(OutputStream& os, type x) { savePod(os, x); }
    93  
    94  CYBOZU_SERIALIZER_MAKE_SERIALIZER_F(bool)
    95  CYBOZU_SERIALIZER_MAKE_SERIALIZER_F(char)
    96  CYBOZU_SERIALIZER_MAKE_SERIALIZER_F(short)
    97  CYBOZU_SERIALIZER_MAKE_SERIALIZER_F(unsigned char)
    98  CYBOZU_SERIALIZER_MAKE_SERIALIZER_F(unsigned short)
    99  CYBOZU_SERIALIZER_MAKE_SERIALIZER_F(wchar_t)
   100  
   101  CYBOZU_SERIALIZER_MAKE_SERIALIZER_F(float)
   102  CYBOZU_SERIALIZER_MAKE_SERIALIZER_F(double)
   103  
   104  #ifdef CYBOZU_SERIALIZER_FIXED_SIZE_INTEGER
   105  
   106  #define CYBOZU_SERIALIZER_MAKE_INT_SERIALIZER(type) CYBOZU_SERIALIZER_MAKE_SERIALIZER_F(type)
   107  
   108  #else
   109  
   110  namespace serializer_local {
   111  
   112  template<class S, class T>
   113  bool isRecoverable(T x)
   114  {
   115  	return T(S(x)) == x;
   116  }
   117  /*
   118  	data structure H:D of integer x
   119  	H:header(1byte)
   120  	0x80 ; D = 1 byte zero ext
   121  	0x81 ; D = 2 byte zero ext
   122  	0x82 ; D = 4 byte zero ext
   123  	0x83 ; D = 8 byte zero ext
   124  	0x84 ; D = 1 byte signed ext
   125  	0x85 ; D = 2 byte signed ext
   126  	0x86 ; D = 4 byte signed ext
   127  	0x87 ; D = 8 byte signed ext
   128  	other; x = signed H, D = none
   129  */
   130  template<class OutputStream, class T>
   131  void saveVariableInt(OutputStream& os, const T& x)
   132  {
   133  	if (isRecoverable<int8_t>(x)) {
   134  		uint8_t u8 = uint8_t(x);
   135  		if (unsigned(u8 - 0x80) <= 7) {
   136  			savePod(os, uint8_t(0x84));
   137  		}
   138  		savePod(os, u8);
   139  	} else if (isRecoverable<uint8_t>(x)) {
   140  		savePod(os, uint8_t(0x80));
   141  		savePod(os, uint8_t(x));
   142  	} else if (isRecoverable<uint16_t>(x) || isRecoverable<int16_t>(x)) {
   143  		savePod(os, uint8_t(isRecoverable<uint16_t>(x) ? 0x81 : 0x85));
   144  		savePod(os, uint16_t(x));
   145  	} else if (isRecoverable<uint32_t>(x) || isRecoverable<int32_t>(x)) {
   146  		savePod(os, uint8_t(isRecoverable<uint32_t>(x) ? 0x82 : 0x86));
   147  		savePod(os, uint32_t(x));
   148  	} else {
   149  		assert(sizeof(T) == 8);
   150  		savePod(os, uint8_t(0x83));
   151  		savePod(os, uint64_t(x));
   152  	}
   153  }
   154  
   155  template<class InputStream, class T>
   156  void loadVariableInt(T& x, InputStream& is)
   157  {
   158  	uint8_t h;
   159  	loadPod(h, is);
   160  	if (h == 0x80) {
   161  		uint8_t v;
   162  		loadPod(v, is);
   163  		x = v;
   164  	} else if (h == 0x81) {
   165  		uint16_t v;
   166  		loadPod(v, is);
   167  		x = v;
   168  	} else if (h == 0x82) {
   169  		uint32_t v;
   170  		loadPod(v, is);
   171  		x = v;
   172  	} else if (h == 0x83) {
   173  		if (sizeof(T) == 4) throw cybozu::Exception("loadVariableInt:bad header") << h;
   174  		uint64_t v;
   175  		loadPod(v, is);
   176  		x = static_cast<T>(v);
   177  	} else if (h == 0x84) {
   178  		int8_t v;
   179  		loadPod(v, is);
   180  		x = v;
   181  	} else if (h == 0x85) {
   182  		int16_t v;
   183  		loadPod(v, is);
   184  		x = v;
   185  	} else if (h == 0x86) {
   186  		int32_t v;
   187  		loadPod(v, is);
   188  		x = v;
   189  	} else if (h == 0x87) {
   190  		if (sizeof(T) == 4) throw cybozu::Exception("loadVariableInt:bad header") << h;
   191  		int64_t v;
   192  		loadPod(v, is);
   193  		x = static_cast<T>(v);
   194  	} else {
   195  		x = static_cast<int8_t>(h);
   196  	}
   197  }
   198  
   199  } // serializer_local
   200  
   201  #define CYBOZU_SERIALIZER_MAKE_INT_SERIALIZER(type) \
   202  template<class InputStream>void load(type& x, InputStream& is) { serializer_local::loadVariableInt(x, is); } \
   203  template<class OutputStream>void save(OutputStream& os, type x) { serializer_local::saveVariableInt(os, x); }
   204  
   205  #endif
   206  
   207  CYBOZU_SERIALIZER_MAKE_INT_SERIALIZER(int)
   208  CYBOZU_SERIALIZER_MAKE_INT_SERIALIZER(long)
   209  CYBOZU_SERIALIZER_MAKE_INT_SERIALIZER(long long)
   210  CYBOZU_SERIALIZER_MAKE_INT_SERIALIZER(unsigned int)
   211  CYBOZU_SERIALIZER_MAKE_INT_SERIALIZER(unsigned long)
   212  CYBOZU_SERIALIZER_MAKE_INT_SERIALIZER(unsigned long long)
   213  
   214  #undef CYBOZU_SERIALIZER_MAKE_INT_SERIALIZER
   215  #undef CYBOZU_SERIALIZER_MAKE_UNT_SERIALIZER
   216  #undef CYBOZU_SERIALIZER_MAKE_SERIALIZER_F
   217  #undef CYBOZU_SERIALIZER_MAKE_SERIALIZER_V
   218  
   219  // only for std::vector<POD>
   220  template<class V, class InputStream>
   221  void loadPodVec(V& v, InputStream& is)
   222  {
   223  	size_t size;
   224  	load(size, is);
   225  	v.resize(size);
   226  	if (size > 0) loadRange(&v[0], size, is);
   227  }
   228  
   229  // only for std::vector<POD>
   230  template<class V, class OutputStream>
   231  void savePodVec(OutputStream& os, const V& v)
   232  {
   233  	save(os, v.size());
   234  	if (!v.empty()) saveRange(os, &v[0], v.size());
   235  }
   236  
   237  template<class InputStream>
   238  void load(std::string& str, InputStream& is)
   239  {
   240  	loadPodVec(str, is);
   241  }
   242  
   243  template<class OutputStream>
   244  void save(OutputStream& os, const std::string& str)
   245  {
   246  	savePodVec(os, str);
   247  }
   248  
   249  template<class OutputStream>
   250  void save(OutputStream& os, const char *x)
   251  {
   252  	const size_t len = strlen(x);
   253  	save(os, len);
   254  	if (len > 0) saveRange(os, x, len);
   255  }
   256  
   257  
   258  // for vector, list
   259  template<class InputStream, class T, class Alloc, template<class T_, class Alloc_>class Container>
   260  void load(Container<T, Alloc>& x, InputStream& is)
   261  {
   262  	size_t size;
   263  	load(size, is);
   264  	serializer_local::reserve_if_exists(x, size);
   265  	for (size_t i = 0; i < size; i++) {
   266  		x.push_back(T());
   267  		T& t = x.back();
   268  		load(t, is);
   269  	}
   270  }
   271  
   272  template<class OutputStream, class T, class Alloc, template<class T_, class Alloc_>class Container>
   273  void save(OutputStream& os, const Container<T, Alloc>& x)
   274  {
   275  	typedef Container<T, Alloc> V;
   276  	save(os, x.size());
   277  	for (typename V::const_iterator i = x.begin(), end = x.end(); i != end; ++i) {
   278  		save(os, *i);
   279  	}
   280  }
   281  
   282  // for set
   283  template<class InputStream, class K, class Pred, class Alloc, template<class K_, class Pred_, class Alloc_>class Container>
   284  void load(Container<K, Pred, Alloc>& x, InputStream& is)
   285  {
   286  	size_t size;
   287  	load(size, is);
   288  	for (size_t i = 0; i < size; i++) {
   289  		K t;
   290  		load(t, is);
   291  		x.insert(t);
   292  	}
   293  }
   294  
   295  template<class OutputStream, class K, class Pred, class Alloc, template<class K_, class Pred_, class Alloc_>class Container>
   296  void save(OutputStream& os, const Container<K, Pred, Alloc>& x)
   297  {
   298  	typedef Container<K, Pred, Alloc> Set;
   299  	save(os, x.size());
   300  	for (typename Set::const_iterator i = x.begin(), end = x.end(); i != end; ++i) {
   301  		save(os, *i);
   302  	}
   303  }
   304  
   305  // for map
   306  template<class InputStream, class K, class V, class Pred, class Alloc, template<class K_, class V_, class Pred_, class Alloc_>class Container>
   307  void load(Container<K, V, Pred, Alloc>& x, InputStream& is)
   308  {
   309  	typedef Container<K, V, Pred, Alloc> Map;
   310  	size_t size;
   311  	load(size, is);
   312  	for (size_t i = 0; i < size; i++) {
   313  		std::pair<typename Map::key_type, typename Map::mapped_type> vt;
   314  		load(vt.first, is);
   315  		load(vt.second, is);
   316  		x.insert(vt);
   317  	}
   318  }
   319  
   320  template<class OutputStream, class K, class V, class Pred, class Alloc, template<class K_, class V_, class Pred_, class Alloc_>class Container>
   321  void save(OutputStream& os, const Container<K, V, Pred, Alloc>& x)
   322  {
   323  	typedef Container<K, V, Pred, Alloc> Map;
   324  	save(os, x.size());
   325  	for (typename Map::const_iterator i = x.begin(), end = x.end(); i != end; ++i) {
   326  		save(os, i->first);
   327  		save(os, i->second);
   328  	}
   329  }
   330  
   331  // unordered_map
   332  template<class InputStream, class K, class V, class Hash, class Pred, class Alloc, template<class K_, class V_, class Hash_, class Pred_, class Alloc_>class Container>
   333  void load(Container<K, V, Hash, Pred, Alloc>& x, InputStream& is)
   334  {
   335  	typedef Container<K, V, Hash, Pred, Alloc> Map;
   336  	size_t size;
   337  	load(size, is);
   338  //	x.reserve(size); // tr1::unordered_map may not have reserve
   339  	cybozu::serializer_local::reserve_if_exists(x, size);
   340  	for (size_t i = 0; i < size; i++) {
   341  		std::pair<typename Map::key_type, typename Map::mapped_type> vt;
   342  		load(vt.first, is);
   343  		load(vt.second, is);
   344  		x.insert(vt);
   345  	}
   346  }
   347  
   348  template<class OutputStream, class K, class V, class Hash, class Pred, class Alloc, template<class K_, class V_, class Hash_, class Pred_, class Alloc_>class Container>
   349  void save(OutputStream& os, const Container<K, V, Hash, Pred, Alloc>& x)
   350  {
   351  	typedef Container<K, V, Hash, Pred, Alloc> Map;
   352  	save(os, x.size());
   353  	for (typename Map::const_iterator i = x.begin(), end = x.end(); i != end; ++i) {
   354  		save(os, i->first);
   355  		save(os, i->second);
   356  	}
   357  }
   358  
   359  } // cybozu
   360  
   361  #ifdef _MSC_VER
   362  	#pragma warning(pop)
   363  #endif