rtlqstr.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682
  1. /*##############################################################################
  2. HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems®.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. ############################################################################## */
  13. #include "limits.h"
  14. #include "platform.h"
  15. #include <math.h>
  16. #include <stdio.h>
  17. #include <algorithm>
  18. #include "jexcept.hpp"
  19. #include "jmisc.hpp"
  20. #include "jutil.hpp"
  21. #include "jlib.hpp"
  22. #include "jptree.hpp"
  23. #include "eclrtl.hpp"
  24. #include "rtlbcd.hpp"
  25. #include "jlog.hpp"
  26. #include "jmd5.hpp"
  27. //=============================================================================
  28. // Miscellaneous string functions...
  29. inline unsigned QStrLength(unsigned size) { return (size * 4) / 3; }
  30. inline unsigned QStrSize(unsigned length) { return (length + 1) * 3 / 4; }
  31. byte lastQStrByteMask(unsigned tlen)
  32. {
  33. switch (tlen & 3)
  34. {
  35. case 1:
  36. return 0xfc;
  37. case 2:
  38. return 0xf0;
  39. case 3:
  40. return 0xc0;
  41. }
  42. return 0xff;
  43. }
  44. inline byte expandQChar(byte c)
  45. {
  46. return ' ' + c;
  47. }
  48. #if 1
  49. static const char compressXlat[256] =
  50. {
  51. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x00
  52. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  53. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x10
  54. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  55. 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // 0x20
  56. 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
  57. 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, // 0x30
  58. 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
  59. 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, // 0x40
  60. 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
  61. 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, // 0x50
  62. 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
  63. 0x00, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, // 0x60
  64. 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
  65. 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, // 0x70
  66. 0x38, 0x39, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00,
  67. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x80
  68. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  69. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x90
  70. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  71. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xA0
  72. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  73. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xB0
  74. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  75. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xC0
  76. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xD0
  78. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  79. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xE0
  80. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  81. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xF0
  82. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  83. };
  84. #define compressQChar(c) compressXlat[(byte)c]
  85. #else
  86. inline byte compressQChar(byte c)
  87. {
  88. if (c > 0x20)
  89. {
  90. if (c < 0x60)
  91. return c - 0x20;
  92. if ((c >= 'a') && (c <= 'z'))
  93. return c - 0x40;
  94. }
  95. return 0;
  96. }
  97. #endif
  98. byte getQChar(const byte * buffer, size32_t index)
  99. {
  100. size32_t offset = (index * 3) / 4;
  101. switch (index & 3)
  102. {
  103. case 0:
  104. return buffer[offset] >> 2;
  105. case 1:
  106. return ((buffer[offset] & 0x3) << 4) | (buffer[offset+1] >> 4);
  107. case 2:
  108. return ((buffer[offset] & 0xf) << 2) | (buffer[offset+1] >> 6);
  109. case 3:
  110. return (buffer[offset] & 0x3f);
  111. }
  112. return 0;
  113. }
  114. void setQChar(byte * buffer, size32_t index, byte value)
  115. {
  116. size32_t offset = (index * 3) / 4;
  117. byte cur = buffer[offset];
  118. switch (index & 3)
  119. {
  120. case 0:
  121. cur = (cur & 0x03) | value << 2;
  122. break;
  123. case 1:
  124. cur = (cur & 0xFC) | (value >> 4);
  125. buffer[offset+1] = (buffer[offset+1] & 0x0f) | ((value & 0x0F) << 4);
  126. break;
  127. case 2:
  128. cur = (cur & 0xF0) | (value >> 2);
  129. buffer[offset+1] = (buffer[offset+1] & 0x3f) | ((value & 0x03) << 6);
  130. break;
  131. case 3:
  132. cur = (cur & 0xC0) | value;
  133. break;
  134. }
  135. buffer[offset] = cur;
  136. }
  137. //-------------------------------------------------------------------------------------------------------------------
  138. bool incrementQString(byte *buf, size32_t size)
  139. {
  140. int i = size;
  141. while (i--)
  142. {
  143. byte next = getQChar(buf, i);
  144. next = (next + 1) & 0x3F;
  145. setQChar(buf, i, next);
  146. if (next != 0)
  147. return true;
  148. }
  149. return false;
  150. }
  151. bool decrementQString(byte *buf, size32_t size)
  152. {
  153. int i = size;
  154. while (i--)
  155. {
  156. byte next = getQChar(buf, i);
  157. next = (next - 1) & 0x3F;
  158. setQChar(buf, i, next);
  159. if (next != 0x3f)
  160. return true;
  161. }
  162. return false;
  163. }
  164. //---------------------------------------------------------------------------
  165. class QStrReader
  166. {
  167. public:
  168. QStrReader(const byte * _buffer) { buffer = _buffer; curLen = 0; offset = 0; }
  169. byte curQChar()
  170. {
  171. switch (curLen & 3)
  172. {
  173. case 0:
  174. return buffer[offset] >> 2;
  175. case 1:
  176. return ((buffer[offset] & 0x3) << 4) | (buffer[offset+1] >> 4);
  177. case 2:
  178. return ((buffer[offset] & 0xf) << 2) | (buffer[offset+1] >> 6);
  179. case 3:
  180. return (buffer[offset] & 0x3f);
  181. }
  182. return 0;
  183. }
  184. byte nextQChar()
  185. {
  186. byte c = curQChar();
  187. if ((curLen & 3) != 0)
  188. offset++;
  189. curLen++;
  190. return c;
  191. }
  192. byte prevQChar()
  193. {
  194. curLen--;
  195. if ((curLen & 3) != 0)
  196. offset--;
  197. return curQChar();
  198. }
  199. char nextChar()
  200. {
  201. return expandQChar(nextQChar());
  202. }
  203. inline void seek(unsigned pos)
  204. {
  205. curLen = pos;
  206. offset = (pos* 3)/4;
  207. }
  208. protected:
  209. const byte * buffer;
  210. unsigned curLen;
  211. unsigned offset;
  212. };
  213. //---------------------------------------------------------------------------
  214. class QStrBuilder
  215. {
  216. public:
  217. QStrBuilder(void * _buffer) { buffer = (byte *)_buffer; curLen = 0; pending = 0; }
  218. void appendChar(char next)
  219. {
  220. appendQChar(compressQChar(next));
  221. }
  222. void appendCharN(unsigned len, char next)
  223. {
  224. byte c = compressQChar(next);
  225. while (len--)
  226. appendQChar(c);
  227. }
  228. void appendQStr(unsigned len, const char * text)
  229. {
  230. QStrReader reader((const byte *)text);
  231. while (len--)
  232. appendQChar(reader.nextQChar());
  233. }
  234. void appendStr(unsigned len, const char * text)
  235. {
  236. while (len--)
  237. appendChar(*text++);
  238. }
  239. void appendQChar(byte c)
  240. {
  241. switch (curLen & 3)
  242. {
  243. case 0:
  244. pending = c << 2;
  245. break;
  246. case 1:
  247. *buffer++ = pending | (c >> 4);
  248. pending = c << 4;
  249. break;
  250. case 2:
  251. *buffer++ = pending | (c >> 2);
  252. pending = c << 6;
  253. break;
  254. case 3:
  255. *buffer++ = pending | c;
  256. pending = 0;
  257. break;
  258. }
  259. curLen++;
  260. }
  261. void finish(unsigned max, byte fill)
  262. {
  263. while (curLen < max)
  264. appendQChar(fill & 0x3F);
  265. //force a final character to be output, but never writes too many.
  266. appendQChar(fill & 0x3F);
  267. //curLen is now undefined.
  268. }
  269. protected:
  270. byte * buffer;
  271. unsigned curLen;
  272. byte pending;
  273. };
  274. //=============================================================================
  275. void copyQStrRange(unsigned tlen, char * tgt, const char * src, unsigned from, unsigned to)
  276. {
  277. unsigned copylen = to - from;
  278. if ((from & 3) == 0)
  279. {
  280. //can index the qstring directly...
  281. rtlQStrToQStr(tlen, tgt, copylen, src+QStrSize(from));
  282. //make sure the contents are in canonical format
  283. if ((copylen & 3) != 0)
  284. {
  285. unsigned copysize = QStrSize(copylen);
  286. tgt[copysize-1] &= lastQStrByteMask(copylen);
  287. }
  288. }
  289. else if (copylen == 0)
  290. {
  291. memset(tgt, 0, QStrSize(tlen));
  292. }
  293. else
  294. {
  295. //More: Could implement this cleverly by shifting and copying, but not worth it at the moment
  296. unsigned tempSrcLen;
  297. char * tempSrcPtr;
  298. rtlQStrToStrX(tempSrcLen, tempSrcPtr, from+copylen, src);
  299. rtlStrToQStr(tlen, tgt, copylen, tempSrcPtr+from);
  300. rtlFree(tempSrcPtr);
  301. }
  302. }
  303. //-----------------------------------------------------------------------------
  304. unsigned rtlQStrLength(unsigned size) { return QStrLength(size); }
  305. unsigned rtlQStrSize(unsigned length) { return QStrSize(length); }
  306. unsigned rtlTrimQStrLen(size32_t l, const char * t)
  307. {
  308. QStrReader reader((const byte *)t);
  309. reader.seek(l);
  310. while (l && (reader.prevQChar() == 0))
  311. l--;
  312. return l;
  313. }
  314. void rtlStrToQStr(size32_t outlen, char * out, size32_t inlen, const void *in)
  315. {
  316. unsigned outSize = QStrSize(outlen);
  317. if (inlen >= outlen)
  318. inlen = outlen;
  319. else
  320. {
  321. size32_t size = QStrSize(inlen);
  322. memset(out+size, 0, outSize-size);
  323. }
  324. byte * curIn = (byte *)in;
  325. byte * endIn = curIn + inlen;
  326. byte * curOut = (byte *)out;
  327. while ((endIn-curIn)>=4)
  328. {
  329. byte c0 = compressQChar(curIn[0]);
  330. byte c1 = compressQChar(curIn[1]);
  331. byte c2 = compressQChar(curIn[2]);
  332. byte c3 = compressQChar(curIn[3]);
  333. curOut[0] = (c0 << 2) | (c1 >> 4);
  334. curOut[1] = (c1 << 4) | (c2 >> 2);
  335. curOut[2] = (c2 << 6) | c3;
  336. curIn += 4;
  337. curOut += 3;
  338. }
  339. byte c0;
  340. byte c1 = 0;
  341. byte c2 = 0;
  342. switch (endIn - curIn)
  343. {
  344. case 3:
  345. c2 = compressQChar(curIn[2]);
  346. curOut[2] = (c2 << 6);
  347. //fallthrough
  348. case 2:
  349. c1 = compressQChar(curIn[1]);
  350. curOut[1] = (c1 << 4) | (c2 >> 2);
  351. //fall through
  352. case 1:
  353. c0 = compressQChar(curIn[0]);
  354. curOut[0] = (c0 << 2) | (c1 >> 4);
  355. break;
  356. case 0:
  357. break;
  358. default:
  359. UNIMPLEMENTED;
  360. }
  361. }
  362. void rtlStrToQStrX(size32_t & outlen, char * & out, size32_t inlen, const void *in)
  363. {
  364. outlen = inlen;
  365. out = (char *)malloc(QStrSize(inlen));
  366. rtlStrToQStr(inlen, out, inlen, in);
  367. }
  368. void rtlStrToQStrNX(size32_t & outlen, char * & out, size32_t inlen, const void * in, size32_t logicalLength)
  369. {
  370. outlen = logicalLength;
  371. out = (char *)malloc(QStrSize(logicalLength));
  372. rtlStrToQStr(logicalLength, out, inlen, in);
  373. }
  374. void rtlQStrToData(size32_t outlen, void * out, size32_t inlen, const char *in)
  375. {
  376. if (inlen >= outlen)
  377. inlen = outlen;
  378. else
  379. memset((char *)out+inlen, 0, outlen-inlen);
  380. rtlQStrToStr(inlen, (char *)out, inlen, in);
  381. }
  382. void rtlQStrToDataX(size32_t & outlen, void * & out, size32_t inlen, const char *in)
  383. {
  384. outlen = inlen;
  385. out = (char *)malloc(inlen);
  386. rtlQStrToStr(inlen, (char *)out, inlen, in);
  387. }
  388. void rtlQStrToVStr(size32_t outlen, char * out, size32_t inlen, const char *in)
  389. {
  390. out[--outlen] = 0;
  391. if (inlen >= outlen)
  392. inlen = outlen;
  393. else
  394. memset((char *)out+inlen, 0, outlen-inlen);
  395. rtlQStrToStr(inlen, out, inlen, in);
  396. }
  397. //NB: Need to be careful when expanding qstring3 to string3, that 4 bytes aren't written.
  398. void rtlQStrToStr(size32_t outlen, char * out, size32_t inlen, const char * in)
  399. {
  400. if (inlen < outlen)
  401. {
  402. memset(out+inlen, ' ', outlen-inlen);
  403. outlen = inlen;
  404. }
  405. const byte * curIn = (const byte *)in;
  406. byte * curOut = (byte *)out;
  407. byte * endOut = curOut + outlen;
  408. while ((endOut-curOut)>=4)
  409. {
  410. byte c0 = curIn[0];
  411. byte c1 = curIn[1];
  412. byte c2 = curIn[2];
  413. curOut[0] = expandQChar(c0 >> 2);
  414. curOut[1] = expandQChar(((c0 & 0x3) << 4) | (c1 >> 4));
  415. curOut[2] = expandQChar(((c1 & 0xF) << 2) | (c2 >> 6));
  416. curOut[3] = expandQChar(c2 & 0x3F);
  417. curIn += 3;
  418. curOut += 4;
  419. }
  420. switch (endOut - curOut)
  421. {
  422. case 3:
  423. curOut[2] = expandQChar(((curIn[1] & 0xF) << 2) | (curIn[2] >> 6));
  424. //fallthrough
  425. case 2:
  426. curOut[1] = expandQChar(((curIn[0] & 0x3) << 4) | (curIn[1] >> 4));
  427. //fallthrough
  428. case 1:
  429. curOut[0] = expandQChar(curIn[0] >> 2);
  430. break;
  431. case 0:
  432. break;
  433. default:
  434. UNIMPLEMENTED;
  435. }
  436. }
  437. void rtlQStrToStrX(size32_t & outlen, char * & out, size32_t inlen, const char *in)
  438. {
  439. outlen = inlen;
  440. out = (char *)malloc(inlen);
  441. rtlQStrToStr(inlen, out, inlen, in);
  442. }
  443. void rtlQStrToQStr(size32_t outlen, char * out, size32_t inlen, const char * in)
  444. {
  445. size32_t inSize = QStrSize(inlen);
  446. size32_t outSize = QStrSize(outlen);
  447. if (inSize >= outSize)
  448. {
  449. memcpy_iflen(out, in, outSize);
  450. }
  451. else
  452. {
  453. memcpy_iflen(out, in, inSize);
  454. memset(out+inSize, 0, outSize-inSize);
  455. }
  456. }
  457. void rtlQStrToQStrX(unsigned & outlen, char * & out, unsigned inlen, const char * in)
  458. {
  459. size32_t inSize = QStrSize(inlen);
  460. char * data = (char *)malloc(inSize);
  461. memcpy_iflen(data, in, inSize);
  462. outlen = inlen;
  463. out = data;
  464. }
  465. int rtlCompareQStrQStr(size32_t llen, const void * left, size32_t rlen, const void * right)
  466. {
  467. size32_t lsize = QStrSize(llen);
  468. size32_t rsize = QStrSize(rlen);
  469. if (lsize < rsize)
  470. {
  471. int ret = memcmp_iflen(left, right, lsize);
  472. if (ret == 0)
  473. {
  474. const byte * r = (const byte *)right;
  475. while (lsize < rsize)
  476. {
  477. if (r[lsize])
  478. return -1;
  479. lsize++;
  480. }
  481. }
  482. return ret;
  483. }
  484. int ret = memcmp_iflen(left, right, rsize);
  485. if (ret == 0)
  486. {
  487. const byte * l = (const byte *)left;
  488. while (lsize > rsize)
  489. {
  490. if (l[rsize])
  491. return +1;
  492. rsize++;
  493. }
  494. }
  495. return ret;
  496. }
  497. int rtlSafeCompareQStrQStr(size32_t llen, const void * left, size32_t rlen, const void * right)
  498. {
  499. QStrReader leftIter((const byte *)left);
  500. QStrReader rightIter((const byte *)right);
  501. size32_t len = std::min(llen, rlen);
  502. for (unsigned i =0; i < len; i++)
  503. {
  504. int diff = (int)leftIter.nextQChar() - (int)rightIter.nextQChar();
  505. if (diff != 0)
  506. return diff;
  507. }
  508. if (len < llen)
  509. {
  510. while (len++ < llen)
  511. {
  512. if (leftIter.nextQChar() != 0)
  513. return +1;
  514. }
  515. }
  516. else
  517. {
  518. while (len++ < rlen)
  519. {
  520. if (rightIter.nextQChar() != 0)
  521. return -1;
  522. }
  523. }
  524. return 0;
  525. }
  526. void rtlDecPushQStr(size32_t len, const void * data)
  527. {
  528. char * strData = (char *)alloca(len);
  529. rtlQStrToStr(len, strData, len, (const char *)data);
  530. DecPushString(len, strData);
  531. }
  532. bool rtlQStrToBool(size32_t inlen, const char *in)
  533. {
  534. unsigned size = QStrSize(inlen);
  535. while (size--)
  536. if (in[size])
  537. return true;
  538. return false;
  539. }
  540. //---------------------------------------------------------------------------
  541. ECLRTL_API void rtlCreateQStrRange(size32_t & outlen, char * & out, unsigned fieldLen, unsigned compareLen, size32_t len, const char * qstr, byte fill)
  542. {
  543. //NB: Keep in sync with rtlCreateRange()
  544. if (compareLen > fieldLen)
  545. {
  546. if ((int)compareLen >= 0)
  547. {
  548. //x[1..m] = y, m is larger than fieldLen, so truncate to fieldLen
  549. compareLen = fieldLen;
  550. }
  551. else
  552. compareLen = 0; // probably m[1..-1] or something silly
  553. }
  554. //y has been trimmed when this function is called. If y is longer than field length, then it is never going to match
  555. //so change the search range to FF,FF,FF .. 00.00.00 which will then never match.
  556. if (len > fieldLen)
  557. {
  558. compareLen = 0;
  559. fill = (fill == 0) ? 255 : 0;
  560. }
  561. outlen = fieldLen;
  562. out = (char *)malloc(QStrSize(fieldLen));
  563. QStrBuilder builder(out);
  564. if (len >= compareLen)
  565. builder.appendQStr(compareLen, qstr);
  566. else
  567. {
  568. builder.appendQStr(len, qstr);
  569. builder.appendCharN(compareLen-len, ' ');
  570. }
  571. builder.finish(fieldLen, fill);
  572. }
  573. ECLRTL_API void rtlCreateQStrRangeLow(size32_t & outlen, char * & out, unsigned fieldLen, unsigned compareLen, size32_t len, const char * qstr)
  574. {
  575. len = rtlTrimQStrLen(len, qstr);
  576. rtlCreateQStrRange(outlen, out, fieldLen, compareLen, len, qstr, 0);
  577. }
  578. ECLRTL_API void rtlCreateQStrRangeHigh(size32_t & outlen, char * & out, unsigned fieldLen, unsigned compareLen, size32_t len, const char * qstr)
  579. {
  580. len = rtlTrimQStrLen(len, qstr);
  581. rtlCreateQStrRange(outlen, out, fieldLen, compareLen, len, qstr, 255);
  582. }
  583. void serializeQStrX(size32_t len, const char * data, MemoryBuffer &out)
  584. {
  585. out.append(len).append(QStrSize(len), data);
  586. }
  587. void deserializeQStrX(size32_t & len, char * & data, MemoryBuffer &in)
  588. {
  589. free(data);
  590. in.read(sizeof(len), &len);
  591. unsigned size = QStrSize(len);
  592. data = (char *)malloc(size);
  593. in.read(size, data);
  594. }