thorxmlwrite.cpp 38 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316
  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 "platform.h"
  14. #include "jlib.hpp"
  15. #include "thorxmlwrite.hpp"
  16. #include "eclrtl.hpp"
  17. #include "rtlkey.hpp"
  18. #include "eclhelper.hpp"
  19. #include "deftype.hpp"
  20. #include "rtlbcd.hpp"
  21. CommonXmlWriter::CommonXmlWriter(unsigned _flags, unsigned initialIndent, IXmlStreamFlusher *_flusher)
  22. {
  23. flusher = _flusher;
  24. flags = _flags;
  25. indent = initialIndent;
  26. nestLimit = flags & XWFnoindent ? (unsigned) -1 : 0;
  27. tagClosed = true;
  28. }
  29. CommonXmlWriter::~CommonXmlWriter()
  30. {
  31. flush(true);
  32. }
  33. CommonXmlWriter & CommonXmlWriter::clear()
  34. {
  35. out.clear();
  36. indent = 0;
  37. nestLimit = flags & XWFnoindent ? (unsigned) -1 : 0;
  38. tagClosed = true;
  39. return *this;
  40. }
  41. bool CommonXmlWriter::checkForAttribute(const char * fieldname)
  42. {
  43. if (!tagClosed)
  44. {
  45. if (fieldname && (fieldname[0] == '@'))
  46. return true;
  47. closeTag();
  48. }
  49. return false;
  50. }
  51. void CommonXmlWriter::closeTag()
  52. {
  53. if (!tagClosed)
  54. {
  55. out.append(">");
  56. if (!nestLimit)
  57. out.newline();
  58. tagClosed = true;
  59. }
  60. flush(false);
  61. }
  62. void CommonXmlWriter::outputQuoted(const char *text)
  63. {
  64. out.append(text);
  65. }
  66. void CommonXmlWriter::outputString(unsigned len, const char *field, const char *fieldname)
  67. {
  68. if (flags & XWFtrim)
  69. len = rtlTrimStrLen(len, field);
  70. if ((flags & XWFopt) && (rtlTrimStrLen(len, field) == 0))
  71. return;
  72. if (checkForAttribute(fieldname))
  73. outputXmlAttrString(len, field, fieldname+1, out);
  74. else
  75. {
  76. if (!nestLimit)
  77. out.pad(indent);
  78. outputXmlString(len, field, fieldname, out);
  79. if (!nestLimit)
  80. out.newline();
  81. }
  82. }
  83. void CommonXmlWriter::outputQString(unsigned len, const char *field, const char *fieldname)
  84. {
  85. MemoryAttr tempBuffer;
  86. char * temp;
  87. if (len <= 100)
  88. temp = (char *)alloca(len);
  89. else
  90. temp = (char *)tempBuffer.allocate(len);
  91. rtlQStrToStr(len, temp, len, field);
  92. outputString(len, temp, fieldname);
  93. }
  94. void CommonXmlWriter::outputBool(bool field, const char *fieldname)
  95. {
  96. if (checkForAttribute(fieldname))
  97. outputXmlAttrBool(field, fieldname+1, out);
  98. else
  99. {
  100. if (!nestLimit)
  101. out.pad(indent);
  102. outputXmlBool(field, fieldname, out);
  103. if (!nestLimit)
  104. out.newline();
  105. }
  106. }
  107. void CommonXmlWriter::outputData(unsigned len, const void *field, const char *fieldname)
  108. {
  109. if (checkForAttribute(fieldname))
  110. outputXmlAttrData(len, field, fieldname+1, out);
  111. else
  112. {
  113. if (!nestLimit)
  114. out.pad(indent);
  115. outputXmlData(len, field, fieldname, out);
  116. if (!nestLimit)
  117. out.newline();
  118. }
  119. }
  120. void CommonXmlWriter::outputInt(__int64 field, const char *fieldname)
  121. {
  122. if (checkForAttribute(fieldname))
  123. outputXmlAttrInt(field, fieldname+1, out);
  124. else
  125. {
  126. if (!nestLimit)
  127. out.pad(indent);
  128. outputXmlInt(field, fieldname, out);
  129. if (!nestLimit)
  130. out.newline();
  131. }
  132. }
  133. void CommonXmlWriter::outputUInt(unsigned __int64 field, const char *fieldname)
  134. {
  135. if (checkForAttribute(fieldname))
  136. outputXmlAttrUInt(field, fieldname+1, out);
  137. else
  138. {
  139. if (!nestLimit)
  140. out.pad(indent);
  141. outputXmlUInt(field, fieldname, out);
  142. if (!nestLimit)
  143. out.newline();
  144. }
  145. }
  146. void CommonXmlWriter::outputReal(double field, const char *fieldname)
  147. {
  148. if (checkForAttribute(fieldname))
  149. outputXmlAttrReal(field, fieldname+1, out);
  150. else
  151. {
  152. if (!nestLimit)
  153. out.pad(indent);
  154. outputXmlReal(field, fieldname, out);
  155. if (!nestLimit)
  156. out.newline();
  157. }
  158. }
  159. void CommonXmlWriter::outputDecimal(const void *field, unsigned size, unsigned precision, const char *fieldname)
  160. {
  161. if (checkForAttribute(fieldname))
  162. outputXmlAttrDecimal(field, size, precision, fieldname+1, out);
  163. else
  164. {
  165. if (!nestLimit)
  166. out.pad(indent);
  167. outputXmlDecimal(field, size, precision, fieldname, out);
  168. if (!nestLimit)
  169. out.newline();
  170. }
  171. }
  172. void CommonXmlWriter::outputUDecimal(const void *field, unsigned size, unsigned precision, const char *fieldname)
  173. {
  174. if (checkForAttribute(fieldname))
  175. outputXmlAttrUDecimal(field, size, precision, fieldname+1, out);
  176. else
  177. {
  178. if (!nestLimit)
  179. out.pad(indent);
  180. outputXmlUDecimal(field, size, precision, fieldname, out);
  181. if (!nestLimit)
  182. out.newline();
  183. }
  184. }
  185. void CommonXmlWriter::outputUnicode(unsigned len, const UChar *field, const char *fieldname)
  186. {
  187. if (flags & XWFtrim)
  188. len = rtlTrimUnicodeStrLen(len, field);
  189. if ((flags & XWFopt) && (rtlTrimUnicodeStrLen(len, field) == 0))
  190. return;
  191. if (checkForAttribute(fieldname))
  192. outputXmlAttrUnicode(len, field, fieldname+1, out);
  193. else
  194. {
  195. if (!nestLimit)
  196. out.pad(indent);
  197. outputXmlUnicode(len, field, fieldname, out);
  198. if (!nestLimit)
  199. out.newline();
  200. }
  201. }
  202. void CommonXmlWriter::outputUtf8(unsigned len, const char *field, const char *fieldname)
  203. {
  204. if (flags & XWFtrim)
  205. len = rtlTrimUtf8StrLen(len, field);
  206. if ((flags & XWFopt) && (rtlTrimUtf8StrLen(len, field) == 0))
  207. return;
  208. if (checkForAttribute(fieldname))
  209. outputXmlAttrUtf8(len, field, fieldname+1, out);
  210. else
  211. {
  212. if (!nestLimit)
  213. out.pad(indent);
  214. outputXmlUtf8(len, field, fieldname, out);
  215. if (!nestLimit)
  216. out.newline();
  217. }
  218. }
  219. void CommonXmlWriter::outputXmlns(const char *name, const char *uri)
  220. {
  221. StringBuffer fieldname;
  222. if (!streq(name, "xmlns"))
  223. fieldname.append("xmlns:");
  224. outputXmlAttrUtf8(rtlUtf8Length(strlen(uri), uri), uri, fieldname.append(name), out);
  225. }
  226. void CommonXmlWriter::outputBeginDataset(const char *dsname, bool nestChildren)
  227. {
  228. outputBeginNested("Dataset", nestChildren, false); //indent row, not dataset for backward compatibility
  229. if (nestChildren && indent==0)
  230. indent++;
  231. if (!dsname || !*dsname)
  232. return;
  233. out.append(" name='"); //single quote for backward compatibility
  234. outputXmlUtf8(rtlUtf8Length(strlen(dsname), dsname), dsname, NULL, out);
  235. out.append("'");
  236. }
  237. void CommonXmlWriter::outputEndDataset(const char *dsname)
  238. {
  239. outputEndNested("Dataset", false);
  240. }
  241. void CommonXmlWriter::outputBeginNested(const char *fieldname, bool nestChildren, bool doIndent)
  242. {
  243. if (!fieldname || !*fieldname)
  244. return;
  245. const char * sep = strchr(fieldname, '/');
  246. if (sep)
  247. {
  248. StringAttr leading(fieldname, sep-fieldname);
  249. outputBeginNested(leading, nestChildren, doIndent);
  250. outputBeginNested(sep+1, nestChildren, doIndent);
  251. return;
  252. }
  253. closeTag();
  254. if (!nestLimit && doIndent)
  255. out.pad(indent);
  256. out.append('<').append(fieldname);
  257. if (doIndent)
  258. indent += 1;
  259. if (!nestChildren && !nestLimit)
  260. nestLimit = indent;
  261. tagClosed = false;
  262. }
  263. void CommonXmlWriter::outputBeginNested(const char *fieldname, bool nestChildren)
  264. {
  265. outputBeginNested(fieldname, nestChildren, true);
  266. }
  267. void CommonXmlWriter::outputEndNested(const char *fieldname, bool doIndent)
  268. {
  269. if (!fieldname || !*fieldname)
  270. return;
  271. const char * sep = strchr(fieldname, '/');
  272. if (sep)
  273. {
  274. StringAttr leading(fieldname, sep-fieldname);
  275. outputEndNested(sep+1, doIndent);
  276. outputEndNested(leading, doIndent);
  277. return;
  278. }
  279. if (flags & XWFexpandempty)
  280. closeTag();
  281. if (!tagClosed)
  282. {
  283. out.append("/>");
  284. tagClosed = true;
  285. }
  286. else
  287. {
  288. if (!nestLimit && doIndent)
  289. out.pad(indent-1);
  290. out.append("</").append(fieldname).append('>');
  291. }
  292. if (indent==nestLimit)
  293. nestLimit = 0;
  294. if (doIndent)
  295. indent -= 1;
  296. if (!nestLimit)
  297. out.newline();
  298. }
  299. void CommonXmlWriter::outputEndNested(const char *fieldname)
  300. {
  301. outputEndNested(fieldname, true);
  302. }
  303. void CommonXmlWriter::outputSetAll()
  304. {
  305. closeTag();
  306. if (!nestLimit)
  307. out.pad(indent);
  308. outputXmlSetAll(out);
  309. if (!nestLimit)
  310. out.newline();
  311. }
  312. //=====================================================================================
  313. CommonJsonWriter::CommonJsonWriter(unsigned _flags, unsigned initialIndent, IXmlStreamFlusher *_flusher)
  314. {
  315. flusher = _flusher;
  316. flags = _flags;
  317. indent = initialIndent;
  318. nestLimit = flags & XWFnoindent ? (unsigned) -1 : 0;
  319. needDelimiter = false;
  320. }
  321. CommonJsonWriter::~CommonJsonWriter()
  322. {
  323. flush(true);
  324. }
  325. CommonJsonWriter & CommonJsonWriter::clear()
  326. {
  327. out.clear();
  328. indent = 0;
  329. nestLimit = flags & XWFnoindent ? (unsigned) -1 : 0;
  330. return *this;
  331. }
  332. void CommonJsonWriter::checkFormat(bool doDelimit, bool delimitNext, int inc)
  333. {
  334. if (doDelimit)
  335. {
  336. if (needDelimiter)
  337. {
  338. if (!out.length()) //new block
  339. out.append(',');
  340. else
  341. delimitJSON(out);
  342. }
  343. if (!nestLimit)
  344. out.append('\n').pad(indent);
  345. }
  346. indent+=inc;
  347. needDelimiter = delimitNext;
  348. }
  349. void CommonJsonWriter::checkDelimit(int inc)
  350. {
  351. checkFormat(true, true, inc);
  352. }
  353. const char *CommonJsonWriter::checkItemName(CJsonWriterItem *item, const char *name, bool simpleType)
  354. {
  355. if (simpleType && (!name || !*name))
  356. name = "#value"; //xml mixed content
  357. if (item && item->depth==0 && strieq(item->name, name))
  358. return NULL;
  359. return name;
  360. }
  361. const char *CommonJsonWriter::checkItemName(const char *name, bool simpleType)
  362. {
  363. CJsonWriterItem *item = (arrays.length()) ? &arrays.tos() : NULL;
  364. return checkItemName(item, name, simpleType);
  365. }
  366. const char *CommonJsonWriter::checkItemNameBeginNested(const char *name)
  367. {
  368. CJsonWriterItem *item = (arrays.length()) ? &arrays.tos() : NULL;
  369. name = checkItemName(item, name, false);
  370. if (item)
  371. item->depth++;
  372. return name;
  373. }
  374. const char *CommonJsonWriter::checkItemNameEndNested(const char *name)
  375. {
  376. CJsonWriterItem *item = (arrays.length()) ? &arrays.tos() : NULL;
  377. if (item)
  378. item->depth--;
  379. return checkItemName(item, name, false);
  380. }
  381. void CommonJsonWriter::outputQuoted(const char *text)
  382. {
  383. checkDelimit();
  384. appendJSONValue(out, NULL, text);
  385. }
  386. void CommonJsonWriter::outputString(unsigned len, const char *field, const char *fieldname)
  387. {
  388. if (flags & XWFtrim)
  389. len = rtlTrimStrLen(len, field);
  390. if ((flags & XWFopt) && (rtlTrimStrLen(len, field) == 0))
  391. return;
  392. checkDelimit();
  393. appendJSONStringValue(out, checkItemName(fieldname), len, field, true);
  394. }
  395. void CommonJsonWriter::outputQString(unsigned len, const char *field, const char *fieldname)
  396. {
  397. MemoryAttr tempBuffer;
  398. char * temp;
  399. if (len <= 100)
  400. temp = (char *)alloca(len);
  401. else
  402. temp = (char *)tempBuffer.allocate(len);
  403. rtlQStrToStr(len, temp, len, field);
  404. outputString(len, temp, fieldname);
  405. }
  406. void CommonJsonWriter::outputBool(bool field, const char *fieldname)
  407. {
  408. checkDelimit();
  409. appendJSONValue(out, checkItemName(fieldname), field);
  410. }
  411. void CommonJsonWriter::outputData(unsigned len, const void *field, const char *fieldname)
  412. {
  413. checkDelimit();
  414. appendJSONDataValue(out, checkItemName(fieldname), len, field);
  415. }
  416. void CommonJsonWriter::outputInt(__int64 field, const char *fieldname)
  417. {
  418. checkDelimit();
  419. appendJSONValue(out, checkItemName(fieldname), field);
  420. }
  421. void CommonJsonWriter::outputUInt(unsigned __int64 field, const char *fieldname)
  422. {
  423. checkDelimit();
  424. appendJSONValue(out, checkItemName(fieldname), field);
  425. }
  426. void CommonJsonWriter::outputReal(double field, const char *fieldname)
  427. {
  428. checkDelimit();
  429. appendJSONValue(out, checkItemName(fieldname), field);
  430. }
  431. void CommonJsonWriter::outputDecimal(const void *field, unsigned size, unsigned precision, const char *fieldname)
  432. {
  433. checkDelimit();
  434. outputJsonDecimal(field, size, precision, checkItemName(fieldname), out);
  435. }
  436. void CommonJsonWriter::outputUDecimal(const void *field, unsigned size, unsigned precision, const char *fieldname)
  437. {
  438. checkDelimit();
  439. outputJsonUDecimal(field, size, precision, checkItemName(fieldname), out);
  440. }
  441. void CommonJsonWriter::outputUnicode(unsigned len, const UChar *field, const char *fieldname)
  442. {
  443. if (flags & XWFtrim)
  444. len = rtlTrimUnicodeStrLen(len, field);
  445. if ((flags & XWFopt) && (rtlTrimUnicodeStrLen(len, field) == 0))
  446. return;
  447. checkDelimit();
  448. outputJsonUnicode(len, field, checkItemName(fieldname), out);
  449. }
  450. void CommonJsonWriter::outputUtf8(unsigned len, const char *field, const char *fieldname)
  451. {
  452. if (flags & XWFtrim)
  453. len = rtlTrimUtf8StrLen(len, field);
  454. if ((flags & XWFopt) && (rtlTrimUtf8StrLen(len, field) == 0))
  455. return;
  456. checkDelimit();
  457. appendJSONStringValue(out, checkItemName(fieldname), len, field, true);
  458. }
  459. void CommonJsonWriter::outputBeginArray(const char *fieldname)
  460. {
  461. arrays.append(*new CJsonWriterItem(fieldname));
  462. const char * sep = strchr(fieldname, '/');
  463. while (sep)
  464. {
  465. StringAttr leading(fieldname, sep-fieldname);
  466. appendJSONName(out, leading).append(" {");
  467. fieldname = sep+1;
  468. sep = strchr(fieldname, '/');
  469. }
  470. checkFormat(false, false, 1);
  471. appendJSONName(out, fieldname).append('[');
  472. }
  473. void CommonJsonWriter::outputEndArray(const char *fieldname)
  474. {
  475. arrays.pop();
  476. checkFormat(false, true, -1);
  477. out.append(']');
  478. const char * sep = (fieldname) ? strchr(fieldname, '/') : NULL;
  479. while (sep)
  480. {
  481. out.append('}');
  482. sep = strchr(sep+1, '/');
  483. }
  484. }
  485. void CommonJsonWriter::outputBeginDataset(const char *dsname, bool nestChildren)
  486. {
  487. if (dsname && *dsname)
  488. outputBeginNested(dsname, nestChildren);
  489. }
  490. void CommonJsonWriter::outputEndDataset(const char *dsname)
  491. {
  492. if (dsname && *dsname)
  493. outputEndNested(dsname);
  494. }
  495. void CommonJsonWriter::outputBeginNested(const char *fieldname, bool nestChildren)
  496. {
  497. if (!fieldname || !*fieldname)
  498. return;
  499. flush(false);
  500. checkFormat(true, false, 1);
  501. fieldname = checkItemNameBeginNested(fieldname);
  502. if (fieldname)
  503. {
  504. const char * sep = (fieldname) ? strchr(fieldname, '/') : NULL;
  505. while (sep)
  506. {
  507. StringAttr leading(fieldname, sep-fieldname);
  508. appendJSONName(out, leading).append("{");
  509. fieldname = sep+1;
  510. sep = strchr(fieldname, '/');
  511. }
  512. appendJSONName(out, fieldname);
  513. }
  514. out.append("{");
  515. if (!nestChildren && !nestLimit)
  516. nestLimit = indent;
  517. }
  518. void CommonJsonWriter::outputEndNested(const char *fieldname)
  519. {
  520. if (!fieldname || !*fieldname)
  521. return;
  522. flush(false);
  523. checkFormat(false, true, -1);
  524. fieldname = checkItemNameEndNested(fieldname);
  525. if (fieldname)
  526. {
  527. const char * sep = (fieldname) ? strchr(fieldname, '/') : NULL;
  528. while (sep)
  529. {
  530. out.append('}');
  531. sep = strchr(sep+1, '/');
  532. }
  533. }
  534. out.append("}");
  535. if (indent==nestLimit)
  536. nestLimit = 0;
  537. }
  538. void CommonJsonWriter::outputSetAll()
  539. {
  540. flush(false);
  541. checkDelimit();
  542. appendJSONValue(out, "All", true);
  543. }
  544. //=====================================================================================
  545. inline void outputEncodedXmlString(unsigned len, const char *field, const char *fieldname, StringBuffer &out)
  546. {
  547. if (fieldname)
  548. out.append('<').append(fieldname).append(" xsi:type=\"xsd:string\">");
  549. encodeXML(field, out, 0, len);
  550. if (fieldname)
  551. out.append("</").append(fieldname).append('>');
  552. }
  553. inline void outputEncodedXmlBool(bool field, const char *fieldname, StringBuffer &out)
  554. {
  555. const char * text = field ? "true" : "false";
  556. if (fieldname)
  557. out.append('<').append(fieldname).append(" xsi:type=\"xsd:boolean\">").append(text).append("</").append(fieldname).append('>');
  558. else
  559. out.append(text);
  560. }
  561. static char thorHelperhexchar[] = "0123456789ABCDEF";
  562. inline void outputEncodedXmlData(unsigned len, const void *_field, const char *fieldname, StringBuffer &out)
  563. {
  564. const unsigned char *field = (const unsigned char *) _field;
  565. if (fieldname)
  566. out.append('<').append(fieldname).append(" xsi:type=\"xsd:hexBinary\">");
  567. for (unsigned int i = 0; i < len; i++)
  568. {
  569. out.append(thorHelperhexchar[field[i] >> 4]).append(thorHelperhexchar[field[i] & 0x0f]);
  570. }
  571. if (fieldname)
  572. out.append("</").append(fieldname).append('>');
  573. }
  574. inline void outputEncoded64XmlData(unsigned len, const void *_field, const char *fieldname, StringBuffer &out)
  575. {
  576. if (fieldname)
  577. out.append('<').append(fieldname).append(" xsi:type=\"xsd:base64Binary\">");
  578. JBASE64_Encode(_field, len, out, false);
  579. if (fieldname)
  580. out.append("</").append(fieldname).append('>');
  581. }
  582. inline void outputEncodedXmlInt(__int64 field, const char *fieldname, StringBuffer &out)
  583. {
  584. if (fieldname)
  585. out.append('<').append(fieldname).append(" xsi:type=\"xsd:integer\">").append(field).append("</").append(fieldname).append('>');
  586. else
  587. out.append(field);
  588. }
  589. inline void outputEncodedXmlUInt(unsigned __int64 field, const char *fieldname, StringBuffer &out)
  590. {
  591. if (fieldname)
  592. out.append('<').append(fieldname).append(" xsi:type=\"xsd:nonNegativeInteger\">").append(field).append("</").append(fieldname).append('>');
  593. else
  594. out.append(field);
  595. }
  596. inline void outputEncodedXmlReal(double field, const char *fieldname, StringBuffer &out)
  597. {
  598. if (fieldname)
  599. out.append('<').append(fieldname).append(" xsi:type=\"xsd:double\">").append(field).append("</").append(fieldname).append('>');
  600. else
  601. out.append(field);
  602. }
  603. inline void outputEncodedXmlDecimal(const void *field, unsigned size, unsigned precision, const char *fieldname, StringBuffer &out)
  604. {
  605. char dec[50];
  606. if (fieldname)
  607. out.append('<').append(fieldname).append(" xsi:type=\"xsd:decimal\">");
  608. DecLock();
  609. if (DecValid(true, size*2-1, field))
  610. {
  611. DecPushDecimal(field, size, precision);
  612. DecPopCString(sizeof(dec), dec);
  613. const char *finger = dec;
  614. while(isspace(*finger)) finger++;
  615. out.append(finger);
  616. }
  617. else
  618. out.append("####");
  619. DecUnlock();
  620. if (fieldname)
  621. out.append("</").append(fieldname).append('>');
  622. }
  623. inline void outputEncodedXmlUDecimal(const void *field, unsigned size, unsigned precision, const char *fieldname, StringBuffer &out)
  624. {
  625. char dec[50];
  626. if (fieldname)
  627. out.append('<').append(fieldname).append(" xsi:type=\"xsd:decimal\">");
  628. DecLock();
  629. if (DecValid(false, size*2, field))
  630. {
  631. DecPushUDecimal(field, size, precision);
  632. DecPopCString(sizeof(dec), dec);
  633. const char *finger = dec;
  634. while(isspace(*finger)) finger++;
  635. out.append(finger);
  636. }
  637. else
  638. out.append("####");
  639. DecUnlock();
  640. if (fieldname)
  641. out.append("</").append(fieldname).append('>');
  642. }
  643. inline void outputEncodedXmlUnicode(unsigned len, const UChar *field, const char *fieldname, StringBuffer &out)
  644. {
  645. char * buff = 0;
  646. unsigned bufflen = 0;
  647. rtlUnicodeToCodepageX(bufflen, buff, len, field, "utf-8");
  648. if (fieldname)
  649. out.append('<').append(fieldname).append(" xsi:type=\"xsd:string\">");
  650. encodeXML(buff, out, 0, bufflen, true); // output as UTF-8
  651. if (fieldname)
  652. out.append("</").append(fieldname).append('>');
  653. rtlFree(buff);
  654. }
  655. inline void outputEncodedXmlUtf8(unsigned len, const char *field, const char *fieldname, StringBuffer &out)
  656. {
  657. if (fieldname)
  658. out.append('<').append(fieldname).append(" xsi:type=\"xsd:string\">");
  659. encodeXML(field, out, 0, rtlUtf8Size(len, field), true); // output as UTF-8
  660. if (fieldname)
  661. out.append("</").append(fieldname).append('>');
  662. }
  663. //=====================================================================================
  664. CommonEncodedXmlWriter::CommonEncodedXmlWriter(unsigned _flags, unsigned initialIndent, IXmlStreamFlusher *_flusher)
  665. : CommonXmlWriter(_flags, initialIndent, _flusher)
  666. {
  667. }
  668. void CommonEncodedXmlWriter::outputString(unsigned len, const char *field, const char *fieldname)
  669. {
  670. if (flags & XWFtrim)
  671. len = rtlTrimStrLen(len, field);
  672. if ((flags & XWFopt) && (rtlTrimStrLen(len, field) == 0))
  673. return;
  674. if (checkForAttribute(fieldname))
  675. outputXmlAttrString(len, field, fieldname+1, out);
  676. else
  677. {
  678. if (!nestLimit)
  679. out.pad(indent);
  680. outputEncodedXmlString(len, field, fieldname, out);
  681. if (!nestLimit)
  682. out.newline();
  683. }
  684. }
  685. void CommonEncodedXmlWriter::outputBool(bool field, const char *fieldname)
  686. {
  687. if (checkForAttribute(fieldname))
  688. outputXmlAttrBool(field, fieldname+1, out);
  689. else
  690. {
  691. if (!nestLimit)
  692. out.pad(indent);
  693. outputEncodedXmlBool(field, fieldname, out);
  694. if (!nestLimit)
  695. out.newline();
  696. }
  697. }
  698. void CommonEncodedXmlWriter::outputData(unsigned len, const void *field, const char *fieldname)
  699. {
  700. if (checkForAttribute(fieldname))
  701. outputXmlAttrData(len, field, fieldname+1, out);
  702. else
  703. {
  704. if (!nestLimit)
  705. out.pad(indent);
  706. outputEncodedXmlData(len, field, fieldname, out);
  707. if (!nestLimit)
  708. out.newline();
  709. }
  710. }
  711. void CommonEncodedXmlWriter::outputInt(__int64 field, const char *fieldname)
  712. {
  713. if (checkForAttribute(fieldname))
  714. outputXmlAttrInt(field, fieldname+1, out);
  715. else
  716. {
  717. if (!nestLimit)
  718. out.pad(indent);
  719. outputEncodedXmlInt(field, fieldname, out);
  720. if (!nestLimit)
  721. out.newline();
  722. }
  723. }
  724. void CommonEncodedXmlWriter::outputUInt(unsigned __int64 field, const char *fieldname)
  725. {
  726. if (checkForAttribute(fieldname))
  727. outputXmlAttrUInt(field, fieldname+1, out);
  728. else
  729. {
  730. if (!nestLimit)
  731. out.pad(indent);
  732. outputEncodedXmlUInt(field, fieldname, out);
  733. if (!nestLimit)
  734. out.newline();
  735. }
  736. }
  737. void CommonEncodedXmlWriter::outputReal(double field, const char *fieldname)
  738. {
  739. if (checkForAttribute(fieldname))
  740. outputXmlAttrReal(field, fieldname+1, out);
  741. else
  742. {
  743. if (!nestLimit)
  744. out.pad(indent);
  745. outputEncodedXmlReal(field, fieldname, out);
  746. if (!nestLimit)
  747. out.newline();
  748. }
  749. }
  750. void CommonEncodedXmlWriter::outputDecimal(const void *field, unsigned size, unsigned precision, const char *fieldname)
  751. {
  752. if (checkForAttribute(fieldname))
  753. outputXmlAttrDecimal(field, size, precision, fieldname+1, out);
  754. else
  755. {
  756. if (!nestLimit)
  757. out.pad(indent);
  758. outputEncodedXmlDecimal(field, size, precision, fieldname, out);
  759. if (!nestLimit)
  760. out.newline();
  761. }
  762. }
  763. void CommonEncodedXmlWriter::outputUDecimal(const void *field, unsigned size, unsigned precision, const char *fieldname)
  764. {
  765. if (checkForAttribute(fieldname))
  766. outputXmlAttrUDecimal(field, size, precision, fieldname+1, out);
  767. else
  768. {
  769. if (!nestLimit)
  770. out.pad(indent);
  771. outputEncodedXmlUDecimal(field, size, precision, fieldname, out);
  772. if (!nestLimit)
  773. out.newline();
  774. }
  775. }
  776. void CommonEncodedXmlWriter::outputUnicode(unsigned len, const UChar *field, const char *fieldname)
  777. {
  778. if (flags & XWFtrim)
  779. len = rtlTrimUnicodeStrLen(len, field);
  780. if ((flags & XWFopt) && (rtlTrimUnicodeStrLen(len, field) == 0))
  781. return;
  782. if (checkForAttribute(fieldname))
  783. outputXmlAttrUnicode(len, field, fieldname+1, out);
  784. else
  785. {
  786. if (!nestLimit)
  787. out.pad(indent);
  788. outputEncodedXmlUnicode(len, field, fieldname, out);
  789. if (!nestLimit)
  790. out.newline();
  791. }
  792. }
  793. void CommonEncodedXmlWriter::outputUtf8(unsigned len, const char *field, const char *fieldname)
  794. {
  795. if (flags & XWFtrim)
  796. len = rtlTrimUtf8StrLen(len, field);
  797. if ((flags & XWFopt) && (rtlTrimUtf8StrLen(len, field) == 0))
  798. return;
  799. if (checkForAttribute(fieldname))
  800. outputXmlAttrUtf8(len, field, fieldname+1, out);
  801. else
  802. {
  803. if (!nestLimit)
  804. out.pad(indent);
  805. outputEncodedXmlUtf8(len, field, fieldname, out);
  806. if (!nestLimit)
  807. out.newline();
  808. }
  809. }
  810. //=====================================================================================
  811. CommonEncoded64XmlWriter::CommonEncoded64XmlWriter(unsigned _flags, unsigned initialIndent, IXmlStreamFlusher *_flusher)
  812. : CommonEncodedXmlWriter(_flags, initialIndent, _flusher)
  813. {
  814. }
  815. void CommonEncoded64XmlWriter::outputData(unsigned len, const void *field, const char *fieldname)
  816. {
  817. if (checkForAttribute(fieldname))
  818. outputXmlAttrData(len, field, fieldname+1, out);
  819. else
  820. {
  821. if (!nestLimit)
  822. out.pad(indent);
  823. outputEncoded64XmlData(len, field, fieldname, out);
  824. if (!nestLimit)
  825. out.newline();
  826. }
  827. }
  828. //=====================================================================================
  829. CommonXmlWriter * CreateCommonXmlWriter(unsigned _flags, unsigned _initialIndent, IXmlStreamFlusher *_flusher, XMLWriterType xmlType)
  830. {
  831. switch (xmlType)
  832. {
  833. case WTStandard:
  834. return new CommonXmlWriter(_flags, _initialIndent, _flusher);//standard XML writer
  835. case WTEncodingData64:
  836. return new CommonEncoded64XmlWriter(_flags, _initialIndent, _flusher);//writes xsd type attributes, and all data as base64binary
  837. case WTEncoding:
  838. return new CommonEncodedXmlWriter(_flags, _initialIndent, _flusher);//writes xsd type attributes, and all data as hexBinary
  839. default:
  840. assertex(false);
  841. return NULL;
  842. }
  843. }
  844. //=====================================================================================
  845. IXmlWriter * createIXmlWriter(unsigned _flags, unsigned _initialIndent, IXmlStreamFlusher *_flusher, XMLWriterType xmlType)
  846. {
  847. if (xmlType==WTJSON)
  848. return new CommonJsonWriter(_flags, _initialIndent, _flusher);
  849. return CreateCommonXmlWriter(_flags, _initialIndent, _flusher, xmlType);
  850. }
  851. //=====================================================================================
  852. SimpleOutputWriter::SimpleOutputWriter()
  853. {
  854. separatorNeeded = false;
  855. }
  856. void SimpleOutputWriter::outputFieldSeparator()
  857. {
  858. if (separatorNeeded)
  859. out.append(',');
  860. separatorNeeded = true;
  861. }
  862. SimpleOutputWriter & SimpleOutputWriter::clear()
  863. {
  864. out.clear();
  865. separatorNeeded = false;
  866. return *this;
  867. }
  868. void SimpleOutputWriter::outputQuoted(const char *text)
  869. {
  870. out.append(text);
  871. }
  872. void SimpleOutputWriter::outputString(unsigned len, const char *field, const char *)
  873. {
  874. outputFieldSeparator();
  875. out.append(len, field);
  876. }
  877. void SimpleOutputWriter::outputQString(unsigned len, const char *field, const char *fieldname)
  878. {
  879. MemoryAttr tempBuffer;
  880. char * temp;
  881. if (len <= 100)
  882. temp = (char *)alloca(len);
  883. else
  884. temp = (char *)tempBuffer.allocate(len);
  885. rtlQStrToStr(len, temp, len, field);
  886. outputString(len, temp, fieldname);
  887. }
  888. void SimpleOutputWriter::outputBool(bool field, const char *)
  889. {
  890. outputFieldSeparator();
  891. outputXmlBool(field, NULL, out);
  892. }
  893. void SimpleOutputWriter::outputData(unsigned len, const void *field, const char *)
  894. {
  895. outputFieldSeparator();
  896. outputXmlData(len, field, NULL, out);
  897. }
  898. void SimpleOutputWriter::outputInt(__int64 field, const char *)
  899. {
  900. outputFieldSeparator();
  901. outputXmlInt(field, NULL, out);
  902. }
  903. void SimpleOutputWriter::outputUInt(unsigned __int64 field, const char *)
  904. {
  905. outputFieldSeparator();
  906. outputXmlUInt(field, NULL, out);
  907. }
  908. void SimpleOutputWriter::outputReal(double field, const char *)
  909. {
  910. outputFieldSeparator();
  911. outputXmlReal(field, NULL, out);
  912. }
  913. void SimpleOutputWriter::outputDecimal(const void *field, unsigned size, unsigned precision, const char *)
  914. {
  915. outputFieldSeparator();
  916. outputXmlDecimal(field, size, precision, NULL, out);
  917. }
  918. void SimpleOutputWriter::outputUDecimal(const void *field, unsigned size, unsigned precision, const char *)
  919. {
  920. outputFieldSeparator();
  921. outputXmlUDecimal(field, size, precision, NULL, out);
  922. }
  923. void SimpleOutputWriter::outputUnicode(unsigned len, const UChar *field, const char *)
  924. {
  925. outputFieldSeparator();
  926. outputXmlUnicode(len, field, NULL, out);
  927. }
  928. void SimpleOutputWriter::outputUtf8(unsigned len, const char *field, const char *)
  929. {
  930. outputFieldSeparator();
  931. outputXmlUtf8(len, field, NULL, out);
  932. }
  933. void SimpleOutputWriter::outputBeginNested(const char *s, bool)
  934. {
  935. if (!s || !*s)
  936. return;
  937. outputFieldSeparator();
  938. out.append('[');
  939. separatorNeeded = false;
  940. }
  941. void SimpleOutputWriter::outputEndNested(const char *s)
  942. {
  943. if (!s || !*s)
  944. return;
  945. out.append(']');
  946. separatorNeeded = true;
  947. }
  948. void SimpleOutputWriter::outputSetAll()
  949. {
  950. out.append('*');
  951. }
  952. void SimpleOutputWriter::newline()
  953. {
  954. out.append('\n');
  955. }
  956. //=====================================================================================
  957. CommonFieldProcessor::CommonFieldProcessor(StringBuffer &_result, bool _trim) : result(_result), trim(_trim)
  958. {
  959. }
  960. void CommonFieldProcessor::processString(unsigned len, const char *value, const RtlFieldInfo * field)
  961. {
  962. if (trim)
  963. len = rtlTrimStrLen(len, value);
  964. result.append("'");
  965. outputXmlString(len, value, NULL, result);
  966. result.append("'");
  967. }
  968. void CommonFieldProcessor::processBool(bool value, const RtlFieldInfo * field)
  969. {
  970. outputXmlBool(value, NULL, result);
  971. }
  972. void CommonFieldProcessor::processData(unsigned len, const void *value, const RtlFieldInfo * field)
  973. {
  974. outputXmlData(len, value, NULL, result);
  975. }
  976. void CommonFieldProcessor::processInt(__int64 value, const RtlFieldInfo * field)
  977. {
  978. outputXmlInt(value, NULL, result);
  979. }
  980. void CommonFieldProcessor::processUInt(unsigned __int64 value, const RtlFieldInfo * field)
  981. {
  982. outputXmlUInt(value, NULL, result);
  983. }
  984. void CommonFieldProcessor::processReal(double value, const RtlFieldInfo * field)
  985. {
  986. outputXmlReal(value, NULL, result);
  987. }
  988. void CommonFieldProcessor::processDecimal(const void *value, unsigned digits, unsigned precision, const RtlFieldInfo * field)
  989. {
  990. outputXmlDecimal(value, digits, precision, NULL, result);
  991. }
  992. void CommonFieldProcessor::processUDecimal(const void *value, unsigned digits, unsigned precision, const RtlFieldInfo * field)
  993. {
  994. outputXmlUDecimal(value, digits, precision, NULL, result);
  995. }
  996. void CommonFieldProcessor::processUnicode(unsigned len, const UChar *value, const RtlFieldInfo * field)
  997. {
  998. if (trim)
  999. len = rtlTrimUnicodeStrLen(len, value);
  1000. outputXmlUnicode(len, value, NULL, result);
  1001. }
  1002. void CommonFieldProcessor::processQString(unsigned len, const char *value, const RtlFieldInfo * field)
  1003. {
  1004. MemoryAttr tempBuffer;
  1005. char * temp;
  1006. if (len <= 100)
  1007. temp = (char *)alloca(len);
  1008. else
  1009. temp = (char *)tempBuffer.allocate(len);
  1010. rtlQStrToStr(len, temp, len, value);
  1011. processString(len, temp, field);
  1012. }
  1013. void CommonFieldProcessor::processUtf8(unsigned len, const char *value, const RtlFieldInfo * field)
  1014. {
  1015. if (trim)
  1016. len = rtlTrimUtf8StrLen(len, value);
  1017. outputXmlUtf8(len, value, NULL, result);
  1018. }
  1019. bool CommonFieldProcessor::processBeginSet(const RtlFieldInfo * field, unsigned numElements, bool isAll, const byte *data)
  1020. {
  1021. result.append('[');
  1022. if (isAll)
  1023. result.append("ALL");
  1024. return true;
  1025. }
  1026. bool CommonFieldProcessor::processBeginDataset(const RtlFieldInfo * field, unsigned numRows)
  1027. {
  1028. result.append('[');
  1029. return true;
  1030. }
  1031. bool CommonFieldProcessor::processBeginRow(const RtlFieldInfo * field)
  1032. {
  1033. result.append('{');
  1034. return true;
  1035. }
  1036. void CommonFieldProcessor::processEndSet(const RtlFieldInfo * field)
  1037. {
  1038. result.append(']');
  1039. }
  1040. void CommonFieldProcessor::processEndDataset(const RtlFieldInfo * field)
  1041. {
  1042. result.append(']');
  1043. }
  1044. void CommonFieldProcessor::processEndRow(const RtlFieldInfo * field)
  1045. {
  1046. result.append('}');
  1047. }
  1048. //=============================================================================================
  1049. void printKeyedValues(StringBuffer &out, IIndexReadContext *segs, IOutputMetaData *rowMeta)
  1050. {
  1051. unsigned totalKeyedSize = 0;
  1052. unsigned numSegs = segs->ordinality();
  1053. while (numSegs)
  1054. {
  1055. IKeySegmentMonitor &seg = *segs->item(numSegs-1);
  1056. if (!seg.isWild())
  1057. {
  1058. totalKeyedSize = seg.getOffset() + seg.getSize();
  1059. break;
  1060. }
  1061. numSegs--;
  1062. }
  1063. if (numSegs)
  1064. {
  1065. byte *tempRow = (byte *) alloca(totalKeyedSize);
  1066. byte *savedRow = (byte *) alloca(totalKeyedSize);
  1067. const RtlFieldInfo * const *fields = rowMeta->queryTypeInfo()->queryFields();
  1068. unsigned fieldOffset = 0;
  1069. bool inKeyed = false;
  1070. bool inWild = false;
  1071. for (unsigned segNo = 0; segNo < numSegs; segNo++)
  1072. {
  1073. IKeySegmentMonitor &seg = *segs->item(segNo);
  1074. unsigned segOffset = seg.getOffset();
  1075. unsigned segSize = seg.getSize();
  1076. while (fieldOffset < segOffset + segSize) // This is trying to cope with the combined case but not sure it completely does
  1077. {
  1078. assertex(fields[0]->type->isFixedSize());
  1079. unsigned curFieldSize = fields[0]->type->size(NULL, NULL);
  1080. if (seg.isWild())
  1081. {
  1082. if (!inWild)
  1083. {
  1084. if (inKeyed)
  1085. {
  1086. out.append("),");
  1087. inKeyed = false;
  1088. }
  1089. out.append("WILD(");
  1090. inWild = true;
  1091. }
  1092. else
  1093. out.append(',');
  1094. out.append(fields[0]->name);
  1095. }
  1096. else
  1097. {
  1098. StringBuffer setValues;
  1099. CommonFieldProcessor setProcessor(setValues, true);
  1100. unsigned numValues = 0;
  1101. unsigned subStringLength = 0;
  1102. if (!seg.isEmpty())
  1103. {
  1104. seg.setLow(tempRow);
  1105. loop
  1106. {
  1107. if (numValues)
  1108. setValues.append(",");
  1109. memcpy(savedRow+segOffset, tempRow+segOffset, segSize);
  1110. seg.endRange(tempRow);
  1111. if (memcmp(savedRow+segOffset, tempRow+segOffset, segSize) != 0)
  1112. {
  1113. // Special case - if they differ only in trailing values that are 0 vs 0xff, then it's a substring match...
  1114. if (numValues==0 && (fields[0]->type->fieldType & (RFTMkind | RFTMebcdic)) == type_string)
  1115. {
  1116. unsigned pos;
  1117. for (pos = 0; pos < segSize; pos++)
  1118. {
  1119. if (savedRow[segOffset+pos] != tempRow[segOffset+pos])
  1120. break;
  1121. }
  1122. subStringLength = pos;
  1123. for (; pos < segSize; pos++)
  1124. {
  1125. if (savedRow[segOffset+pos] != 0 || tempRow[segOffset+pos] != 0xff)
  1126. {
  1127. subStringLength = 0;
  1128. break;
  1129. }
  1130. }
  1131. }
  1132. fields[0]->process(savedRow + fieldOffset, tempRow, setProcessor);
  1133. setValues.append("..");
  1134. fields[0]->process(tempRow + fieldOffset, tempRow, setProcessor);
  1135. numValues+=2;
  1136. }
  1137. else
  1138. {
  1139. fields[0]->process(tempRow + fieldOffset, tempRow, setProcessor);
  1140. numValues++;
  1141. }
  1142. if (!seg.increment(tempRow))
  1143. break;
  1144. }
  1145. }
  1146. if (!inKeyed)
  1147. {
  1148. if (inWild)
  1149. {
  1150. out.append("),");
  1151. inWild = false;
  1152. }
  1153. out.append("KEYED(");
  1154. inKeyed = true;
  1155. }
  1156. else
  1157. out.append(',');
  1158. out.append(fields[0]->name);
  1159. if (numValues==1)
  1160. out.append("=").append(setValues);
  1161. else if (subStringLength)
  1162. out.appendf("[1..%d]='", subStringLength).append(subStringLength, (char *) savedRow+fieldOffset).append("'");
  1163. else
  1164. out.append(" IN [").append(setValues).append("]");
  1165. }
  1166. fieldOffset += curFieldSize;
  1167. fields++;
  1168. if (!fields[0])
  1169. break;
  1170. }
  1171. }
  1172. if (inKeyed || inWild)
  1173. out.append(")");
  1174. }
  1175. else
  1176. out.append("UNKEYED");
  1177. }
  1178. extern thorhelper_decl void convertRowToXML(size32_t & lenResult, char * & result, IOutputMetaData & info, const void * row, unsigned flags)
  1179. {
  1180. const byte * self = (const byte *)row;
  1181. if (flags == (unsigned)-1)
  1182. flags = XWFtrim|XWFopt|XWFnoindent;
  1183. CommonXmlWriter writer(flags);
  1184. info.toXML(self, writer);
  1185. //could use detach...
  1186. unsigned sizeResult;
  1187. rtlStrToStrX(sizeResult, result, writer.length(), writer.str());
  1188. lenResult = rtlUtf8Length(sizeResult, result);
  1189. }