rtlfield.cpp 36 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103
  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 <math.h>
  15. #include <stdio.h>
  16. #include "jmisc.hpp"
  17. #include "jlib.hpp"
  18. #include "eclhelper.hpp"
  19. #include "eclrtl_imp.hpp"
  20. #include "rtlfield_imp.hpp"
  21. static const char * queryXPath(const RtlFieldInfo * field)
  22. {
  23. const char * xpath = field->xpath;
  24. if (xpath)
  25. {
  26. const char * sep = strchr(xpath, xpathCompoundSeparatorChar);
  27. if (!sep)
  28. return xpath;
  29. return sep+1;
  30. }
  31. return field->name->str();
  32. }
  33. static bool hasOuterXPath(const RtlFieldInfo * field)
  34. {
  35. const char * xpath = field->xpath;
  36. assertex(xpath);
  37. return (*xpath != xpathCompoundSeparatorChar);
  38. }
  39. static void queryNestedOuterXPath(StringAttr & ret, const RtlFieldInfo * field)
  40. {
  41. const char * xpath = field->xpath;
  42. assertex(xpath);
  43. const char * sep = strchr(xpath, xpathCompoundSeparatorChar);
  44. assertex(sep);
  45. ret.set(xpath, (size32_t)(sep-xpath));
  46. }
  47. //-------------------------------------------------------------------------------------------------------------------
  48. size32_t RtlTypeInfoBase::size(const byte * self, const byte * selfrow) const
  49. {
  50. return length;
  51. }
  52. size32_t RtlTypeInfoBase::process(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IFieldProcessor & target) const
  53. {
  54. rtlFailUnexpected();
  55. return 0;
  56. }
  57. size32_t RtlTypeInfoBase::toXML(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IXmlWriter & out) const
  58. {
  59. rtlFailUnexpected();
  60. return 0;
  61. }
  62. const char * RtlTypeInfoBase::queryLocale() const
  63. {
  64. return NULL;
  65. }
  66. const RtlFieldInfo * const * RtlTypeInfoBase::queryFields() const
  67. {
  68. return NULL;
  69. }
  70. const RtlTypeInfo * RtlTypeInfoBase::queryChildType() const
  71. {
  72. return NULL;
  73. }
  74. //-------------------------------------------------------------------------------------------------------------------
  75. size32_t RtlBoolTypeInfo::process(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IFieldProcessor & target) const
  76. {
  77. target.processBool(*(const bool *)self, field);
  78. return sizeof(bool);
  79. }
  80. size32_t RtlBoolTypeInfo::toXML(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IXmlWriter & target) const
  81. {
  82. target.outputBool(*(const bool *)self, queryXPath(field));
  83. return sizeof(bool);
  84. }
  85. //-------------------------------------------------------------------------------------------------------------------
  86. double RtlRealTypeInfo::value(const byte * self) const
  87. {
  88. if (length == 4)
  89. return *(const float *)self;
  90. return *(const double *)self;
  91. }
  92. size32_t RtlRealTypeInfo::process(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IFieldProcessor & target) const
  93. {
  94. target.processReal(value(self), field);
  95. return length;
  96. }
  97. size32_t RtlRealTypeInfo::toXML(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IXmlWriter & target) const
  98. {
  99. target.outputReal(value(self), queryXPath(field));
  100. return length;
  101. }
  102. //-------------------------------------------------------------------------------------------------------------------
  103. size32_t RtlIntTypeInfo::process(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IFieldProcessor & target) const
  104. {
  105. if (isUnsigned())
  106. target.processUInt(rtlReadUInt(self, length), field);
  107. else
  108. target.processInt(rtlReadInt(self, length), field);
  109. return length;
  110. }
  111. size32_t RtlIntTypeInfo::toXML(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IXmlWriter & target) const
  112. {
  113. if (isUnsigned())
  114. target.outputUInt(rtlReadUInt(self, length), queryXPath(field));
  115. else
  116. target.outputInt(rtlReadInt(self, length), queryXPath(field));
  117. return length;
  118. }
  119. //-------------------------------------------------------------------------------------------------------------------
  120. size32_t RtlSwapIntTypeInfo::process(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IFieldProcessor & target) const
  121. {
  122. if (isUnsigned())
  123. target.processUInt(rtlReadSwapUInt(self, length), field);
  124. else
  125. target.processInt(rtlReadSwapInt(self, length), field);
  126. return length;
  127. }
  128. size32_t RtlSwapIntTypeInfo::toXML(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IXmlWriter & target) const
  129. {
  130. if (isUnsigned())
  131. target.outputUInt(rtlReadSwapUInt(self, length), queryXPath(field));
  132. else
  133. target.outputInt(rtlReadSwapInt(self, length), queryXPath(field));
  134. return length;
  135. }
  136. //-------------------------------------------------------------------------------------------------------------------
  137. size32_t RtlPackedIntTypeInfo::size(const byte * self, const byte * selfrow) const
  138. {
  139. return rtlGetPackedSize(self);
  140. }
  141. size32_t RtlPackedIntTypeInfo::process(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IFieldProcessor & target) const
  142. {
  143. if (isUnsigned())
  144. target.processUInt(rtlGetPackedUnsigned(self), field);
  145. else
  146. target.processInt(rtlGetPackedSigned(self), field);
  147. return rtlGetPackedSize(self);
  148. }
  149. size32_t RtlPackedIntTypeInfo::toXML(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IXmlWriter & target) const
  150. {
  151. if (isUnsigned())
  152. target.outputUInt(rtlGetPackedUnsigned(self), queryXPath(field));
  153. else
  154. target.outputInt(rtlGetPackedSigned(self), queryXPath(field));
  155. return rtlGetPackedSize(self);
  156. }
  157. //-------------------------------------------------------------------------------------------------------------------
  158. size32_t RtlStringTypeInfo::size(const byte * self, const byte * selfrow) const
  159. {
  160. if (isFixedSize())
  161. return length;
  162. return sizeof(size32_t) + rtlReadUInt4(self);
  163. }
  164. size32_t RtlStringTypeInfo::process(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IFieldProcessor & target) const
  165. {
  166. const char * str = reinterpret_cast<const char *>(self);
  167. unsigned thisLength;
  168. unsigned thisSize;
  169. if (isFixedSize())
  170. {
  171. thisLength = length;
  172. thisSize = thisLength;
  173. }
  174. else
  175. {
  176. str = reinterpret_cast<const char *>(self + sizeof(size32_t));
  177. thisLength = rtlReadUInt4(self);
  178. thisSize = sizeof(size32_t) + thisLength;
  179. }
  180. if (isEbcdic())
  181. {
  182. unsigned lenAscii;
  183. rtlDataAttr ascii;
  184. rtlEStrToStrX(lenAscii, ascii.refstr(), thisLength, str);
  185. target.processString(lenAscii, ascii.getstr(), field);
  186. }
  187. else
  188. {
  189. target.processString(thisLength, str, field);
  190. }
  191. return thisSize;
  192. }
  193. size32_t RtlStringTypeInfo::toXML(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IXmlWriter & target) const
  194. {
  195. const char * str = reinterpret_cast<const char *>(self);
  196. unsigned thisLength;
  197. unsigned thisSize;
  198. if (isFixedSize())
  199. {
  200. thisLength = length;
  201. thisSize = thisLength;
  202. }
  203. else
  204. {
  205. str = reinterpret_cast<const char *>(self + sizeof(size32_t));
  206. thisLength = rtlReadUInt4(self);
  207. thisSize = sizeof(size32_t) + thisLength;
  208. }
  209. if (isEbcdic())
  210. {
  211. unsigned lenAscii;
  212. rtlDataAttr ascii;
  213. rtlEStrToStrX(lenAscii, ascii.refstr(), thisLength, str);
  214. target.outputString(lenAscii, ascii.getstr(), queryXPath(field));
  215. }
  216. else
  217. {
  218. target.outputString(thisLength, str, queryXPath(field));
  219. }
  220. return thisSize;
  221. }
  222. //-------------------------------------------------------------------------------------------------------------------
  223. size32_t RtlDataTypeInfo::size(const byte * self, const byte * selfrow) const
  224. {
  225. if (isFixedSize())
  226. return length;
  227. return sizeof(size32_t) + rtlReadUInt4(self);
  228. }
  229. size32_t RtlDataTypeInfo::process(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IFieldProcessor & target) const
  230. {
  231. const char * str = reinterpret_cast<const char *>(self);
  232. unsigned thisLength;
  233. unsigned thisSize;
  234. if (isFixedSize())
  235. {
  236. thisLength = length;
  237. thisSize = thisLength;
  238. }
  239. else
  240. {
  241. str = reinterpret_cast<const char *>(self + sizeof(size32_t));
  242. thisLength = rtlReadUInt4(self);
  243. thisSize = sizeof(size32_t) + thisLength;
  244. }
  245. target.processData(thisLength, str, field);
  246. return thisSize;
  247. }
  248. size32_t RtlDataTypeInfo::toXML(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IXmlWriter & target) const
  249. {
  250. const char * str = reinterpret_cast<const char *>(self);
  251. unsigned thisLength;
  252. unsigned thisSize;
  253. if (isFixedSize())
  254. {
  255. thisLength = length;
  256. thisSize = thisLength;
  257. }
  258. else
  259. {
  260. str = reinterpret_cast<const char *>(self + sizeof(size32_t));
  261. thisLength = rtlReadUInt4(self);
  262. thisSize = sizeof(size32_t) + thisLength;
  263. }
  264. target.outputData(thisLength, str, queryXPath(field));
  265. return thisSize;
  266. }
  267. //-------------------------------------------------------------------------------------------------------------------
  268. size32_t RtlVarStringTypeInfo::size(const byte * self, const byte * selfrow) const
  269. {
  270. if (isFixedSize())
  271. return length + 1;
  272. const char * str = reinterpret_cast<const char *>(self);
  273. return (size32_t)strlen(str)+1;
  274. }
  275. size32_t RtlVarStringTypeInfo::process(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IFieldProcessor & target) const
  276. {
  277. const char * str = reinterpret_cast<const char *>(self);
  278. unsigned thisLength = (size32_t)strlen(str);
  279. unsigned thisSize;
  280. if (isFixedSize())
  281. thisSize = length+1;
  282. else
  283. thisSize = thisLength+1;
  284. if (isEbcdic())
  285. {
  286. unsigned lenAscii;
  287. rtlDataAttr ascii;
  288. rtlEStrToStrX(lenAscii, ascii.refstr(), thisLength, str);
  289. target.processString(lenAscii, ascii.getstr(), field);
  290. }
  291. else
  292. target.processString(thisLength, str, field);
  293. return thisSize;
  294. }
  295. size32_t RtlVarStringTypeInfo::toXML(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IXmlWriter & target) const
  296. {
  297. const char * str = reinterpret_cast<const char *>(self);
  298. unsigned thisLength = (size32_t)strlen(str);
  299. unsigned thisSize;
  300. if (isFixedSize())
  301. thisSize = length+1;
  302. else
  303. thisSize = thisLength+1;
  304. if (isEbcdic())
  305. {
  306. unsigned lenAscii;
  307. rtlDataAttr ascii;
  308. rtlEStrToStrX(lenAscii, ascii.refstr(), thisLength, str);
  309. target.outputString(lenAscii, ascii.getstr(), queryXPath(field));
  310. }
  311. else
  312. target.outputString(thisLength, str, queryXPath(field));
  313. return thisSize;
  314. }
  315. //-------------------------------------------------------------------------------------------------------------------
  316. size32_t RtlQStringTypeInfo::size(const byte * self, const byte * selfrow) const
  317. {
  318. if (isFixedSize())
  319. return rtlQStrSize(length);
  320. return sizeof(size32_t) + rtlQStrSize(rtlReadUInt4(self));
  321. }
  322. size32_t RtlQStringTypeInfo::process(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IFieldProcessor & target) const
  323. {
  324. const char * str = reinterpret_cast<const char *>(self);
  325. unsigned thisLength;
  326. unsigned thisSize;
  327. if (isFixedSize())
  328. {
  329. thisLength = length;
  330. thisSize = rtlQStrSize(thisLength);
  331. }
  332. else
  333. {
  334. str = reinterpret_cast<const char *>(self + sizeof(size32_t));
  335. thisLength = rtlReadUInt4(self);
  336. thisSize = sizeof(size32_t) + rtlQStrSize(thisLength);
  337. }
  338. target.processQString(thisLength, str, field);
  339. return thisSize;
  340. }
  341. size32_t RtlQStringTypeInfo::toXML(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IXmlWriter & target) const
  342. {
  343. const char * str = reinterpret_cast<const char *>(self);
  344. unsigned thisLength;
  345. unsigned thisSize;
  346. if (isFixedSize())
  347. {
  348. thisLength = length;
  349. thisSize = rtlQStrSize(thisLength);
  350. }
  351. else
  352. {
  353. str = reinterpret_cast<const char *>(self + sizeof(size32_t));
  354. thisLength = rtlReadUInt4(self);
  355. thisSize = sizeof(size32_t) + rtlQStrSize(thisLength);
  356. }
  357. target.outputQString(thisLength, str, queryXPath(field));
  358. return thisSize;
  359. }
  360. //-------------------------------------------------------------------------------------------------------------------
  361. size32_t RtlDecimalTypeInfo::calcSize() const
  362. {
  363. if (isUnsigned())
  364. return (getDecimalDigits()+1)/2;
  365. return (getDecimalDigits()+2)/2;
  366. }
  367. size32_t RtlDecimalTypeInfo::size(const byte * self, const byte * selfrow) const
  368. {
  369. return calcSize();
  370. }
  371. size32_t RtlDecimalTypeInfo::process(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IFieldProcessor & target) const
  372. {
  373. size32_t thisSize = calcSize();
  374. if (isUnsigned())
  375. target.processUDecimal(self, thisSize, getDecimalPrecision(), field);
  376. else
  377. target.processDecimal(self, thisSize, getDecimalPrecision(), field);
  378. return thisSize;
  379. }
  380. size32_t RtlDecimalTypeInfo::toXML(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IXmlWriter & target) const
  381. {
  382. size32_t thisSize = calcSize();
  383. if (isUnsigned())
  384. target.outputUDecimal(self, thisSize, getDecimalPrecision(), queryXPath(field));
  385. else
  386. target.outputDecimal(self, thisSize, getDecimalPrecision(), queryXPath(field));
  387. return thisSize;
  388. }
  389. //-------------------------------------------------------------------------------------------------------------------
  390. size32_t RtlCharTypeInfo::process(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IFieldProcessor & target) const
  391. {
  392. const char * str = reinterpret_cast<const char *>(self);
  393. char c;
  394. if (isEbcdic())
  395. rtlEStrToStr(1, &c, 1, str);
  396. else
  397. c = *str;
  398. target.processString(1, &c, field);
  399. return 1;
  400. }
  401. size32_t RtlCharTypeInfo::toXML(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IXmlWriter & target) const
  402. {
  403. const char * str = reinterpret_cast<const char *>(self);
  404. char c;
  405. if (isEbcdic())
  406. rtlEStrToStr(1, &c, 1, str);
  407. else
  408. c = *str;
  409. target.outputString(1, &c, queryXPath(field));
  410. return 1;
  411. }
  412. //-------------------------------------------------------------------------------------------------------------------
  413. size32_t RtlUnicodeTypeInfo::size(const byte * self, const byte * selfrow) const
  414. {
  415. if (isFixedSize())
  416. return length * sizeof(UChar);
  417. return sizeof(size32_t) + rtlReadUInt4(self) * sizeof(UChar);
  418. }
  419. size32_t RtlUnicodeTypeInfo::process(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IFieldProcessor & target) const
  420. {
  421. const UChar * ustr = reinterpret_cast<const UChar *>(self);
  422. unsigned thisLength;
  423. unsigned thisSize;
  424. if (isFixedSize())
  425. {
  426. thisLength = length;
  427. thisSize = thisLength * sizeof(UChar);
  428. }
  429. else
  430. {
  431. ustr = reinterpret_cast<const UChar *>(self + sizeof(size32_t));
  432. thisLength = rtlReadUInt4(self);
  433. thisSize = sizeof(size32_t) + thisLength * sizeof(UChar);
  434. }
  435. target.processUnicode(thisLength, ustr, field);
  436. return thisSize;
  437. }
  438. size32_t RtlUnicodeTypeInfo::toXML(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IXmlWriter & target) const
  439. {
  440. const UChar * ustr = reinterpret_cast<const UChar *>(self);
  441. unsigned thisLength;
  442. unsigned thisSize;
  443. if (isFixedSize())
  444. {
  445. thisLength = length;
  446. thisSize = thisLength * sizeof(UChar);
  447. }
  448. else
  449. {
  450. ustr = reinterpret_cast<const UChar *>(self + sizeof(size32_t));
  451. thisLength = rtlReadUInt4(self);
  452. thisSize = sizeof(size32_t) + thisLength * sizeof(UChar);
  453. }
  454. target.outputUnicode(thisLength, ustr, queryXPath(field));
  455. return thisSize;
  456. }
  457. //-------------------------------------------------------------------------------------------------------------------
  458. size32_t RtlVarUnicodeTypeInfo::size(const byte * self, const byte * selfrow) const
  459. {
  460. if (isFixedSize())
  461. return (length+1) * sizeof(UChar);
  462. const UChar * ustr = reinterpret_cast<const UChar *>(self);
  463. return (rtlUnicodeStrlen(ustr)+1) * sizeof(UChar);
  464. }
  465. size32_t RtlVarUnicodeTypeInfo::process(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IFieldProcessor & target) const
  466. {
  467. const UChar * ustr = reinterpret_cast<const UChar *>(self);
  468. unsigned thisLength = rtlUnicodeStrlen(ustr);
  469. unsigned thisSize;
  470. if (isFixedSize())
  471. thisSize = (length + 1) * sizeof(UChar);
  472. else
  473. thisSize = (thisLength + 1) * sizeof(UChar);
  474. target.processUnicode(thisLength, ustr, field);
  475. return thisSize;
  476. }
  477. size32_t RtlVarUnicodeTypeInfo::toXML(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IXmlWriter & target) const
  478. {
  479. const UChar * ustr = reinterpret_cast<const UChar *>(self);
  480. unsigned thisLength = rtlUnicodeStrlen(ustr);
  481. unsigned thisSize;
  482. if (isFixedSize())
  483. thisSize = (length + 1) * sizeof(UChar);
  484. else
  485. thisSize = (thisLength + 1) * sizeof(UChar);
  486. target.outputUnicode(thisLength, ustr, queryXPath(field));
  487. return thisSize;
  488. }
  489. //-------------------------------------------------------------------------------------------------------------------
  490. size32_t RtlUtf8TypeInfo::size(const byte * self, const byte * selfrow) const
  491. {
  492. assertex(!isFixedSize());
  493. return sizeof(size32_t) + rtlUtf8Size(rtlReadUInt4(self), self+sizeof(unsigned));
  494. }
  495. size32_t RtlUtf8TypeInfo::process(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IFieldProcessor & target) const
  496. {
  497. assertex(!isFixedSize());
  498. const char * str = reinterpret_cast<const char *>(self + sizeof(size32_t));
  499. unsigned thisLength = rtlReadUInt4(self);
  500. unsigned thisSize = sizeof(size32_t) + rtlUtf8Size(thisLength, str);
  501. target.processUtf8(thisLength, str, field);
  502. return thisSize;
  503. }
  504. size32_t RtlUtf8TypeInfo::toXML(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IXmlWriter & target) const
  505. {
  506. assertex(!isFixedSize());
  507. const char * str = reinterpret_cast<const char *>(self + sizeof(size32_t));
  508. unsigned thisLength = rtlReadUInt4(self);
  509. unsigned thisSize = sizeof(size32_t) + rtlUtf8Size(thisLength, str);
  510. target.outputUtf8(thisLength, str, queryXPath(field));
  511. return thisSize;
  512. }
  513. //-------------------------------------------------------------------------------------------------------------------
  514. inline size32_t sizeFields(const RtlFieldInfo * const * cur, const byte * self, const byte * selfrow)
  515. {
  516. unsigned offset = 0;
  517. loop
  518. {
  519. const RtlFieldInfo * child = *cur;
  520. if (!child)
  521. break;
  522. offset += child->size(self+offset, selfrow);
  523. cur++;
  524. }
  525. return offset;
  526. }
  527. inline size32_t processFields(const RtlFieldInfo * const * cur, const byte * self, const byte * selfrow, IFieldProcessor & target)
  528. {
  529. unsigned offset = 0;
  530. loop
  531. {
  532. const RtlFieldInfo * child = *cur;
  533. if (!child)
  534. break;
  535. child->process(self+offset, selfrow, target);
  536. offset += child->size(self+offset, selfrow);
  537. cur++;
  538. }
  539. return offset;
  540. }
  541. inline size32_t toXMLFields(const RtlFieldInfo * const * cur, const byte * self, const byte * selfrow, IXmlWriter & target)
  542. {
  543. size32_t offset = 0;
  544. loop
  545. {
  546. const RtlFieldInfo * child = *cur;
  547. if (!child)
  548. break;
  549. size32_t size = child->toXML(self+offset, selfrow, target);
  550. offset += size;
  551. cur++;
  552. }
  553. return offset;
  554. }
  555. //-------------------------------------------------------------------------------------------------------------------
  556. size32_t RtlRecordTypeInfo::size(const byte * self, const byte * selfrow) const
  557. {
  558. return sizeFields(fields, self, self);
  559. }
  560. size32_t RtlRecordTypeInfo::process(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IFieldProcessor & target) const
  561. {
  562. if (target.processBeginRow(field))
  563. {
  564. unsigned offset = processFields(fields, self, self, target);
  565. target.processEndRow(field);
  566. return offset;
  567. }
  568. return size(self, selfrow);
  569. }
  570. size32_t RtlRecordTypeInfo::toXML(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IXmlWriter & target) const
  571. {
  572. const char * xpath = queryXPath(field);
  573. if (*xpath)
  574. target.outputBeginNested(xpath, false);
  575. unsigned thisSize = toXMLFields(fields, self, self, target);
  576. if (*xpath)
  577. target.outputEndNested(xpath);
  578. return thisSize;
  579. }
  580. //-------------------------------------------------------------------------------------------------------------------
  581. size32_t RtlSetTypeInfo::size(const byte * self, const byte * selfrow) const
  582. {
  583. return sizeof(bool) + sizeof(size32_t) + rtlReadUInt4(self + sizeof(bool));
  584. }
  585. size32_t RtlSetTypeInfo::process(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IFieldProcessor & target) const
  586. {
  587. unsigned offset = sizeof(bool) + sizeof(size32_t);
  588. unsigned max = offset + rtlReadUInt4(self + sizeof(bool));
  589. if (target.processBeginSet(field))
  590. {
  591. if (*(bool *)self)
  592. target.processSetAll(field);
  593. else
  594. {
  595. while (offset < max)
  596. {
  597. offset += child->process(self+offset, selfrow, field, target);
  598. }
  599. }
  600. target.processEndSet(field);
  601. }
  602. return max;
  603. }
  604. size32_t RtlSetTypeInfo::toXML(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IXmlWriter & target) const
  605. {
  606. unsigned offset = sizeof(bool) + sizeof(size32_t);
  607. unsigned max = offset + rtlReadUInt4(self + sizeof(bool));
  608. StringAttr outerTag;
  609. if (hasOuterXPath(field))
  610. {
  611. queryNestedOuterXPath(outerTag, field);
  612. target.outputBeginNested(outerTag, false);
  613. }
  614. const char *innerPath = queryXPath(field);
  615. target.outputBeginArray(innerPath);
  616. if (*(bool *)self)
  617. target.outputSetAll();
  618. else
  619. {
  620. while (offset < max)
  621. {
  622. child->toXML(self+offset, selfrow, field, target);
  623. offset += child->size(self+offset, selfrow);
  624. }
  625. }
  626. target.outputEndArray(innerPath);
  627. if (outerTag)
  628. target.outputEndNested(outerTag);
  629. return max;
  630. }
  631. //-------------------------------------------------------------------------------------------------------------------
  632. size32_t RtlRowTypeInfo::size(const byte * self, const byte * selfrow) const
  633. {
  634. if (isLinkCounted())
  635. return sizeof(void *);
  636. return child->size(self, selfrow);
  637. }
  638. size32_t RtlRowTypeInfo::process(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IFieldProcessor & target) const
  639. {
  640. if (isLinkCounted())
  641. {
  642. const byte * row = *(const byte * *)self;
  643. if (row)
  644. child->process(row, row, field, target);
  645. return sizeof(row);
  646. }
  647. return child->process(self, self, field, target);
  648. }
  649. size32_t RtlRowTypeInfo::toXML(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IXmlWriter & target) const
  650. {
  651. if (isLinkCounted())
  652. {
  653. const byte * row = *(const byte * *)self;
  654. child->toXML(row, row, field, target);
  655. return sizeof(row);
  656. }
  657. return child->toXML(self, self, field, target);
  658. }
  659. //-------------------------------------------------------------------------------------------------------------------
  660. size32_t RtlDatasetTypeInfo::size(const byte * self, const byte * selfrow) const
  661. {
  662. if (isLinkCounted())
  663. return sizeof(size32_t) + sizeof(void * *);
  664. return sizeof(size32_t) + rtlReadUInt4(self);
  665. }
  666. size32_t RtlDatasetTypeInfo::process(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IFieldProcessor & target) const
  667. {
  668. if (isLinkCounted())
  669. {
  670. if (target.processBeginDataset(field))
  671. {
  672. size32_t thisCount = rtlReadUInt4(self);
  673. const byte * * rows = *reinterpret_cast<const byte * * const *>(self + sizeof(size32_t));
  674. for (unsigned i= 0; i < thisCount; i++)
  675. {
  676. const byte * row = rows[i];
  677. child->process(row, row, field, target);
  678. }
  679. target.processEndDataset(field);
  680. }
  681. return sizeof(size32_t) + sizeof(void * *);
  682. }
  683. else
  684. {
  685. unsigned offset = sizeof(size32_t);
  686. unsigned max = offset + rtlReadUInt4(self);
  687. if (target.processBeginDataset(field))
  688. {
  689. while (offset < max)
  690. {
  691. offset += child->process(self+offset, self+offset, field, target);
  692. }
  693. target.processEndDataset(field);
  694. }
  695. return max;
  696. }
  697. }
  698. size32_t RtlDatasetTypeInfo::toXML(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IXmlWriter & target) const
  699. {
  700. StringAttr outerTag;
  701. if (hasOuterXPath(field))
  702. {
  703. queryNestedOuterXPath(outerTag, field);
  704. target.outputBeginNested(outerTag, false);
  705. }
  706. const char *innerPath = queryXPath(field);
  707. target.outputBeginArray(innerPath);
  708. unsigned thisSize;
  709. if (isLinkCounted())
  710. {
  711. size32_t thisCount = rtlReadUInt4(self);
  712. const byte * * rows = *reinterpret_cast<const byte * * const *>(self + sizeof(size32_t));
  713. for (unsigned i= 0; i < thisCount; i++)
  714. {
  715. const byte * row = rows[i];
  716. if (row)
  717. child->toXML(row, row, field, target);
  718. }
  719. thisSize = sizeof(size32_t) + sizeof(void * *);
  720. }
  721. else
  722. {
  723. unsigned offset = sizeof(size32_t);
  724. unsigned max = offset + rtlReadUInt4(self);
  725. while (offset < max)
  726. {
  727. child->toXML(self+offset, self+offset, field, target);
  728. offset += child->size(self+offset, self+offset);
  729. }
  730. thisSize = max;
  731. }
  732. target.outputEndArray(innerPath);
  733. if (outerTag)
  734. target.outputEndNested(outerTag);
  735. return thisSize;
  736. }
  737. //-------------------------------------------------------------------------------------------------------------------
  738. size32_t RtlDictionaryTypeInfo::size(const byte * self, const byte * selfrow) const
  739. {
  740. if (isLinkCounted())
  741. return sizeof(size32_t) + sizeof(void * *);
  742. return sizeof(size32_t) + rtlReadUInt4(self);
  743. }
  744. size32_t RtlDictionaryTypeInfo::process(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IFieldProcessor & target) const
  745. {
  746. if (isLinkCounted())
  747. {
  748. if (target.processBeginDataset(field))
  749. {
  750. size32_t thisCount = rtlReadUInt4(self);
  751. const byte * * rows = *reinterpret_cast<const byte * * const *>(self + sizeof(size32_t));
  752. for (unsigned i= 0; i < thisCount; i++)
  753. {
  754. const byte * row = rows[i];
  755. if (row)
  756. child->process(row, row, field, target);
  757. }
  758. target.processEndDataset(field);
  759. }
  760. return sizeof(size32_t) + sizeof(void * *);
  761. }
  762. else
  763. {
  764. //MORE: We could interpret serialized dictionaries if there was ever a need
  765. UNIMPLEMENTED;
  766. }
  767. }
  768. size32_t RtlDictionaryTypeInfo::toXML(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IXmlWriter & target) const
  769. {
  770. StringAttr outerTag;
  771. if (hasOuterXPath(field))
  772. {
  773. queryNestedOuterXPath(outerTag, field);
  774. target.outputBeginNested(outerTag, false);
  775. }
  776. const char *innerPath = queryXPath(field);
  777. target.outputBeginArray(innerPath);
  778. unsigned thisSize;
  779. if (isLinkCounted())
  780. {
  781. size32_t thisCount = rtlReadUInt4(self);
  782. const byte * * rows = *reinterpret_cast<const byte * * const *>(self + sizeof(size32_t));
  783. for (unsigned i= 0; i < thisCount; i++)
  784. {
  785. const byte * row = rows[i];
  786. if (row)
  787. child->toXML(row, row, field, target);
  788. }
  789. thisSize = sizeof(size32_t) + sizeof(void * *);
  790. }
  791. else
  792. {
  793. //MORE: We could interpret serialized dictionaries if there was ever a need
  794. UNIMPLEMENTED;
  795. }
  796. target.outputEndArray(innerPath);
  797. if (outerTag)
  798. target.outputEndNested(outerTag);
  799. return thisSize;
  800. }
  801. //-------------------------------------------------------------------------------------------------------------------
  802. size32_t RtlIfBlockTypeInfo::size(const byte * self, const byte * selfrow) const
  803. {
  804. if (getCondition(selfrow))
  805. return sizeFields(fields, self, selfrow);
  806. return 0;
  807. }
  808. size32_t RtlIfBlockTypeInfo::process(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IFieldProcessor & target) const
  809. {
  810. if (getCondition(selfrow))
  811. return processFields(fields, self, selfrow, target);
  812. return 0;
  813. }
  814. size32_t RtlIfBlockTypeInfo::toXML(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IXmlWriter & target) const
  815. {
  816. if (getCondition(selfrow))
  817. return toXMLFields(fields, self, selfrow, target);
  818. return 0;
  819. }
  820. //-------------------------------------------------------------------------------------------------------------------
  821. __int64 RtlBitfieldTypeInfo::signedValue(const byte * self) const
  822. {
  823. __int64 value = rtlReadInt(self, getBitfieldIntSize());
  824. unsigned shift = getBitfieldShift();
  825. unsigned numBits = getBitfieldNumBits();
  826. value <<= (sizeof(value) - shift - numBits);
  827. return value >> numBits;
  828. }
  829. unsigned __int64 RtlBitfieldTypeInfo::unsignedValue(const byte * self) const
  830. {
  831. unsigned __int64 value = rtlReadInt(self, getBitfieldIntSize());
  832. unsigned shift = getBitfieldShift();
  833. unsigned numBits = getBitfieldNumBits();
  834. value <<= (sizeof(value) - shift - numBits);
  835. return value >> numBits;
  836. }
  837. size32_t RtlBitfieldTypeInfo::size(const byte * self, const byte * selfrow) const
  838. {
  839. if (fieldType & RFTMislastbitfield)
  840. return getBitfieldIntSize();
  841. return 0;
  842. }
  843. size32_t RtlBitfieldTypeInfo::process(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IFieldProcessor & target) const
  844. {
  845. if (isUnsigned())
  846. target.processUInt(unsignedValue(self), field);
  847. else
  848. target.processInt(signedValue(self), field);
  849. return size(self, selfrow);
  850. }
  851. size32_t RtlBitfieldTypeInfo::toXML(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IXmlWriter & target) const
  852. {
  853. if (isUnsigned())
  854. target.outputUInt(unsignedValue(self), queryXPath(field));
  855. else
  856. target.outputInt(signedValue(self), queryXPath(field));
  857. return size(self, selfrow);
  858. }
  859. //-------------------------------------------------------------------------------------------------------------------
  860. size32_t RtlUnimplementedTypeInfo::size(const byte * self, const byte * selfrow) const
  861. {
  862. rtlFailUnexpected();
  863. return 0;
  864. }
  865. size32_t RtlUnimplementedTypeInfo::process(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IFieldProcessor & target) const
  866. {
  867. rtlFailUnexpected();
  868. return 0;
  869. }
  870. size32_t RtlUnimplementedTypeInfo::toXML(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IXmlWriter & target) const
  871. {
  872. rtlFailUnexpected();
  873. return 0;
  874. }
  875. //-------------------------------------------------------------------------------------------------------------------
  876. RtlFieldStrInfo::RtlFieldStrInfo(const char * _name, const char * _xpath, const RtlTypeInfo * _type)
  877. : RtlFieldInfo(rtlCreateFieldNameAtom(_name), _xpath, _type)
  878. {
  879. }
  880. /*
  881. Stack:
  882. * Change hqlhtcpp so that the correct derived classes are generated.
  883. * Test so that toXML calls the default implementaions and check that the same values are generated. (Don't if contains ifblocks/alien)
  884. * Release
  885. * Think about bitfields - how do I know it is the last bitfield, how am I going to keep track of the offsets.
  886. * What code would need to be generated for alien datatypes.
  887. * Could have alien int and alien string varieties????
  888. * What would an ecl interpreter look like (a special workunit?) helpers are interpreted? What about the graph?
  889. * Could I add associations to register user attributes - so a callback could know when they were assigned to?
  890. * Could I add ctx->noteLocation() into the generated code - so could put breakpoints on variables.
  891. * Add annotation when a member of the target dataset is updated.
  892. ctx->noteFieldAssigned(self, <field>); - does this include temporary datasets?
  893. ctx->noteAttributeX(<name>, Int|String|Unicode|
  894. ctx->noteLocation(location); - reduce locations, so only one returned per line for a non-dataset? Should it just be the first item on the line that is tagged??
  895. * Need static information about the breakpoints so debugger knows where to put valid brakpoints....
  896. * Debugger will want to know about the type of the breakpoints.
  897. * Should try and compress the location format - possibly have a table of <module.attributes>-># with breakpoint as 12:23
  898. Also need some information about which datasets, and stored variables etc. are used so they can be displayed.
  899. - Most datasets can be deduced from the parameters passed into the transform
  900. - Some are trickier e.g., the extract, could possibly define some mappings
  901. - options to disable projects/other more complex operations inline (so easier to walk through)
  902. Bitfields:
  903. - Two separate questions:
  904. i) How is the meta information generated.
  905. ii) How is it stored internally in an IHqlExpression * ?
  906. * Could store the offset in the type - either in the base type of as a qualifier.
  907. + much easier code generation.
  908. - Doesn't provie an easy indication of the last field in a bitfield (because can't really modify after the fact)
  909. - Problematic when fields are removed to merge them.
  910. * Could add a bitfield container to the record.
  911. + Makes it easier to handle the last bitfield
  912. + Matches the structure used for the cursor.
  913. - Everything needs to walk the bitfield containers similar to ifblocks.
  914. - Makes it just as tricky to merge
  915. - Harder to create the record, unless the code is implicitly handled by appendOperand().
  916. * The type of no_select could contain a modifier to indicate the offset/islast
  917. + the type of a no_select would have a 1:1 mapping with type info.
  918. - A bit complicated to calculate, especially when it isn't used much of the time
  919. => On Reflection is is probably easiest to keep the structure as it is (some comments should go in hqlexpr to avoid revisiting).
  920. * interperet bitfield offsets and "is last bitfield" dynamically
  921. + Greatly simplifies generating the meta - you can always use the field.
  922. - Requires another parameter and significant extra complexity for the uncommon case. (especially incrementing self)
  923. * Could generate from the expanded record instead of walking the record structure directly
  924. + That already knows how the bitfields are allocated, and could easily know which is the last field.
  925. - A field is no longer sufficient as key fr searching for the information.
  926. - Best would be a createFieldTypeKey(select-expr) which returns field when approriate, or modified if a bitfield. Then the pain is localised.
  927. * Output a bitfield container item into the type information
  928. + Solves the size problem
  929. - Individual bitfields still need to know their offsets, so doesn't solve the full problem.
  930. =>
  931. Change so that either use meta to generate the information, or use no_select when appropriate to fidn out the nesc. information.
  932. Probably the latter for the moment.
  933. a) Create a key function and make sure it is always used.
  934. b) Need to work out how to generate no_ifblock.
  935. - ifblock is context dependent, so need to generate as part of the parent record, and in the parent record context.
  936. */