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