serialize.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656
  1. /*
  2. Minetest
  3. Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU Lesser General Public License as published by
  6. the Free Software Foundation; either version 2.1 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public License along
  13. with this program; if not, write to the Free Software Foundation, Inc.,
  14. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  15. */
  16. #pragma once
  17. #include "../irrlichttypes_bloated.h"
  18. #include "../exceptions.h" // for SerializationError
  19. #include "../debug.h" // for assert
  20. #include "config.h"
  21. #if HAVE_ENDIAN_H
  22. #ifdef _WIN32
  23. #define __BYTE_ORDER 0
  24. #define __LITTLE_ENDIAN 0
  25. #define __BIG_ENDIAN 1
  26. #elif defined(__MACH__) && defined(__APPLE__)
  27. #include <machine/endian.h>
  28. #elif defined(__FreeBSD__)
  29. #include <sys/endian.h>
  30. #else
  31. #include <endian.h>
  32. #endif
  33. #endif
  34. #include <cstring> // for memcpy
  35. #include <iostream>
  36. #include <string>
  37. #include <vector>
  38. #define FIXEDPOINT_FACTOR 1000.0f
  39. // 0x7FFFFFFF / 1000.0f is not serializable.
  40. // The limited float precision at this magnitude may cause the result to round
  41. // to a greater value than can be represented by a 32 bit integer when increased
  42. // by a factor of FIXEDPOINT_FACTOR. As a result, [F1000_MIN..F1000_MAX] does
  43. // not represent the full range, but rather the largest safe range, of values on
  44. // all supported architectures. Note: This definition makes assumptions on
  45. // platform float-to-int conversion behavior.
  46. #define F1000_MIN ((float)(s32)((-0x7FFFFFFF - 1) / FIXEDPOINT_FACTOR))
  47. #define F1000_MAX ((float)(s32)((0x7FFFFFFF) / FIXEDPOINT_FACTOR))
  48. #define STRING_MAX_LEN 0xFFFF
  49. #define WIDE_STRING_MAX_LEN 0xFFFF
  50. // 64 MB ought to be enough for anybody - Billy G.
  51. #define LONG_STRING_MAX_LEN (64 * 1024 * 1024)
  52. #if HAVE_ENDIAN_H
  53. // use machine native byte swapping routines
  54. // Note: memcpy below is optimized out by modern compilers
  55. inline u16 readU16(const u8 *data)
  56. {
  57. u16 val;
  58. memcpy(&val, data, 2);
  59. return be16toh(val);
  60. }
  61. inline u32 readU32(const u8 *data)
  62. {
  63. u32 val;
  64. memcpy(&val, data, 4);
  65. return be32toh(val);
  66. }
  67. inline u64 readU64(const u8 *data)
  68. {
  69. u64 val;
  70. memcpy(&val, data, 8);
  71. return be64toh(val);
  72. }
  73. inline void writeU16(u8 *data, u16 i)
  74. {
  75. u16 val = htobe16(i);
  76. memcpy(data, &val, 2);
  77. }
  78. inline void writeU32(u8 *data, u32 i)
  79. {
  80. u32 val = htobe32(i);
  81. memcpy(data, &val, 4);
  82. }
  83. inline void writeU64(u8 *data, u64 i)
  84. {
  85. u64 val = htobe64(i);
  86. memcpy(data, &val, 8);
  87. }
  88. #else
  89. // generic byte-swapping implementation
  90. inline u16 readU16(const u8 *data)
  91. {
  92. return
  93. ((u16)data[0] << 8) | ((u16)data[1] << 0);
  94. }
  95. inline u32 readU32(const u8 *data)
  96. {
  97. return
  98. ((u32)data[0] << 24) | ((u32)data[1] << 16) |
  99. ((u32)data[2] << 8) | ((u32)data[3] << 0);
  100. }
  101. inline u64 readU64(const u8 *data)
  102. {
  103. return
  104. ((u64)data[0] << 56) | ((u64)data[1] << 48) |
  105. ((u64)data[2] << 40) | ((u64)data[3] << 32) |
  106. ((u64)data[4] << 24) | ((u64)data[5] << 16) |
  107. ((u64)data[6] << 8) | ((u64)data[7] << 0);
  108. }
  109. inline void writeU16(u8 *data, u16 i)
  110. {
  111. data[0] = (i >> 8) & 0xFF;
  112. data[1] = (i >> 0) & 0xFF;
  113. }
  114. inline void writeU32(u8 *data, u32 i)
  115. {
  116. data[0] = (i >> 24) & 0xFF;
  117. data[1] = (i >> 16) & 0xFF;
  118. data[2] = (i >> 8) & 0xFF;
  119. data[3] = (i >> 0) & 0xFF;
  120. }
  121. inline void writeU64(u8 *data, u64 i)
  122. {
  123. data[0] = (i >> 56) & 0xFF;
  124. data[1] = (i >> 48) & 0xFF;
  125. data[2] = (i >> 40) & 0xFF;
  126. data[3] = (i >> 32) & 0xFF;
  127. data[4] = (i >> 24) & 0xFF;
  128. data[5] = (i >> 16) & 0xFF;
  129. data[6] = (i >> 8) & 0xFF;
  130. data[7] = (i >> 0) & 0xFF;
  131. }
  132. #endif // HAVE_ENDIAN_H
  133. //////////////// read routines ////////////////
  134. inline u8 readU8(const u8 *data)
  135. {
  136. return ((u8)data[0] << 0);
  137. }
  138. inline s8 readS8(const u8 *data)
  139. {
  140. return (s8)readU8(data);
  141. }
  142. inline s16 readS16(const u8 *data)
  143. {
  144. return (s16)readU16(data);
  145. }
  146. inline s32 readS32(const u8 *data)
  147. {
  148. return (s32)readU32(data);
  149. }
  150. inline s64 readS64(const u8 *data)
  151. {
  152. return (s64)readU64(data);
  153. }
  154. inline f32 readF1000(const u8 *data)
  155. {
  156. return (f32)readS32(data) / FIXEDPOINT_FACTOR;
  157. }
  158. inline video::SColor readARGB8(const u8 *data)
  159. {
  160. video::SColor p(readU32(data));
  161. return p;
  162. }
  163. inline v2s16 readV2S16(const u8 *data)
  164. {
  165. v2s16 p;
  166. p.X = readS16(&data[0]);
  167. p.Y = readS16(&data[2]);
  168. return p;
  169. }
  170. inline v3s16 readV3S16(const u8 *data)
  171. {
  172. v3s16 p;
  173. p.X = readS16(&data[0]);
  174. p.Y = readS16(&data[2]);
  175. p.Z = readS16(&data[4]);
  176. return p;
  177. }
  178. inline v2s32 readV2S32(const u8 *data)
  179. {
  180. v2s32 p;
  181. p.X = readS32(&data[0]);
  182. p.Y = readS32(&data[4]);
  183. return p;
  184. }
  185. inline v3s32 readV3S32(const u8 *data)
  186. {
  187. v3s32 p;
  188. p.X = readS32(&data[0]);
  189. p.Y = readS32(&data[4]);
  190. p.Z = readS32(&data[8]);
  191. return p;
  192. }
  193. inline v2f readV2F1000(const u8 *data)
  194. {
  195. v2f p;
  196. p.X = (float)readF1000(&data[0]);
  197. p.Y = (float)readF1000(&data[4]);
  198. return p;
  199. }
  200. inline v3f readV3F1000(const u8 *data)
  201. {
  202. v3f p;
  203. p.X = (float)readF1000(&data[0]);
  204. p.Y = (float)readF1000(&data[4]);
  205. p.Z = (float)readF1000(&data[8]);
  206. return p;
  207. }
  208. /////////////// write routines ////////////////
  209. inline void writeU8(u8 *data, u8 i)
  210. {
  211. data[0] = (i >> 0) & 0xFF;
  212. }
  213. inline void writeS8(u8 *data, s8 i)
  214. {
  215. writeU8(data, (u8)i);
  216. }
  217. inline void writeS16(u8 *data, s16 i)
  218. {
  219. writeU16(data, (u16)i);
  220. }
  221. inline void writeS32(u8 *data, s32 i)
  222. {
  223. writeU32(data, (u32)i);
  224. }
  225. inline void writeS64(u8 *data, s64 i)
  226. {
  227. writeU64(data, (u64)i);
  228. }
  229. inline void writeF1000(u8 *data, f32 i)
  230. {
  231. assert(i >= F1000_MIN && i <= F1000_MAX);
  232. writeS32(data, i * FIXEDPOINT_FACTOR);
  233. }
  234. inline void writeARGB8(u8 *data, video::SColor p)
  235. {
  236. writeU32(data, p.color);
  237. }
  238. inline void writeV2S16(u8 *data, v2s16 p)
  239. {
  240. writeS16(&data[0], p.X);
  241. writeS16(&data[2], p.Y);
  242. }
  243. inline void writeV3S16(u8 *data, v3s16 p)
  244. {
  245. writeS16(&data[0], p.X);
  246. writeS16(&data[2], p.Y);
  247. writeS16(&data[4], p.Z);
  248. }
  249. inline void writeV2S32(u8 *data, v2s32 p)
  250. {
  251. writeS32(&data[0], p.X);
  252. writeS32(&data[4], p.Y);
  253. }
  254. inline void writeV3S32(u8 *data, v3s32 p)
  255. {
  256. writeS32(&data[0], p.X);
  257. writeS32(&data[4], p.Y);
  258. writeS32(&data[8], p.Z);
  259. }
  260. inline void writeV2F1000(u8 *data, v2f p)
  261. {
  262. writeF1000(&data[0], p.X);
  263. writeF1000(&data[4], p.Y);
  264. }
  265. inline void writeV3F1000(u8 *data, v3f p)
  266. {
  267. writeF1000(&data[0], p.X);
  268. writeF1000(&data[4], p.Y);
  269. writeF1000(&data[8], p.Z);
  270. }
  271. ////
  272. //// Iostream wrapper for data read/write
  273. ////
  274. #define MAKE_STREAM_READ_FXN(T, N, S) \
  275. inline T read ## N(std::istream &is) \
  276. { \
  277. char buf[S] = {0}; \
  278. is.read(buf, sizeof(buf)); \
  279. return read ## N((u8 *)buf); \
  280. }
  281. #define MAKE_STREAM_WRITE_FXN(T, N, S) \
  282. inline void write ## N(std::ostream &os, T val) \
  283. { \
  284. char buf[S]; \
  285. write ## N((u8 *)buf, val); \
  286. os.write(buf, sizeof(buf)); \
  287. }
  288. MAKE_STREAM_READ_FXN(u8, U8, 1);
  289. MAKE_STREAM_READ_FXN(u16, U16, 2);
  290. MAKE_STREAM_READ_FXN(u32, U32, 4);
  291. MAKE_STREAM_READ_FXN(u64, U64, 8);
  292. MAKE_STREAM_READ_FXN(s8, S8, 1);
  293. MAKE_STREAM_READ_FXN(s16, S16, 2);
  294. MAKE_STREAM_READ_FXN(s32, S32, 4);
  295. MAKE_STREAM_READ_FXN(s64, S64, 8);
  296. MAKE_STREAM_READ_FXN(f32, F1000, 4);
  297. MAKE_STREAM_READ_FXN(v2s16, V2S16, 4);
  298. MAKE_STREAM_READ_FXN(v3s16, V3S16, 6);
  299. MAKE_STREAM_READ_FXN(v2s32, V2S32, 8);
  300. MAKE_STREAM_READ_FXN(v3s32, V3S32, 12);
  301. MAKE_STREAM_READ_FXN(v2f, V2F1000, 8);
  302. MAKE_STREAM_READ_FXN(v3f, V3F1000, 12);
  303. MAKE_STREAM_READ_FXN(video::SColor, ARGB8, 4);
  304. MAKE_STREAM_WRITE_FXN(u8, U8, 1);
  305. MAKE_STREAM_WRITE_FXN(u16, U16, 2);
  306. MAKE_STREAM_WRITE_FXN(u32, U32, 4);
  307. MAKE_STREAM_WRITE_FXN(u64, U64, 8);
  308. MAKE_STREAM_WRITE_FXN(s8, S8, 1);
  309. MAKE_STREAM_WRITE_FXN(s16, S16, 2);
  310. MAKE_STREAM_WRITE_FXN(s32, S32, 4);
  311. MAKE_STREAM_WRITE_FXN(s64, S64, 8);
  312. MAKE_STREAM_WRITE_FXN(f32, F1000, 4);
  313. MAKE_STREAM_WRITE_FXN(v2s16, V2S16, 4);
  314. MAKE_STREAM_WRITE_FXN(v3s16, V3S16, 6);
  315. MAKE_STREAM_WRITE_FXN(v2s32, V2S32, 8);
  316. MAKE_STREAM_WRITE_FXN(v3s32, V3S32, 12);
  317. MAKE_STREAM_WRITE_FXN(v2f, V2F1000, 8);
  318. MAKE_STREAM_WRITE_FXN(v3f, V3F1000, 12);
  319. MAKE_STREAM_WRITE_FXN(video::SColor, ARGB8, 4);
  320. ////
  321. //// More serialization stuff
  322. ////
  323. // Creates a string with the length as the first two bytes
  324. std::string serializeString(const std::string &plain);
  325. // Creates a string with the length as the first two bytes from wide string
  326. std::string serializeWideString(const std::wstring &plain);
  327. // Reads a string with the length as the first two bytes
  328. std::string deSerializeString(std::istream &is);
  329. // Reads a wide string with the length as the first two bytes
  330. std::wstring deSerializeWideString(std::istream &is);
  331. // Creates a string with the length as the first four bytes
  332. std::string serializeLongString(const std::string &plain);
  333. // Reads a string with the length as the first four bytes
  334. std::string deSerializeLongString(std::istream &is);
  335. // Creates a string encoded in JSON format (almost equivalent to a C string literal)
  336. std::string serializeJsonString(const std::string &plain);
  337. // Reads a string encoded in JSON format
  338. std::string deSerializeJsonString(std::istream &is);
  339. // If the string contains spaces, quotes or control characters, encodes as JSON.
  340. // Else returns the string unmodified.
  341. std::string serializeJsonStringIfNeeded(const std::string &s);
  342. // Parses a string serialized by serializeJsonStringIfNeeded.
  343. std::string deSerializeJsonStringIfNeeded(std::istream &is);
  344. // Creates a string consisting of the hexadecimal representation of `data`
  345. std::string serializeHexString(const std::string &data, bool insert_spaces=false);
  346. // Creates a string containing comma delimited values of a struct whose layout is
  347. // described by the parameter format
  348. bool serializeStructToString(std::string *out,
  349. std::string format, void *value);
  350. // Reads a comma delimited string of values into a struct whose layout is
  351. // decribed by the parameter format
  352. bool deSerializeStringToStruct(std::string valstr,
  353. std::string format, void *out, size_t olen);
  354. ////
  355. //// BufReader
  356. ////
  357. #define MAKE_BUFREADER_GETNOEX_FXN(T, N, S) \
  358. inline bool get ## N ## NoEx(T *val) \
  359. { \
  360. if (pos + S > size) \
  361. return false; \
  362. *val = read ## N(data + pos); \
  363. pos += S; \
  364. return true; \
  365. }
  366. #define MAKE_BUFREADER_GET_FXN(T, N) \
  367. inline T get ## N() \
  368. { \
  369. T val; \
  370. if (!get ## N ## NoEx(&val)) \
  371. throw SerializationError("Attempted read past end of data"); \
  372. return val; \
  373. }
  374. class BufReader {
  375. public:
  376. BufReader(const u8 *data_, size_t size_) :
  377. data(data_),
  378. size(size_)
  379. {
  380. }
  381. MAKE_BUFREADER_GETNOEX_FXN(u8, U8, 1);
  382. MAKE_BUFREADER_GETNOEX_FXN(u16, U16, 2);
  383. MAKE_BUFREADER_GETNOEX_FXN(u32, U32, 4);
  384. MAKE_BUFREADER_GETNOEX_FXN(u64, U64, 8);
  385. MAKE_BUFREADER_GETNOEX_FXN(s8, S8, 1);
  386. MAKE_BUFREADER_GETNOEX_FXN(s16, S16, 2);
  387. MAKE_BUFREADER_GETNOEX_FXN(s32, S32, 4);
  388. MAKE_BUFREADER_GETNOEX_FXN(s64, S64, 8);
  389. MAKE_BUFREADER_GETNOEX_FXN(f32, F1000, 4);
  390. MAKE_BUFREADER_GETNOEX_FXN(v2s16, V2S16, 4);
  391. MAKE_BUFREADER_GETNOEX_FXN(v3s16, V3S16, 6);
  392. MAKE_BUFREADER_GETNOEX_FXN(v2s32, V2S32, 8);
  393. MAKE_BUFREADER_GETNOEX_FXN(v3s32, V3S32, 12);
  394. MAKE_BUFREADER_GETNOEX_FXN(v2f, V2F1000, 8);
  395. MAKE_BUFREADER_GETNOEX_FXN(v3f, V3F1000, 12);
  396. MAKE_BUFREADER_GETNOEX_FXN(video::SColor, ARGB8, 4);
  397. bool getStringNoEx(std::string *val);
  398. bool getWideStringNoEx(std::wstring *val);
  399. bool getLongStringNoEx(std::string *val);
  400. bool getRawDataNoEx(void *data, size_t len);
  401. MAKE_BUFREADER_GET_FXN(u8, U8);
  402. MAKE_BUFREADER_GET_FXN(u16, U16);
  403. MAKE_BUFREADER_GET_FXN(u32, U32);
  404. MAKE_BUFREADER_GET_FXN(u64, U64);
  405. MAKE_BUFREADER_GET_FXN(s8, S8);
  406. MAKE_BUFREADER_GET_FXN(s16, S16);
  407. MAKE_BUFREADER_GET_FXN(s32, S32);
  408. MAKE_BUFREADER_GET_FXN(s64, S64);
  409. MAKE_BUFREADER_GET_FXN(f32, F1000);
  410. MAKE_BUFREADER_GET_FXN(v2s16, V2S16);
  411. MAKE_BUFREADER_GET_FXN(v3s16, V3S16);
  412. MAKE_BUFREADER_GET_FXN(v2s32, V2S32);
  413. MAKE_BUFREADER_GET_FXN(v3s32, V3S32);
  414. MAKE_BUFREADER_GET_FXN(v2f, V2F1000);
  415. MAKE_BUFREADER_GET_FXN(v3f, V3F1000);
  416. MAKE_BUFREADER_GET_FXN(video::SColor, ARGB8);
  417. MAKE_BUFREADER_GET_FXN(std::string, String);
  418. MAKE_BUFREADER_GET_FXN(std::wstring, WideString);
  419. MAKE_BUFREADER_GET_FXN(std::string, LongString);
  420. inline void getRawData(void *val, size_t len)
  421. {
  422. if (!getRawDataNoEx(val, len))
  423. throw SerializationError("Attempted read past end of data");
  424. }
  425. inline size_t remaining()
  426. {
  427. assert(pos <= size);
  428. return size - pos;
  429. }
  430. const u8 *data;
  431. size_t size;
  432. size_t pos = 0;
  433. };
  434. #undef MAKE_BUFREADER_GET_FXN
  435. #undef MAKE_BUFREADER_GETNOEX_FXN
  436. ////
  437. //// Vector-based write routines
  438. ////
  439. inline void putU8(std::vector<u8> *dest, u8 val)
  440. {
  441. dest->push_back((val >> 0) & 0xFF);
  442. }
  443. inline void putU16(std::vector<u8> *dest, u16 val)
  444. {
  445. dest->push_back((val >> 8) & 0xFF);
  446. dest->push_back((val >> 0) & 0xFF);
  447. }
  448. inline void putU32(std::vector<u8> *dest, u32 val)
  449. {
  450. dest->push_back((val >> 24) & 0xFF);
  451. dest->push_back((val >> 16) & 0xFF);
  452. dest->push_back((val >> 8) & 0xFF);
  453. dest->push_back((val >> 0) & 0xFF);
  454. }
  455. inline void putU64(std::vector<u8> *dest, u64 val)
  456. {
  457. dest->push_back((val >> 56) & 0xFF);
  458. dest->push_back((val >> 48) & 0xFF);
  459. dest->push_back((val >> 40) & 0xFF);
  460. dest->push_back((val >> 32) & 0xFF);
  461. dest->push_back((val >> 24) & 0xFF);
  462. dest->push_back((val >> 16) & 0xFF);
  463. dest->push_back((val >> 8) & 0xFF);
  464. dest->push_back((val >> 0) & 0xFF);
  465. }
  466. inline void putS8(std::vector<u8> *dest, s8 val)
  467. {
  468. putU8(dest, val);
  469. }
  470. inline void putS16(std::vector<u8> *dest, s16 val)
  471. {
  472. putU16(dest, val);
  473. }
  474. inline void putS32(std::vector<u8> *dest, s32 val)
  475. {
  476. putU32(dest, val);
  477. }
  478. inline void putS64(std::vector<u8> *dest, s64 val)
  479. {
  480. putU64(dest, val);
  481. }
  482. inline void putF1000(std::vector<u8> *dest, f32 val)
  483. {
  484. putS32(dest, val * FIXEDPOINT_FACTOR);
  485. }
  486. inline void putV2S16(std::vector<u8> *dest, v2s16 val)
  487. {
  488. putS16(dest, val.X);
  489. putS16(dest, val.Y);
  490. }
  491. inline void putV3S16(std::vector<u8> *dest, v3s16 val)
  492. {
  493. putS16(dest, val.X);
  494. putS16(dest, val.Y);
  495. putS16(dest, val.Z);
  496. }
  497. inline void putV2S32(std::vector<u8> *dest, v2s32 val)
  498. {
  499. putS32(dest, val.X);
  500. putS32(dest, val.Y);
  501. }
  502. inline void putV3S32(std::vector<u8> *dest, v3s32 val)
  503. {
  504. putS32(dest, val.X);
  505. putS32(dest, val.Y);
  506. putS32(dest, val.Z);
  507. }
  508. inline void putV2F1000(std::vector<u8> *dest, v2f val)
  509. {
  510. putF1000(dest, val.X);
  511. putF1000(dest, val.Y);
  512. }
  513. inline void putV3F1000(std::vector<u8> *dest, v3f val)
  514. {
  515. putF1000(dest, val.X);
  516. putF1000(dest, val.Y);
  517. putF1000(dest, val.Z);
  518. }
  519. inline void putARGB8(std::vector<u8> *dest, video::SColor val)
  520. {
  521. putU32(dest, val.color);
  522. }
  523. inline void putString(std::vector<u8> *dest, const std::string &val)
  524. {
  525. if (val.size() > STRING_MAX_LEN)
  526. throw SerializationError("String too long");
  527. putU16(dest, val.size());
  528. dest->insert(dest->end(), val.begin(), val.end());
  529. }
  530. inline void putWideString(std::vector<u8> *dest, const std::wstring &val)
  531. {
  532. if (val.size() > WIDE_STRING_MAX_LEN)
  533. throw SerializationError("String too long");
  534. putU16(dest, val.size());
  535. for (size_t i = 0; i != val.size(); i++)
  536. putU16(dest, val[i]);
  537. }
  538. inline void putLongString(std::vector<u8> *dest, const std::string &val)
  539. {
  540. if (val.size() > LONG_STRING_MAX_LEN)
  541. throw SerializationError("String too long");
  542. putU32(dest, val.size());
  543. dest->insert(dest->end(), val.begin(), val.end());
  544. }
  545. inline void putRawData(std::vector<u8> *dest, const void *src, size_t len)
  546. {
  547. dest->insert(dest->end(), (u8 *)src, (u8 *)src + len);
  548. }