thorxmlwrite.cpp 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002
  1. /*##############################################################################
  2. Copyright (C) 2011 HPCC Systems.
  3. All rights reserved. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU Affero General Public License as
  5. published by the Free Software Foundation, either version 3 of the
  6. License, or (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU Affero General Public License for more details.
  11. You should have received a copy of the GNU Affero General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. ############################################################################## */
  14. #include "platform.h"
  15. #include "jlib.hpp"
  16. #include "thorxmlwrite.hpp"
  17. #include "eclrtl.hpp"
  18. #include "rtlkey.hpp"
  19. #include "eclhelper.hpp"
  20. #include "deftype.hpp"
  21. #include "bcd.hpp"
  22. CommonXmlWriter::CommonXmlWriter(unsigned _flags, unsigned initialIndent, IXmlStreamFlusher *_flusher)
  23. {
  24. flusher = _flusher;
  25. flags = _flags;
  26. indent = initialIndent;
  27. nestLimit = flags & XWFnoindent ? (unsigned) -1 : 0;
  28. tagClosed = true;
  29. }
  30. CommonXmlWriter::~CommonXmlWriter()
  31. {
  32. flush(true);
  33. }
  34. CommonXmlWriter & CommonXmlWriter::clear()
  35. {
  36. out.clear();
  37. indent = 0;
  38. nestLimit = flags & XWFnoindent ? (unsigned) -1 : 0;
  39. tagClosed = true;
  40. return *this;
  41. }
  42. bool CommonXmlWriter::checkForAttribute(const char * fieldname)
  43. {
  44. if (!tagClosed)
  45. {
  46. if (fieldname && (fieldname[0] == '@'))
  47. return true;
  48. closeTag();
  49. }
  50. return false;
  51. }
  52. void CommonXmlWriter::closeTag()
  53. {
  54. if (!tagClosed)
  55. {
  56. out.append(">");
  57. if (!nestLimit)
  58. out.newline();
  59. tagClosed = true;
  60. }
  61. flush(false);
  62. }
  63. void CommonXmlWriter::outputQuoted(const char *text)
  64. {
  65. out.append(text);
  66. }
  67. void CommonXmlWriter::outputString(unsigned len, const char *field, const char *fieldname)
  68. {
  69. if (flags & XWFtrim)
  70. len = rtlTrimStrLen(len, field);
  71. if ((flags & XWFopt) && (rtlTrimStrLen(len, field) == 0))
  72. return;
  73. if (checkForAttribute(fieldname))
  74. outputXmlAttrString(len, field, fieldname+1, out);
  75. else
  76. {
  77. if (!nestLimit)
  78. out.pad(indent);
  79. outputXmlString(len, field, fieldname, out);
  80. if (!nestLimit)
  81. out.newline();
  82. }
  83. }
  84. void CommonXmlWriter::outputQString(unsigned len, const char *field, const char *fieldname)
  85. {
  86. MemoryAttr tempBuffer;
  87. char * temp;
  88. if (len <= 100)
  89. temp = (char *)alloca(len);
  90. else
  91. temp = (char *)tempBuffer.allocate(len);
  92. rtlQStrToStr(len, temp, len, field);
  93. outputString(len, temp, fieldname);
  94. }
  95. void CommonXmlWriter::outputBool(bool field, const char *fieldname)
  96. {
  97. if (checkForAttribute(fieldname))
  98. outputXmlAttrBool(field, fieldname+1, out);
  99. else
  100. {
  101. if (!nestLimit)
  102. out.pad(indent);
  103. outputXmlBool(field, fieldname, out);
  104. if (!nestLimit)
  105. out.newline();
  106. }
  107. }
  108. void CommonXmlWriter::outputData(unsigned len, const void *field, const char *fieldname)
  109. {
  110. if (checkForAttribute(fieldname))
  111. outputXmlAttrData(len, field, fieldname+1, out);
  112. else
  113. {
  114. if (!nestLimit)
  115. out.pad(indent);
  116. outputXmlData(len, field, fieldname, out);
  117. if (!nestLimit)
  118. out.newline();
  119. }
  120. }
  121. void CommonXmlWriter::outputInt(__int64 field, const char *fieldname)
  122. {
  123. if (checkForAttribute(fieldname))
  124. outputXmlAttrInt(field, fieldname+1, out);
  125. else
  126. {
  127. if (!nestLimit)
  128. out.pad(indent);
  129. outputXmlInt(field, fieldname, out);
  130. if (!nestLimit)
  131. out.newline();
  132. }
  133. }
  134. void CommonXmlWriter::outputUInt(unsigned __int64 field, const char *fieldname)
  135. {
  136. if (checkForAttribute(fieldname))
  137. outputXmlAttrUInt(field, fieldname+1, out);
  138. else
  139. {
  140. if (!nestLimit)
  141. out.pad(indent);
  142. outputXmlUInt(field, fieldname, out);
  143. if (!nestLimit)
  144. out.newline();
  145. }
  146. }
  147. void CommonXmlWriter::outputReal(double field, const char *fieldname)
  148. {
  149. if (checkForAttribute(fieldname))
  150. outputXmlAttrReal(field, fieldname+1, out);
  151. else
  152. {
  153. if (!nestLimit)
  154. out.pad(indent);
  155. outputXmlReal(field, fieldname, out);
  156. if (!nestLimit)
  157. out.newline();
  158. }
  159. }
  160. void CommonXmlWriter::outputDecimal(const void *field, unsigned size, unsigned precision, const char *fieldname)
  161. {
  162. if (checkForAttribute(fieldname))
  163. outputXmlAttrDecimal(field, size, precision, fieldname+1, out);
  164. else
  165. {
  166. if (!nestLimit)
  167. out.pad(indent);
  168. outputXmlDecimal(field, size, precision, fieldname, out);
  169. if (!nestLimit)
  170. out.newline();
  171. }
  172. }
  173. void CommonXmlWriter::outputUDecimal(const void *field, unsigned size, unsigned precision, const char *fieldname)
  174. {
  175. if (checkForAttribute(fieldname))
  176. outputXmlAttrUDecimal(field, size, precision, fieldname+1, out);
  177. else
  178. {
  179. if (!nestLimit)
  180. out.pad(indent);
  181. outputXmlUDecimal(field, size, precision, fieldname, out);
  182. if (!nestLimit)
  183. out.newline();
  184. }
  185. }
  186. void CommonXmlWriter::outputUnicode(unsigned len, const UChar *field, const char *fieldname)
  187. {
  188. if (flags & XWFtrim)
  189. len = rtlTrimUnicodeStrLen(len, field);
  190. if ((flags & XWFopt) && (rtlTrimUnicodeStrLen(len, field) == 0))
  191. return;
  192. if (checkForAttribute(fieldname))
  193. outputXmlAttrUnicode(len, field, fieldname+1, out);
  194. else
  195. {
  196. if (!nestLimit)
  197. out.pad(indent);
  198. outputXmlUnicode(len, field, fieldname, out);
  199. if (!nestLimit)
  200. out.newline();
  201. }
  202. }
  203. void CommonXmlWriter::outputUtf8(unsigned len, const char *field, const char *fieldname)
  204. {
  205. if (flags & XWFtrim)
  206. len = rtlTrimUtf8StrLen(len, field);
  207. if ((flags & XWFopt) && (rtlTrimUtf8StrLen(len, field) == 0))
  208. return;
  209. if (checkForAttribute(fieldname))
  210. outputXmlAttrUtf8(len, field, fieldname+1, out);
  211. else
  212. {
  213. if (!nestLimit)
  214. out.pad(indent);
  215. outputXmlUtf8(len, field, fieldname, out);
  216. if (!nestLimit)
  217. out.newline();
  218. }
  219. }
  220. void CommonXmlWriter::outputBeginNested(const char *fieldname, bool nestChildren)
  221. {
  222. const char * sep = strchr(fieldname, '/');
  223. if (sep)
  224. {
  225. StringAttr leading(fieldname, sep-fieldname);
  226. outputBeginNested(leading, nestChildren);
  227. outputBeginNested(sep+1, nestChildren);
  228. return;
  229. }
  230. closeTag();
  231. if (!nestLimit)
  232. out.pad(indent);
  233. out.append('<').append(fieldname);
  234. indent += 1;
  235. if (!nestChildren && !nestLimit)
  236. nestLimit = indent;
  237. tagClosed = false;
  238. }
  239. void CommonXmlWriter::outputEndNested(const char *fieldname)
  240. {
  241. const char * sep = strchr(fieldname, '/');
  242. if (sep)
  243. {
  244. StringAttr leading(fieldname, sep-fieldname);
  245. outputEndNested(sep+1);
  246. outputEndNested(leading);
  247. return;
  248. }
  249. if (flags & XWFexpandempty)
  250. closeTag();
  251. if (!tagClosed)
  252. {
  253. out.append("/>");
  254. tagClosed = true;
  255. }
  256. else
  257. {
  258. if (!nestLimit)
  259. out.pad(indent-1);
  260. out.append("</").append(fieldname).append('>');
  261. }
  262. if (indent==nestLimit)
  263. nestLimit = 0;
  264. indent -= 1;
  265. if (!nestLimit)
  266. out.newline();
  267. }
  268. void CommonXmlWriter::outputSetAll()
  269. {
  270. closeTag();
  271. if (!nestLimit)
  272. out.pad(indent);
  273. outputXmlSetAll(out);
  274. if (!nestLimit)
  275. out.newline();
  276. }
  277. //=====================================================================================
  278. inline void outputEncodedXmlString(unsigned len, const char *field, const char *fieldname, StringBuffer &out)
  279. {
  280. if (fieldname)
  281. out.append('<').append(fieldname).append(" xsi:type=\"xsd:string\">");
  282. encodeXML(field, out, 0, len);
  283. if (fieldname)
  284. out.append("</").append(fieldname).append('>');
  285. }
  286. inline void outputEncodedXmlBool(bool field, const char *fieldname, StringBuffer &out)
  287. {
  288. const char * text = field ? "true" : "false";
  289. if (fieldname)
  290. out.append('<').append(fieldname).append(" xsi:type=\"xsd:boolean\">").append(text).append("</").append(fieldname).append('>');
  291. else
  292. out.append(text);
  293. }
  294. static char thorHelperhexchar[] = "0123456789ABCDEF";
  295. inline void outputEncodedXmlData(unsigned len, const void *_field, const char *fieldname, StringBuffer &out)
  296. {
  297. const unsigned char *field = (const unsigned char *) _field;
  298. if (fieldname)
  299. out.append('<').append(fieldname).append(" xsi:type=\"xsd:hexBinary\">");
  300. for (unsigned int i = 0; i < len; i++)
  301. {
  302. out.append(thorHelperhexchar[field[i] >> 4]).append(thorHelperhexchar[field[i] & 0x0f]);
  303. }
  304. if (fieldname)
  305. out.append("</").append(fieldname).append('>');
  306. }
  307. inline void outputEncoded64XmlData(unsigned len, const void *_field, const char *fieldname, StringBuffer &out)
  308. {
  309. if (fieldname)
  310. out.append('<').append(fieldname).append(" xsi:type=\"xsd:base64Binary\">");
  311. JBASE64_Encode(_field, len, out, false);
  312. if (fieldname)
  313. out.append("</").append(fieldname).append('>');
  314. }
  315. inline void outputEncodedXmlInt(__int64 field, const char *fieldname, StringBuffer &out)
  316. {
  317. if (fieldname)
  318. out.append('<').append(fieldname).append(" xsi:type=\"xsd:integer\">").append(field).append("</").append(fieldname).append('>');
  319. else
  320. out.append(field);
  321. }
  322. inline void outputEncodedXmlUInt(unsigned __int64 field, const char *fieldname, StringBuffer &out)
  323. {
  324. if (fieldname)
  325. out.append('<').append(fieldname).append(" xsi:type=\"xsd:nonNegativeInteger\">").append(field).append("</").append(fieldname).append('>');
  326. else
  327. out.append(field);
  328. }
  329. inline void outputEncodedXmlReal(double field, const char *fieldname, StringBuffer &out)
  330. {
  331. if (fieldname)
  332. out.append('<').append(fieldname).append(" xsi:type=\"xsd:double\">").append(field).append("</").append(fieldname).append('>');
  333. else
  334. out.append(field);
  335. }
  336. inline void outputEncodedXmlDecimal(const void *field, unsigned size, unsigned precision, const char *fieldname, StringBuffer &out)
  337. {
  338. char dec[50];
  339. if (fieldname)
  340. out.append('<').append(fieldname).append(" xsi:type=\"xsd:decimal\">");
  341. DecLock();
  342. if (DecValid(true, size*2-1, field))
  343. {
  344. DecPushDecimal(field, size, precision);
  345. DecPopCString(sizeof(dec), dec);
  346. const char *finger = dec;
  347. while(isspace(*finger)) finger++;
  348. out.append(finger);
  349. }
  350. else
  351. out.append("####");
  352. DecUnlock();
  353. if (fieldname)
  354. out.append("</").append(fieldname).append('>');
  355. }
  356. inline void outputEncodedXmlUDecimal(const void *field, unsigned size, unsigned precision, const char *fieldname, StringBuffer &out)
  357. {
  358. char dec[50];
  359. if (fieldname)
  360. out.append('<').append(fieldname).append(" xsi:type=\"xsd:decimal\">");
  361. DecLock();
  362. if (DecValid(false, size*2, field))
  363. {
  364. DecPushUDecimal(field, size, precision);
  365. DecPopCString(sizeof(dec), dec);
  366. const char *finger = dec;
  367. while(isspace(*finger)) finger++;
  368. out.append(finger);
  369. }
  370. else
  371. out.append("####");
  372. DecUnlock();
  373. if (fieldname)
  374. out.append("</").append(fieldname).append('>');
  375. }
  376. inline void outputEncodedXmlUnicode(unsigned len, const UChar *field, const char *fieldname, StringBuffer &out)
  377. {
  378. char * buff = 0;
  379. unsigned bufflen = 0;
  380. rtlUnicodeToCodepageX(bufflen, buff, len, field, "utf-8");
  381. if (fieldname)
  382. out.append('<').append(fieldname).append(" xsi:type=\"xsd:string\">");
  383. encodeXML(buff, out, 0, bufflen, true); // output as UTF-8
  384. if (fieldname)
  385. out.append("</").append(fieldname).append('>');
  386. rtlFree(buff);
  387. }
  388. inline void outputEncodedXmlUtf8(unsigned len, const char *field, const char *fieldname, StringBuffer &out)
  389. {
  390. if (fieldname)
  391. out.append('<').append(fieldname).append(" xsi:type=\"xsd:string\">");
  392. encodeXML(field, out, 0, rtlUtf8Size(len, field), true); // output as UTF-8
  393. if (fieldname)
  394. out.append("</").append(fieldname).append('>');
  395. }
  396. //=====================================================================================
  397. CommonEncodedXmlWriter::CommonEncodedXmlWriter(unsigned _flags, unsigned initialIndent, IXmlStreamFlusher *_flusher)
  398. : CommonXmlWriter(_flags, initialIndent, _flusher)
  399. {
  400. }
  401. void CommonEncodedXmlWriter::outputString(unsigned len, const char *field, const char *fieldname)
  402. {
  403. if (flags & XWFtrim)
  404. len = rtlTrimStrLen(len, field);
  405. if ((flags & XWFopt) && (rtlTrimStrLen(len, field) == 0))
  406. return;
  407. if (checkForAttribute(fieldname))
  408. outputXmlAttrString(len, field, fieldname+1, out);
  409. else
  410. {
  411. if (!nestLimit)
  412. out.pad(indent);
  413. outputEncodedXmlString(len, field, fieldname, out);
  414. if (!nestLimit)
  415. out.newline();
  416. }
  417. }
  418. void CommonEncodedXmlWriter::outputBool(bool field, const char *fieldname)
  419. {
  420. if (checkForAttribute(fieldname))
  421. outputXmlAttrBool(field, fieldname+1, out);
  422. else
  423. {
  424. if (!nestLimit)
  425. out.pad(indent);
  426. outputEncodedXmlBool(field, fieldname, out);
  427. if (!nestLimit)
  428. out.newline();
  429. }
  430. }
  431. void CommonEncodedXmlWriter::outputData(unsigned len, const void *field, const char *fieldname)
  432. {
  433. if (checkForAttribute(fieldname))
  434. outputXmlAttrData(len, field, fieldname+1, out);
  435. else
  436. {
  437. if (!nestLimit)
  438. out.pad(indent);
  439. outputEncodedXmlData(len, field, fieldname, out);
  440. if (!nestLimit)
  441. out.newline();
  442. }
  443. }
  444. void CommonEncodedXmlWriter::outputInt(__int64 field, const char *fieldname)
  445. {
  446. if (checkForAttribute(fieldname))
  447. outputXmlAttrInt(field, fieldname+1, out);
  448. else
  449. {
  450. if (!nestLimit)
  451. out.pad(indent);
  452. outputEncodedXmlInt(field, fieldname, out);
  453. if (!nestLimit)
  454. out.newline();
  455. }
  456. }
  457. void CommonEncodedXmlWriter::outputUInt(unsigned __int64 field, const char *fieldname)
  458. {
  459. if (checkForAttribute(fieldname))
  460. outputXmlAttrUInt(field, fieldname+1, out);
  461. else
  462. {
  463. if (!nestLimit)
  464. out.pad(indent);
  465. outputEncodedXmlUInt(field, fieldname, out);
  466. if (!nestLimit)
  467. out.newline();
  468. }
  469. }
  470. void CommonEncodedXmlWriter::outputReal(double field, const char *fieldname)
  471. {
  472. if (checkForAttribute(fieldname))
  473. outputXmlAttrReal(field, fieldname+1, out);
  474. else
  475. {
  476. if (!nestLimit)
  477. out.pad(indent);
  478. outputEncodedXmlReal(field, fieldname, out);
  479. if (!nestLimit)
  480. out.newline();
  481. }
  482. }
  483. void CommonEncodedXmlWriter::outputDecimal(const void *field, unsigned size, unsigned precision, const char *fieldname)
  484. {
  485. if (checkForAttribute(fieldname))
  486. outputXmlAttrDecimal(field, size, precision, fieldname+1, out);
  487. else
  488. {
  489. if (!nestLimit)
  490. out.pad(indent);
  491. outputEncodedXmlDecimal(field, size, precision, fieldname, out);
  492. if (!nestLimit)
  493. out.newline();
  494. }
  495. }
  496. void CommonEncodedXmlWriter::outputUDecimal(const void *field, unsigned size, unsigned precision, const char *fieldname)
  497. {
  498. if (checkForAttribute(fieldname))
  499. outputXmlAttrUDecimal(field, size, precision, fieldname+1, out);
  500. else
  501. {
  502. if (!nestLimit)
  503. out.pad(indent);
  504. outputEncodedXmlUDecimal(field, size, precision, fieldname, out);
  505. if (!nestLimit)
  506. out.newline();
  507. }
  508. }
  509. void CommonEncodedXmlWriter::outputUnicode(unsigned len, const UChar *field, const char *fieldname)
  510. {
  511. if (flags & XWFtrim)
  512. len = rtlTrimUnicodeStrLen(len, field);
  513. if ((flags & XWFopt) && (rtlTrimUnicodeStrLen(len, field) == 0))
  514. return;
  515. if (checkForAttribute(fieldname))
  516. outputXmlAttrUnicode(len, field, fieldname+1, out);
  517. else
  518. {
  519. if (!nestLimit)
  520. out.pad(indent);
  521. outputEncodedXmlUnicode(len, field, fieldname, out);
  522. if (!nestLimit)
  523. out.newline();
  524. }
  525. }
  526. void CommonEncodedXmlWriter::outputUtf8(unsigned len, const char *field, const char *fieldname)
  527. {
  528. if (flags & XWFtrim)
  529. len = rtlTrimUtf8StrLen(len, field);
  530. if ((flags & XWFopt) && (rtlTrimUtf8StrLen(len, field) == 0))
  531. return;
  532. if (checkForAttribute(fieldname))
  533. outputXmlAttrUtf8(len, field, fieldname+1, out);
  534. else
  535. {
  536. if (!nestLimit)
  537. out.pad(indent);
  538. outputEncodedXmlUtf8(len, field, fieldname, out);
  539. if (!nestLimit)
  540. out.newline();
  541. }
  542. }
  543. //=====================================================================================
  544. CommonEncoded64XmlWriter::CommonEncoded64XmlWriter(unsigned _flags, unsigned initialIndent, IXmlStreamFlusher *_flusher)
  545. : CommonEncodedXmlWriter(_flags, initialIndent, _flusher)
  546. {
  547. }
  548. void CommonEncoded64XmlWriter::outputData(unsigned len, const void *field, const char *fieldname)
  549. {
  550. if (checkForAttribute(fieldname))
  551. outputXmlAttrData(len, field, fieldname+1, out);
  552. else
  553. {
  554. if (!nestLimit)
  555. out.pad(indent);
  556. outputEncoded64XmlData(len, field, fieldname, out);
  557. if (!nestLimit)
  558. out.newline();
  559. }
  560. }
  561. //=====================================================================================
  562. CommonXmlWriter * CreateCommonXmlWriter(unsigned _flags, unsigned _initialIndent, IXmlStreamFlusher *_flusher, XMLWriterType xmlType)
  563. {
  564. switch (xmlType)
  565. {
  566. case WTStandard:
  567. return new CommonXmlWriter(_flags, _initialIndent, _flusher);//standard XML writer
  568. case WTEncodingData64:
  569. return new CommonEncoded64XmlWriter(_flags, _initialIndent, _flusher);//writes xsd type attributes, and all data as base64binary
  570. case WTEncoding:
  571. return new CommonEncodedXmlWriter(_flags, _initialIndent, _flusher);//writes xsd type attributes, and all data as hexBinary
  572. default:
  573. assertex(false);
  574. return NULL;
  575. }
  576. }
  577. //=====================================================================================
  578. SimpleOutputWriter::SimpleOutputWriter()
  579. {
  580. separatorNeeded = false;
  581. }
  582. void SimpleOutputWriter::outputFieldSeparator()
  583. {
  584. if (separatorNeeded)
  585. out.append(',');
  586. separatorNeeded = true;
  587. }
  588. SimpleOutputWriter & SimpleOutputWriter::clear()
  589. {
  590. out.clear();
  591. separatorNeeded = false;
  592. return *this;
  593. }
  594. void SimpleOutputWriter::outputQuoted(const char *text)
  595. {
  596. out.append(text);
  597. }
  598. void SimpleOutputWriter::outputString(unsigned len, const char *field, const char *)
  599. {
  600. outputFieldSeparator();
  601. out.append(len, field);
  602. }
  603. void SimpleOutputWriter::outputQString(unsigned len, const char *field, const char *fieldname)
  604. {
  605. MemoryAttr tempBuffer;
  606. char * temp;
  607. if (len <= 100)
  608. temp = (char *)alloca(len);
  609. else
  610. temp = (char *)tempBuffer.allocate(len);
  611. rtlQStrToStr(len, temp, len, field);
  612. outputString(len, temp, fieldname);
  613. }
  614. void SimpleOutputWriter::outputBool(bool field, const char *)
  615. {
  616. outputFieldSeparator();
  617. outputXmlBool(field, NULL, out);
  618. }
  619. void SimpleOutputWriter::outputData(unsigned len, const void *field, const char *)
  620. {
  621. outputFieldSeparator();
  622. outputXmlData(len, field, NULL, out);
  623. }
  624. void SimpleOutputWriter::outputInt(__int64 field, const char *)
  625. {
  626. outputFieldSeparator();
  627. outputXmlInt(field, NULL, out);
  628. }
  629. void SimpleOutputWriter::outputUInt(unsigned __int64 field, const char *)
  630. {
  631. outputFieldSeparator();
  632. outputXmlUInt(field, NULL, out);
  633. }
  634. void SimpleOutputWriter::outputReal(double field, const char *)
  635. {
  636. outputFieldSeparator();
  637. outputXmlReal(field, NULL, out);
  638. }
  639. void SimpleOutputWriter::outputDecimal(const void *field, unsigned size, unsigned precision, const char *)
  640. {
  641. outputFieldSeparator();
  642. outputXmlDecimal(field, size, precision, NULL, out);
  643. }
  644. void SimpleOutputWriter::outputUDecimal(const void *field, unsigned size, unsigned precision, const char *)
  645. {
  646. outputFieldSeparator();
  647. outputXmlUDecimal(field, size, precision, NULL, out);
  648. }
  649. void SimpleOutputWriter::outputUnicode(unsigned len, const UChar *field, const char *)
  650. {
  651. outputFieldSeparator();
  652. outputXmlUnicode(len, field, NULL, out);
  653. }
  654. void SimpleOutputWriter::outputUtf8(unsigned len, const char *field, const char *)
  655. {
  656. outputFieldSeparator();
  657. outputXmlUtf8(len, field, NULL, out);
  658. }
  659. void SimpleOutputWriter::outputBeginNested(const char *, bool)
  660. {
  661. outputFieldSeparator();
  662. out.append('[');
  663. separatorNeeded = false;
  664. }
  665. void SimpleOutputWriter::outputEndNested(const char *)
  666. {
  667. out.append(']');
  668. separatorNeeded = true;
  669. }
  670. void SimpleOutputWriter::outputSetAll()
  671. {
  672. out.append('*');
  673. }
  674. void SimpleOutputWriter::newline()
  675. {
  676. out.append('\n');
  677. }
  678. //=====================================================================================
  679. CommonFieldProcessor::CommonFieldProcessor(StringBuffer &_result, bool _trim) : result(_result), trim(_trim)
  680. {
  681. }
  682. void CommonFieldProcessor::processString(unsigned len, const char *value, const RtlFieldInfo * field)
  683. {
  684. if (trim)
  685. len = rtlTrimStrLen(len, value);
  686. result.append("'");
  687. outputXmlString(len, value, NULL, result);
  688. result.append("'");
  689. }
  690. void CommonFieldProcessor::processBool(bool value, const RtlFieldInfo * field)
  691. {
  692. outputXmlBool(value, NULL, result);
  693. }
  694. void CommonFieldProcessor::processData(unsigned len, const void *value, const RtlFieldInfo * field)
  695. {
  696. outputXmlData(len, value, NULL, result);
  697. }
  698. void CommonFieldProcessor::processInt(__int64 value, const RtlFieldInfo * field)
  699. {
  700. outputXmlInt(value, NULL, result);
  701. }
  702. void CommonFieldProcessor::processUInt(unsigned __int64 value, const RtlFieldInfo * field)
  703. {
  704. outputXmlUInt(value, NULL, result);
  705. }
  706. void CommonFieldProcessor::processReal(double value, const RtlFieldInfo * field)
  707. {
  708. outputXmlReal(value, NULL, result);
  709. }
  710. void CommonFieldProcessor::processDecimal(const void *value, unsigned digits, unsigned precision, const RtlFieldInfo * field)
  711. {
  712. outputXmlDecimal(value, digits, precision, NULL, result);
  713. }
  714. void CommonFieldProcessor::processUDecimal(const void *value, unsigned digits, unsigned precision, const RtlFieldInfo * field)
  715. {
  716. outputXmlUDecimal(value, digits, precision, NULL, result);
  717. }
  718. void CommonFieldProcessor::processUnicode(unsigned len, const UChar *value, const RtlFieldInfo * field)
  719. {
  720. if (trim)
  721. len = rtlTrimUnicodeStrLen(len, value);
  722. outputXmlUnicode(len, value, NULL, result);
  723. }
  724. void CommonFieldProcessor::processQString(unsigned len, const char *value, const RtlFieldInfo * field)
  725. {
  726. MemoryAttr tempBuffer;
  727. char * temp;
  728. if (len <= 100)
  729. temp = (char *)alloca(len);
  730. else
  731. temp = (char *)tempBuffer.allocate(len);
  732. rtlQStrToStr(len, temp, len, value);
  733. processString(len, temp, field);
  734. }
  735. void CommonFieldProcessor::processSetAll(const RtlFieldInfo * field)
  736. {
  737. result.append("ALL");
  738. }
  739. void CommonFieldProcessor::processUtf8(unsigned len, const char *value, const RtlFieldInfo * field)
  740. {
  741. if (trim)
  742. len = rtlTrimUtf8StrLen(len, value);
  743. outputXmlUtf8(len, value, NULL, result);
  744. }
  745. bool CommonFieldProcessor::processBeginSet(const RtlFieldInfo * field)
  746. {
  747. result.append('[');
  748. return true;
  749. }
  750. bool CommonFieldProcessor::processBeginDataset(const RtlFieldInfo * field)
  751. {
  752. result.append('[');
  753. return true;
  754. }
  755. bool CommonFieldProcessor::processBeginRow(const RtlFieldInfo * field)
  756. {
  757. result.append('{');
  758. return true;
  759. }
  760. void CommonFieldProcessor::processEndSet(const RtlFieldInfo * field)
  761. {
  762. result.append(']');
  763. }
  764. void CommonFieldProcessor::processEndDataset(const RtlFieldInfo * field)
  765. {
  766. result.append(']');
  767. }
  768. void CommonFieldProcessor::processEndRow(const RtlFieldInfo * field)
  769. {
  770. result.append('}');
  771. }
  772. //=============================================================================================
  773. void printKeyedValues(StringBuffer &out, IIndexReadContext *segs, IOutputMetaData *rowMeta)
  774. {
  775. unsigned totalKeyedSize = 0;
  776. unsigned numSegs = segs->ordinality();
  777. while (numSegs)
  778. {
  779. IKeySegmentMonitor &seg = *segs->item(numSegs-1);
  780. if (!seg.isWild())
  781. {
  782. totalKeyedSize = seg.getOffset() + seg.getSize();
  783. break;
  784. }
  785. numSegs--;
  786. }
  787. if (numSegs)
  788. {
  789. byte *tempRow = (byte *) alloca(totalKeyedSize);
  790. byte *savedRow = (byte *) alloca(totalKeyedSize);
  791. const RtlFieldInfo * const *fields = rowMeta->queryTypeInfo()->queryFields();
  792. unsigned fieldOffset = 0;
  793. bool inKeyed = false;
  794. bool inWild = false;
  795. for (unsigned segNo = 0; segNo < numSegs; segNo++)
  796. {
  797. IKeySegmentMonitor &seg = *segs->item(segNo);
  798. unsigned segOffset = seg.getOffset();
  799. unsigned segSize = seg.getSize();
  800. while (fieldOffset < segOffset + segSize) // This is trying to cope with the combined case but not sure it completely does
  801. {
  802. assertex(fields[0]->type->isFixedSize());
  803. unsigned curFieldSize = fields[0]->type->size(NULL, NULL);
  804. if (seg.isWild())
  805. {
  806. if (!inWild)
  807. {
  808. if (inKeyed)
  809. {
  810. out.append("),");
  811. inKeyed = false;
  812. }
  813. out.append("WILD(");
  814. inWild = true;
  815. }
  816. else
  817. out.append(',');
  818. out.append(fields[0]->name);
  819. }
  820. else
  821. {
  822. StringBuffer setValues;
  823. CommonFieldProcessor setProcessor(setValues, true);
  824. unsigned numValues = 0;
  825. unsigned subStringLength = 0;
  826. if (!seg.isEmpty())
  827. {
  828. seg.setLow(tempRow);
  829. loop
  830. {
  831. if (numValues)
  832. setValues.append(",");
  833. memcpy(savedRow+segOffset, tempRow+segOffset, segSize);
  834. seg.endRange(tempRow);
  835. if (memcmp(savedRow+segOffset, tempRow+segOffset, segSize) != 0)
  836. {
  837. // Special case - if they differ only in trailing values that are 0 vs 0xff, then it's a substring match...
  838. if (numValues==0 && (fields[0]->type->fieldType & (RFTMkind | RFTMebcdic)) == type_string)
  839. {
  840. unsigned pos;
  841. for (pos = 0; pos < segSize; pos++)
  842. {
  843. if (savedRow[segOffset+pos] != tempRow[segOffset+pos])
  844. break;
  845. }
  846. subStringLength = pos;
  847. for (; pos < segSize; pos++)
  848. {
  849. if (savedRow[segOffset+pos] != 0 || tempRow[segOffset+pos] != 0xff)
  850. {
  851. subStringLength = 0;
  852. break;
  853. }
  854. }
  855. }
  856. fields[0]->process(savedRow + fieldOffset, tempRow, setProcessor);
  857. setValues.append("..");
  858. fields[0]->process(tempRow + fieldOffset, tempRow, setProcessor);
  859. numValues+=2;
  860. }
  861. else
  862. {
  863. fields[0]->process(tempRow + fieldOffset, tempRow, setProcessor);
  864. numValues++;
  865. }
  866. if (!seg.increment(tempRow))
  867. break;
  868. }
  869. }
  870. if (!inKeyed)
  871. {
  872. if (inWild)
  873. {
  874. out.append("),");
  875. inWild = false;
  876. }
  877. out.append("KEYED(");
  878. inKeyed = true;
  879. }
  880. else
  881. out.append(',');
  882. out.append(fields[0]->name);
  883. if (numValues==1)
  884. out.append("=").append(setValues);
  885. else if (subStringLength)
  886. out.appendf("[1..%d]='", subStringLength).append(subStringLength, (char *) savedRow+fieldOffset).append("'");
  887. else
  888. out.append(" IN [").append(setValues).append("]");
  889. }
  890. fieldOffset += curFieldSize;
  891. fields++;
  892. if (!fields[0])
  893. break;
  894. }
  895. }
  896. if (inKeyed || inWild)
  897. out.append(")");
  898. }
  899. else
  900. out.append("UNKEYED");
  901. }
  902. extern thorhelper_decl void convertRowToXML(size32_t & lenResult, char * & result, IOutputMetaData & info, const void * row, unsigned flags)
  903. {
  904. const byte * self = (const byte *)row;
  905. if (flags == (unsigned)-1)
  906. flags = XWFtrim|XWFopt|XWFnoindent;
  907. CommonXmlWriter writer(flags);
  908. info.toXML(self, writer);
  909. //could use detach...
  910. unsigned sizeResult;
  911. rtlStrToStrX(sizeResult, result, writer.length(), writer.str());
  912. lenResult = rtlUtf8Length(sizeResult, result);
  913. }