rtlfield.cpp 53 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540
  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. #include "rtlds_imp.hpp"
  22. #include "nbcd.hpp"
  23. static const char * queryXPath(const RtlFieldInfo * field)
  24. {
  25. const char * xpath = field->xpath;
  26. if (xpath)
  27. {
  28. const char * sep = strchr(xpath, xpathCompoundSeparatorChar);
  29. if (!sep)
  30. return xpath;
  31. return sep+1;
  32. }
  33. return str(field->name);
  34. }
  35. static const char * queryScalarXPath(const RtlFieldInfo * field)
  36. {
  37. if (field->type->hasNonScalarXpath())
  38. return str(field->name);
  39. return queryXPath(field);
  40. }
  41. static bool hasOuterXPath(const RtlFieldInfo * field)
  42. {
  43. const char * xpath = field->xpath;
  44. assertex(xpath);
  45. return (*xpath != xpathCompoundSeparatorChar);
  46. }
  47. static void queryNestedOuterXPath(StringAttr & ret, const RtlFieldInfo * field)
  48. {
  49. const char * xpath = field->xpath;
  50. assertex(xpath);
  51. const char * sep = strchr(xpath, xpathCompoundSeparatorChar);
  52. assertex(sep);
  53. ret.set(xpath, (size32_t)(sep-xpath));
  54. }
  55. //-------------------------------------------------------------------------------------------------------------------
  56. class DummyFieldProcessor : public CInterfaceOf<IFieldProcessor>
  57. {
  58. public:
  59. virtual void processString(unsigned len, const char *value, const RtlFieldInfo * field) {}
  60. virtual void processBool(bool value, const RtlFieldInfo * field) {}
  61. virtual void processData(unsigned len, const void *value, const RtlFieldInfo * field) {}
  62. virtual void processInt(__int64 value, const RtlFieldInfo * field) {}
  63. virtual void processUInt(unsigned __int64 value, const RtlFieldInfo * field) {}
  64. virtual void processReal(double value, const RtlFieldInfo * field) {}
  65. virtual void processDecimal(const void *value, unsigned digits, unsigned precision, const RtlFieldInfo * field) {}
  66. virtual void processUDecimal(const void *value, unsigned digits, unsigned precision, const RtlFieldInfo * field) {}
  67. virtual void processUnicode(unsigned len, const UChar *value, const RtlFieldInfo * field) {}
  68. virtual void processQString(unsigned len, const char *value, const RtlFieldInfo * field) {}
  69. virtual void processUtf8(unsigned len, const char *value, const RtlFieldInfo * field) {}
  70. virtual bool processBeginSet(const RtlFieldInfo * field, unsigned numElements, bool isAll, const byte *data) { return false; }
  71. virtual bool processBeginDataset(const RtlFieldInfo * field, unsigned numRows) { return true; }
  72. virtual bool processBeginRow(const RtlFieldInfo * field) { return true; }
  73. virtual void processEndSet(const RtlFieldInfo * field) {}
  74. virtual void processEndDataset(const RtlFieldInfo * field) {}
  75. virtual void processEndRow(const RtlFieldInfo * field) {}
  76. };
  77. //-------------------------------------------------------------------------------------------------------------------
  78. size32_t RtlTypeInfoBase::size(const byte * self, const byte * selfrow) const
  79. {
  80. return length;
  81. }
  82. size32_t RtlTypeInfoBase::process(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IFieldProcessor & target) const
  83. {
  84. rtlFailUnexpected();
  85. return 0;
  86. }
  87. size32_t RtlTypeInfoBase::toXML(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IXmlWriter & out) const
  88. {
  89. rtlFailUnexpected();
  90. return 0;
  91. }
  92. size32_t RtlTypeInfoBase::build(ARowBuilder &builder, size32_t offset, const RtlFieldInfo *field, IFieldSource &source) const
  93. {
  94. rtlFailUnexpected();
  95. return 0;
  96. }
  97. const char * RtlTypeInfoBase::queryLocale() const
  98. {
  99. return NULL;
  100. }
  101. const RtlFieldInfo * const * RtlTypeInfoBase::queryFields() const
  102. {
  103. return NULL;
  104. }
  105. const RtlTypeInfo * RtlTypeInfoBase::queryChildType() const
  106. {
  107. return NULL;
  108. }
  109. //-------------------------------------------------------------------------------------------------------------------
  110. size32_t RtlBoolTypeInfo::build(ARowBuilder &builder, size32_t offset, const RtlFieldInfo *field, IFieldSource &source) const
  111. {
  112. builder.ensureCapacity(sizeof(bool)+offset, str(field->name));
  113. bool val = source.getBooleanResult(field);
  114. * (bool *) (builder.getSelf() + offset) = val;
  115. offset += sizeof(bool);
  116. return offset;
  117. }
  118. size32_t RtlBoolTypeInfo::process(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IFieldProcessor & target) const
  119. {
  120. target.processBool(*(const bool *)self, field);
  121. return sizeof(bool);
  122. }
  123. size32_t RtlBoolTypeInfo::toXML(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IXmlWriter & target) const
  124. {
  125. target.outputBool(*(const bool *)self, queryScalarXPath(field));
  126. return sizeof(bool);
  127. }
  128. //-------------------------------------------------------------------------------------------------------------------
  129. double RtlRealTypeInfo::value(const byte * self) const
  130. {
  131. if (length == 4)
  132. return *(const float *)self;
  133. return *(const double *)self;
  134. }
  135. size32_t RtlRealTypeInfo::build(ARowBuilder &builder, size32_t offset, const RtlFieldInfo *field, IFieldSource &source) const
  136. {
  137. builder.ensureCapacity(length+offset, str(field->name));
  138. double val = source.getRealResult(field);
  139. byte *dest = builder.getSelf() + offset;
  140. if (length == 4)
  141. *(float *) dest = (float) val;
  142. else
  143. *(double *) dest = val;
  144. offset += length;
  145. return offset;
  146. }
  147. size32_t RtlRealTypeInfo::process(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IFieldProcessor & target) const
  148. {
  149. target.processReal(value(self), field);
  150. return length;
  151. }
  152. size32_t RtlRealTypeInfo::toXML(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IXmlWriter & target) const
  153. {
  154. target.outputReal(value(self), queryScalarXPath(field));
  155. return length;
  156. }
  157. //-------------------------------------------------------------------------------------------------------------------
  158. size32_t RtlIntTypeInfo::build(ARowBuilder &builder, size32_t offset, const RtlFieldInfo *field, IFieldSource &source) const
  159. {
  160. builder.ensureCapacity(length+offset, str(field->name));
  161. __int64 val = isUnsigned() ? (__int64) source.getUnsignedResult(field) : source.getSignedResult(field);
  162. rtlWriteInt(builder.getSelf() + offset, val, length);
  163. offset += length;
  164. return offset;
  165. }
  166. size32_t RtlIntTypeInfo::process(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IFieldProcessor & target) const
  167. {
  168. if (isUnsigned())
  169. target.processUInt(rtlReadUInt(self, length), field);
  170. else
  171. target.processInt(rtlReadInt(self, length), field);
  172. return length;
  173. }
  174. size32_t RtlIntTypeInfo::toXML(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IXmlWriter & target) const
  175. {
  176. if (isUnsigned())
  177. target.outputUInt(rtlReadUInt(self, length), length, queryScalarXPath(field));
  178. else
  179. target.outputInt(rtlReadInt(self, length), length, queryScalarXPath(field));
  180. return length;
  181. }
  182. //-------------------------------------------------------------------------------------------------------------------
  183. size32_t RtlSwapIntTypeInfo::build(ARowBuilder &builder, size32_t offset, const RtlFieldInfo *field, IFieldSource &source) const
  184. {
  185. builder.ensureCapacity(length+offset, str(field->name));
  186. __int64 val = isUnsigned() ? (__int64) source.getUnsignedResult(field) : source.getSignedResult(field);
  187. // NOTE - we assume that the value returned from the source is NOT already a swapped int - source doesn;t know that we are going to store it swapped
  188. rtlWriteSwapInt(builder.getSelf() + offset, val, length);
  189. offset += length;
  190. return offset;
  191. }
  192. size32_t RtlSwapIntTypeInfo::process(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IFieldProcessor & target) const
  193. {
  194. if (isUnsigned())
  195. target.processUInt(rtlReadSwapUInt(self, length), field);
  196. else
  197. target.processInt(rtlReadSwapInt(self, length), field);
  198. return length;
  199. }
  200. size32_t RtlSwapIntTypeInfo::toXML(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IXmlWriter & target) const
  201. {
  202. if (isUnsigned())
  203. target.outputUInt(rtlReadSwapUInt(self, length), length, queryScalarXPath(field));
  204. else
  205. target.outputInt(rtlReadSwapInt(self, length), length, queryScalarXPath(field));
  206. return length;
  207. }
  208. //-------------------------------------------------------------------------------------------------------------------
  209. size32_t RtlPackedIntTypeInfo::size(const byte * self, const byte * selfrow) const
  210. {
  211. return rtlGetPackedSize(self);
  212. }
  213. size32_t RtlPackedIntTypeInfo::build(ARowBuilder &builder, size32_t offset, const RtlFieldInfo *field, IFieldSource &source) const
  214. {
  215. unsigned __int64 value = isUnsigned() ? (__int64) source.getUnsignedResult(field) : source.getSignedResult(field);
  216. size32_t sizeInBytes = rtlGetPackedSize(&value);
  217. builder.ensureCapacity(sizeInBytes+offset, str(field->name));
  218. rtlSetPackedUnsigned(builder.getSelf() + offset, value);
  219. offset += sizeInBytes;
  220. return offset;
  221. }
  222. size32_t RtlPackedIntTypeInfo::process(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IFieldProcessor & target) const
  223. {
  224. if (isUnsigned())
  225. target.processUInt(rtlGetPackedUnsigned(self), field);
  226. else
  227. target.processInt(rtlGetPackedSigned(self), field);
  228. return rtlGetPackedSize(self);
  229. }
  230. size32_t RtlPackedIntTypeInfo::toXML(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IXmlWriter & target) const
  231. {
  232. size32_t fieldsize = rtlGetPackedSize(self);
  233. if (isUnsigned())
  234. target.outputUInt(rtlGetPackedUnsigned(self), fieldsize, queryScalarXPath(field));
  235. else
  236. target.outputInt(rtlGetPackedSigned(self), fieldsize, queryScalarXPath(field));
  237. return fieldsize;
  238. }
  239. //-------------------------------------------------------------------------------------------------------------------
  240. size32_t RtlStringTypeInfo::size(const byte * self, const byte * selfrow) const
  241. {
  242. if (isFixedSize())
  243. return length;
  244. return sizeof(size32_t) + rtlReadUInt4(self);
  245. }
  246. size32_t RtlStringTypeInfo::build(ARowBuilder &builder, size32_t offset, const RtlFieldInfo *field, IFieldSource &source) const
  247. {
  248. size32_t size;
  249. char *value;
  250. source.getStringResult(field, size, value);
  251. if (!isFixedSize())
  252. {
  253. builder.ensureCapacity(offset+size+sizeof(size32_t), str(field->name));
  254. byte *dest = builder.getSelf()+offset;
  255. rtlWriteInt4(dest, size);
  256. // NOTE - it has been the subject of debate whether we should convert the incoming data to EBCDIC, or expect the IFieldSource to have already returned ebcdic
  257. // In order to be symmetrical with the passing of ecl data to a IFieldProcessor the former interpretation is preferred.
  258. // Expecting source.getStringResult to somehow "know" that EBCDIC was expected seems odd.
  259. if (isEbcdic())
  260. rtlStrToEStr(size, (char *) dest+sizeof(size32_t), size, (char *)value);
  261. else
  262. memcpy(dest+sizeof(size32_t), value, size);
  263. offset += size+sizeof(size32_t);
  264. }
  265. else
  266. {
  267. builder.ensureCapacity(offset+length, str(field->name));
  268. byte *dest = builder.getSelf()+offset;
  269. if (isEbcdic())
  270. rtlStrToEStr(length, (char *) dest, size, (char *) value);
  271. else
  272. rtlStrToStr(length, dest, size, value);
  273. offset += length;
  274. }
  275. rtlFree(value);
  276. return offset;
  277. }
  278. size32_t RtlStringTypeInfo::process(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IFieldProcessor & target) const
  279. {
  280. const char * str = reinterpret_cast<const char *>(self);
  281. unsigned thisLength;
  282. unsigned thisSize;
  283. if (isFixedSize())
  284. {
  285. thisLength = length;
  286. thisSize = thisLength;
  287. }
  288. else
  289. {
  290. str = reinterpret_cast<const char *>(self + sizeof(size32_t));
  291. thisLength = rtlReadUInt4(self);
  292. thisSize = sizeof(size32_t) + thisLength;
  293. }
  294. if (isEbcdic())
  295. {
  296. unsigned lenAscii;
  297. rtlDataAttr ascii;
  298. rtlEStrToStrX(lenAscii, ascii.refstr(), thisLength, str);
  299. target.processString(lenAscii, ascii.getstr(), field);
  300. }
  301. else
  302. {
  303. target.processString(thisLength, str, field);
  304. }
  305. return thisSize;
  306. }
  307. size32_t RtlStringTypeInfo::toXML(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IXmlWriter & target) const
  308. {
  309. const char * str = reinterpret_cast<const char *>(self);
  310. unsigned thisLength;
  311. unsigned thisSize;
  312. if (isFixedSize())
  313. {
  314. thisLength = length;
  315. thisSize = thisLength;
  316. }
  317. else
  318. {
  319. str = reinterpret_cast<const char *>(self + sizeof(size32_t));
  320. thisLength = rtlReadUInt4(self);
  321. thisSize = sizeof(size32_t) + thisLength;
  322. }
  323. if (isEbcdic())
  324. {
  325. unsigned lenAscii;
  326. rtlDataAttr ascii;
  327. rtlEStrToStrX(lenAscii, ascii.refstr(), thisLength, str);
  328. target.outputString(lenAscii, ascii.getstr(), queryScalarXPath(field));
  329. }
  330. else
  331. {
  332. target.outputString(thisLength, str, queryScalarXPath(field));
  333. }
  334. return thisSize;
  335. }
  336. //-------------------------------------------------------------------------------------------------------------------
  337. size32_t RtlDataTypeInfo::size(const byte * self, const byte * selfrow) const
  338. {
  339. if (isFixedSize())
  340. return length;
  341. return sizeof(size32_t) + rtlReadUInt4(self);
  342. }
  343. size32_t RtlDataTypeInfo::build(ARowBuilder &builder, size32_t offset, const RtlFieldInfo *field, IFieldSource &source) const
  344. {
  345. size32_t size;
  346. void *value;
  347. source.getDataResult(field, size, value);
  348. if (!isFixedSize())
  349. {
  350. builder.ensureCapacity(offset+size+sizeof(size32_t), str(field->name));
  351. byte *dest = builder.getSelf()+offset;
  352. rtlWriteInt4(dest, size);
  353. memcpy(dest+sizeof(size32_t), value, size);
  354. offset += size+sizeof(size32_t);
  355. }
  356. else
  357. {
  358. builder.ensureCapacity(offset+length, str(field->name));
  359. byte *dest = builder.getSelf()+offset;
  360. rtlDataToData(length, dest, size, value);
  361. offset += length;
  362. }
  363. rtlFree(value);
  364. return offset;
  365. }
  366. size32_t RtlDataTypeInfo::process(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IFieldProcessor & target) const
  367. {
  368. const char * str = reinterpret_cast<const char *>(self);
  369. unsigned thisLength;
  370. unsigned thisSize;
  371. if (isFixedSize())
  372. {
  373. thisLength = length;
  374. thisSize = thisLength;
  375. }
  376. else
  377. {
  378. str = reinterpret_cast<const char *>(self + sizeof(size32_t));
  379. thisLength = rtlReadUInt4(self);
  380. thisSize = sizeof(size32_t) + thisLength;
  381. }
  382. target.processData(thisLength, str, field);
  383. return thisSize;
  384. }
  385. size32_t RtlDataTypeInfo::toXML(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IXmlWriter & target) const
  386. {
  387. const char * str = reinterpret_cast<const char *>(self);
  388. unsigned thisLength;
  389. unsigned thisSize;
  390. if (isFixedSize())
  391. {
  392. thisLength = length;
  393. thisSize = thisLength;
  394. }
  395. else
  396. {
  397. str = reinterpret_cast<const char *>(self + sizeof(size32_t));
  398. thisLength = rtlReadUInt4(self);
  399. thisSize = sizeof(size32_t) + thisLength;
  400. }
  401. target.outputData(thisLength, str, queryScalarXPath(field));
  402. return thisSize;
  403. }
  404. //-------------------------------------------------------------------------------------------------------------------
  405. size32_t RtlVarStringTypeInfo::size(const byte * self, const byte * selfrow) const
  406. {
  407. if (isFixedSize())
  408. return length + 1;
  409. const char * str = reinterpret_cast<const char *>(self);
  410. return (size32_t)strlen(str)+1;
  411. }
  412. size32_t RtlVarStringTypeInfo::build(ARowBuilder &builder, size32_t offset, const RtlFieldInfo *field, IFieldSource &source) const
  413. {
  414. size32_t size;
  415. char *value;
  416. source.getStringResult(field, size, value);
  417. if (!isFixedSize())
  418. {
  419. builder.ensureCapacity(offset+size+1, str(field->name));
  420. // See notes re EBCDIC conversion in RtlStringTypeInfo code
  421. byte *dest = builder.getSelf()+offset;
  422. memcpy(dest, value, size);
  423. dest[size] = '\0';
  424. offset += size+1;
  425. }
  426. else
  427. {
  428. builder.ensureCapacity(offset+length, str(field->name));
  429. byte *dest = builder.getSelf()+offset;
  430. rtlStrToVStr(length, dest, size, value);
  431. offset += length;
  432. }
  433. rtlFree(value);
  434. return offset;
  435. }
  436. size32_t RtlVarStringTypeInfo::process(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IFieldProcessor & target) const
  437. {
  438. const char * str = reinterpret_cast<const char *>(self);
  439. unsigned thisLength = (size32_t)strlen(str);
  440. unsigned thisSize;
  441. if (isFixedSize())
  442. thisSize = length+1;
  443. else
  444. thisSize = thisLength+1;
  445. if (isEbcdic())
  446. {
  447. unsigned lenAscii;
  448. rtlDataAttr ascii;
  449. rtlEStrToStrX(lenAscii, ascii.refstr(), thisLength, str);
  450. target.processString(lenAscii, ascii.getstr(), field);
  451. }
  452. else
  453. target.processString(thisLength, str, field);
  454. return thisSize;
  455. }
  456. size32_t RtlVarStringTypeInfo::toXML(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IXmlWriter & target) const
  457. {
  458. const char * str = reinterpret_cast<const char *>(self);
  459. unsigned thisLength = (size32_t)strlen(str);
  460. unsigned thisSize;
  461. if (isFixedSize())
  462. thisSize = length+1;
  463. else
  464. thisSize = thisLength+1;
  465. if (isEbcdic())
  466. {
  467. unsigned lenAscii;
  468. rtlDataAttr ascii;
  469. rtlEStrToStrX(lenAscii, ascii.refstr(), thisLength, str);
  470. target.outputString(lenAscii, ascii.getstr(), queryScalarXPath(field));
  471. }
  472. else
  473. target.outputString(thisLength, str, queryScalarXPath(field));
  474. return thisSize;
  475. }
  476. //-------------------------------------------------------------------------------------------------------------------
  477. size32_t RtlQStringTypeInfo::size(const byte * self, const byte * selfrow) const
  478. {
  479. if (isFixedSize())
  480. return rtlQStrSize(length);
  481. return sizeof(size32_t) + rtlQStrSize(rtlReadUInt4(self));
  482. }
  483. size32_t RtlQStringTypeInfo::build(ARowBuilder &builder, size32_t offset, const RtlFieldInfo *field, IFieldSource &source) const
  484. {
  485. size32_t size;
  486. char *value;
  487. source.getStringResult(field, size, value);
  488. if (!isFixedSize())
  489. {
  490. size32_t sizeInBytes = rtlQStrSize(size) + sizeof(size32_t);
  491. builder.ensureCapacity(offset+sizeInBytes, str(field->name));
  492. byte *dest = builder.getSelf()+offset;
  493. rtlWriteInt4(dest, size);
  494. rtlStrToQStr(size, (char *) dest+sizeof(size32_t), size, value);
  495. offset += sizeInBytes;
  496. }
  497. else
  498. {
  499. size32_t sizeInBytes = rtlQStrSize(length);
  500. builder.ensureCapacity(offset+sizeInBytes, str(field->name));
  501. byte *dest = builder.getSelf()+offset;
  502. rtlStrToQStr(length, (char *) dest, size, value);
  503. offset += sizeInBytes;
  504. }
  505. rtlFree(value);
  506. return offset;
  507. }
  508. size32_t RtlQStringTypeInfo::process(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IFieldProcessor & target) const
  509. {
  510. const char * str = reinterpret_cast<const char *>(self);
  511. unsigned thisLength;
  512. unsigned thisSize;
  513. if (isFixedSize())
  514. {
  515. thisLength = length;
  516. thisSize = rtlQStrSize(thisLength);
  517. }
  518. else
  519. {
  520. str = reinterpret_cast<const char *>(self + sizeof(size32_t));
  521. thisLength = rtlReadUInt4(self);
  522. thisSize = sizeof(size32_t) + rtlQStrSize(thisLength);
  523. }
  524. target.processQString(thisLength, str, field);
  525. return thisSize;
  526. }
  527. size32_t RtlQStringTypeInfo::toXML(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IXmlWriter & target) const
  528. {
  529. const char * str = reinterpret_cast<const char *>(self);
  530. unsigned thisLength;
  531. unsigned thisSize;
  532. if (isFixedSize())
  533. {
  534. thisLength = length;
  535. thisSize = rtlQStrSize(thisLength);
  536. }
  537. else
  538. {
  539. str = reinterpret_cast<const char *>(self + sizeof(size32_t));
  540. thisLength = rtlReadUInt4(self);
  541. thisSize = sizeof(size32_t) + rtlQStrSize(thisLength);
  542. }
  543. target.outputQString(thisLength, str, queryScalarXPath(field));
  544. return thisSize;
  545. }
  546. //-------------------------------------------------------------------------------------------------------------------
  547. size32_t RtlDecimalTypeInfo::calcSize() const
  548. {
  549. if (isUnsigned())
  550. return (getDecimalDigits()+1)/2;
  551. return (getDecimalDigits()+2)/2;
  552. }
  553. size32_t RtlDecimalTypeInfo::size(const byte * self, const byte * selfrow) const
  554. {
  555. return calcSize();
  556. }
  557. size32_t RtlDecimalTypeInfo::build(ARowBuilder &builder, size32_t offset, const RtlFieldInfo *field, IFieldSource &source) const
  558. {
  559. Decimal value;
  560. source.getDecimalResult(field, value);
  561. size32_t sizeInBytes = calcSize();
  562. builder.ensureCapacity(sizeInBytes+offset, str(field->name));
  563. if (isUnsigned())
  564. value.getUDecimal(sizeInBytes, getDecimalPrecision(), builder.getSelf()+offset);
  565. else
  566. value.getDecimal(sizeInBytes, getDecimalPrecision(), builder.getSelf()+offset);
  567. offset += sizeInBytes;
  568. return offset;
  569. }
  570. size32_t RtlDecimalTypeInfo::process(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IFieldProcessor & target) const
  571. {
  572. size32_t thisSize = calcSize();
  573. if (isUnsigned())
  574. target.processUDecimal(self, thisSize, getDecimalPrecision(), field);
  575. else
  576. target.processDecimal(self, thisSize, getDecimalPrecision(), field);
  577. return thisSize;
  578. }
  579. size32_t RtlDecimalTypeInfo::toXML(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IXmlWriter & target) const
  580. {
  581. size32_t thisSize = calcSize();
  582. if (isUnsigned())
  583. target.outputUDecimal(self, thisSize, getDecimalPrecision(), queryScalarXPath(field));
  584. else
  585. target.outputDecimal(self, thisSize, getDecimalPrecision(), queryScalarXPath(field));
  586. return thisSize;
  587. }
  588. //-------------------------------------------------------------------------------------------------------------------
  589. size32_t RtlCharTypeInfo::build(ARowBuilder &builder, size32_t offset, const RtlFieldInfo *field, IFieldSource &source) const
  590. {
  591. throwUnexpected(); // Can't have a field of type char
  592. }
  593. size32_t RtlCharTypeInfo::process(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IFieldProcessor & target) const
  594. {
  595. const char * str = reinterpret_cast<const char *>(self);
  596. char c;
  597. if (isEbcdic())
  598. rtlEStrToStr(1, &c, 1, str);
  599. else
  600. c = *str;
  601. target.processString(1, &c, field);
  602. return 1;
  603. }
  604. size32_t RtlCharTypeInfo::toXML(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IXmlWriter & target) const
  605. {
  606. const char * str = reinterpret_cast<const char *>(self);
  607. char c;
  608. if (isEbcdic())
  609. rtlEStrToStr(1, &c, 1, str);
  610. else
  611. c = *str;
  612. target.outputString(1, &c, queryScalarXPath(field));
  613. return 1;
  614. }
  615. //-------------------------------------------------------------------------------------------------------------------
  616. size32_t RtlUnicodeTypeInfo::size(const byte * self, const byte * selfrow) const
  617. {
  618. if (isFixedSize())
  619. return length * sizeof(UChar);
  620. return sizeof(size32_t) + rtlReadUInt4(self) * sizeof(UChar);
  621. }
  622. size32_t RtlUnicodeTypeInfo::build(ARowBuilder &builder, size32_t offset, const RtlFieldInfo *field, IFieldSource &source) const
  623. {
  624. size32_t sizeInChars;
  625. UChar *value;
  626. source.getUnicodeResult(field, sizeInChars, value);
  627. if (!isFixedSize())
  628. {
  629. size32_t sizeInBytes = sizeInChars * sizeof(UChar);
  630. builder.ensureCapacity(offset+sizeInBytes+sizeof(size32_t), str(field->name));
  631. byte *dest = builder.getSelf()+offset;
  632. rtlWriteInt4(dest, sizeInChars); // NOTE - in chars!
  633. memcpy(dest+sizeof(size32_t), value, sizeInBytes);
  634. offset += sizeInBytes+sizeof(size32_t);
  635. }
  636. else
  637. {
  638. size32_t sizeInBytes = length * sizeof(UChar);
  639. builder.ensureCapacity(offset+sizeInBytes, str(field->name));
  640. byte *dest = builder.getSelf()+offset;
  641. rtlUnicodeToUnicode(length, (UChar *) dest, sizeInChars, value);
  642. offset += sizeInBytes;
  643. }
  644. rtlFree(value);
  645. return offset;
  646. }
  647. size32_t RtlUnicodeTypeInfo::process(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IFieldProcessor & target) const
  648. {
  649. const UChar * ustr = reinterpret_cast<const UChar *>(self);
  650. unsigned thisLength;
  651. unsigned thisSize;
  652. if (isFixedSize())
  653. {
  654. thisLength = length;
  655. thisSize = thisLength * sizeof(UChar);
  656. }
  657. else
  658. {
  659. ustr = reinterpret_cast<const UChar *>(self + sizeof(size32_t));
  660. thisLength = rtlReadUInt4(self);
  661. thisSize = sizeof(size32_t) + thisLength * sizeof(UChar);
  662. }
  663. target.processUnicode(thisLength, ustr, field);
  664. return thisSize;
  665. }
  666. size32_t RtlUnicodeTypeInfo::toXML(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IXmlWriter & target) const
  667. {
  668. const UChar * ustr = reinterpret_cast<const UChar *>(self);
  669. unsigned thisLength;
  670. unsigned thisSize;
  671. if (isFixedSize())
  672. {
  673. thisLength = length;
  674. thisSize = thisLength * sizeof(UChar);
  675. }
  676. else
  677. {
  678. ustr = reinterpret_cast<const UChar *>(self + sizeof(size32_t));
  679. thisLength = rtlReadUInt4(self);
  680. thisSize = sizeof(size32_t) + thisLength * sizeof(UChar);
  681. }
  682. target.outputUnicode(thisLength, ustr, queryScalarXPath(field));
  683. return thisSize;
  684. }
  685. //-------------------------------------------------------------------------------------------------------------------
  686. size32_t RtlVarUnicodeTypeInfo::size(const byte * self, const byte * selfrow) const
  687. {
  688. if (isFixedSize())
  689. return (length+1) * sizeof(UChar);
  690. const UChar * ustr = reinterpret_cast<const UChar *>(self);
  691. return (rtlUnicodeStrlen(ustr)+1) * sizeof(UChar);
  692. }
  693. size32_t RtlVarUnicodeTypeInfo::build(ARowBuilder &builder, size32_t offset, const RtlFieldInfo *field, IFieldSource &source) const
  694. {
  695. size32_t sizeInChars;
  696. UChar *value;
  697. source.getUnicodeResult(field, sizeInChars, value);
  698. if (!isFixedSize())
  699. {
  700. size32_t sizeInBytes = (sizeInChars+1) * sizeof(UChar);
  701. builder.ensureCapacity(offset+sizeInBytes, str(field->name));
  702. UChar *dest = (UChar *) builder.getSelf()+offset;
  703. memcpy(dest, value, sizeInBytes - sizeof(UChar));
  704. dest[sizeInChars] = 0;
  705. offset += sizeInBytes;
  706. }
  707. else
  708. {
  709. size32_t sizeInBytes = length * sizeof(UChar);
  710. builder.ensureCapacity(offset+sizeInBytes, str(field->name));
  711. byte *dest = builder.getSelf()+offset;
  712. rtlUnicodeToVUnicode(length, (UChar *) dest, sizeInChars, value);
  713. offset += sizeInBytes;
  714. }
  715. rtlFree(value);
  716. return offset;
  717. }
  718. size32_t RtlVarUnicodeTypeInfo::process(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IFieldProcessor & target) const
  719. {
  720. const UChar * ustr = reinterpret_cast<const UChar *>(self);
  721. unsigned thisLength = rtlUnicodeStrlen(ustr);
  722. unsigned thisSize;
  723. if (isFixedSize())
  724. thisSize = (length + 1) * sizeof(UChar);
  725. else
  726. thisSize = (thisLength + 1) * sizeof(UChar);
  727. target.processUnicode(thisLength, ustr, field);
  728. return thisSize;
  729. }
  730. size32_t RtlVarUnicodeTypeInfo::toXML(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IXmlWriter & target) const
  731. {
  732. const UChar * ustr = reinterpret_cast<const UChar *>(self);
  733. unsigned thisLength = rtlUnicodeStrlen(ustr);
  734. unsigned thisSize;
  735. if (isFixedSize())
  736. thisSize = (length + 1) * sizeof(UChar);
  737. else
  738. thisSize = (thisLength + 1) * sizeof(UChar);
  739. target.outputUnicode(thisLength, ustr, queryScalarXPath(field));
  740. return thisSize;
  741. }
  742. //-------------------------------------------------------------------------------------------------------------------
  743. size32_t RtlUtf8TypeInfo::size(const byte * self, const byte * selfrow) const
  744. {
  745. assertex(!isFixedSize());
  746. return sizeof(size32_t) + rtlUtf8Size(rtlReadUInt4(self), self+sizeof(unsigned));
  747. }
  748. size32_t RtlUtf8TypeInfo::build(ARowBuilder &builder, size32_t offset, const RtlFieldInfo *field, IFieldSource &source) const
  749. {
  750. size32_t sizeInChars;
  751. char *value;
  752. source.getUTF8Result(field, sizeInChars, value);
  753. size32_t sizeInBytes = rtlUtf8Size(sizeInChars, value);
  754. assertex(!isFixedSize());
  755. builder.ensureCapacity(offset+sizeInBytes+sizeof(size32_t), str(field->name));
  756. byte *dest = builder.getSelf()+offset;
  757. rtlWriteInt4(dest, sizeInChars); // NOTE - in chars!
  758. memcpy(dest+sizeof(size32_t), value, sizeInBytes);
  759. offset += sizeInBytes+sizeof(size32_t);
  760. rtlFree(value);
  761. return offset;
  762. }
  763. size32_t RtlUtf8TypeInfo::process(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IFieldProcessor & target) const
  764. {
  765. assertex(!isFixedSize());
  766. const char * str = reinterpret_cast<const char *>(self + sizeof(size32_t));
  767. unsigned thisLength = rtlReadUInt4(self);
  768. unsigned thisSize = sizeof(size32_t) + rtlUtf8Size(thisLength, str);
  769. target.processUtf8(thisLength, str, field);
  770. return thisSize;
  771. }
  772. size32_t RtlUtf8TypeInfo::toXML(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IXmlWriter & target) const
  773. {
  774. assertex(!isFixedSize());
  775. const char * str = reinterpret_cast<const char *>(self + sizeof(size32_t));
  776. unsigned thisLength = rtlReadUInt4(self);
  777. unsigned thisSize = sizeof(size32_t) + rtlUtf8Size(thisLength, str);
  778. target.outputUtf8(thisLength, str, queryScalarXPath(field));
  779. return thisSize;
  780. }
  781. //-------------------------------------------------------------------------------------------------------------------
  782. inline size32_t sizeFields(const RtlFieldInfo * const * cur, const byte * self, const byte * selfrow)
  783. {
  784. unsigned offset = 0;
  785. for (;;)
  786. {
  787. const RtlFieldInfo * child = *cur;
  788. if (!child)
  789. break;
  790. offset += child->size(self+offset, selfrow);
  791. cur++;
  792. }
  793. return offset;
  794. }
  795. inline size32_t processFields(const RtlFieldInfo * const * cur, const byte * self, const byte * selfrow, IFieldProcessor & target)
  796. {
  797. unsigned offset = 0;
  798. for (;;)
  799. {
  800. const RtlFieldInfo * child = *cur;
  801. if (!child)
  802. break;
  803. child->process(self+offset, selfrow, target);
  804. offset += child->size(self+offset, selfrow);
  805. cur++;
  806. }
  807. return offset;
  808. }
  809. inline size32_t buildFields(const RtlFieldInfo * const * cur, ARowBuilder &builder, size32_t offset, IFieldSource &source)
  810. {
  811. for (;;)
  812. {
  813. const RtlFieldInfo * child = *cur;
  814. if (!child)
  815. break;
  816. offset = child->build(builder, offset, source);
  817. cur++;
  818. }
  819. return offset;
  820. }
  821. inline size32_t toXMLFields(const RtlFieldInfo * const * cur, const byte * self, const byte * selfrow, IXmlWriter & target)
  822. {
  823. size32_t offset = 0;
  824. for (;;)
  825. {
  826. const RtlFieldInfo * child = *cur;
  827. if (!child)
  828. break;
  829. size32_t size = child->toXML(self+offset, selfrow, target);
  830. offset += size;
  831. cur++;
  832. }
  833. return offset;
  834. }
  835. //-------------------------------------------------------------------------------------------------------------------
  836. size32_t RtlRecordTypeInfo::size(const byte * self, const byte * selfrow) const
  837. {
  838. return sizeFields(fields, self, self);
  839. }
  840. size32_t RtlRecordTypeInfo::process(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IFieldProcessor & target) const
  841. {
  842. if (target.processBeginRow(field))
  843. {
  844. unsigned offset = processFields(fields, self, self, target);
  845. target.processEndRow(field);
  846. return offset;
  847. }
  848. return size(self, selfrow);
  849. }
  850. size32_t RtlRecordTypeInfo::toXML(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IXmlWriter & target) const
  851. {
  852. const char * xpath = queryXPath(field);
  853. if (*xpath)
  854. target.outputBeginNested(xpath, false);
  855. unsigned thisSize = toXMLFields(fields, self, self, target);
  856. if (*xpath)
  857. target.outputEndNested(xpath);
  858. return thisSize;
  859. }
  860. size32_t RtlRecordTypeInfo::build(ARowBuilder &builder, size32_t offset, const RtlFieldInfo *field, IFieldSource &source) const
  861. {
  862. source.processBeginRow(field);
  863. offset = buildFields(fields, builder, offset, source);
  864. source.processEndRow(field);
  865. return offset;
  866. }
  867. //-------------------------------------------------------------------------------------------------------------------
  868. size32_t RtlSetTypeInfo::size(const byte * self, const byte * selfrow) const
  869. {
  870. return sizeof(bool) + sizeof(size32_t) + rtlReadUInt4(self + sizeof(bool));
  871. }
  872. size32_t RtlSetTypeInfo::build(ARowBuilder &builder, size32_t offset, const RtlFieldInfo *field, IFieldSource &source) const
  873. {
  874. bool isAll;
  875. source.processBeginSet(field, isAll);
  876. size32_t sizeInBytes = sizeof(bool) + sizeof(size32_t);
  877. builder.ensureCapacity(offset+sizeInBytes, str(field->name));
  878. byte *dest = builder.getSelf()+offset;
  879. if (isAll)
  880. {
  881. * (bool *) dest = true;
  882. rtlWriteInt4(dest+1, 0);
  883. offset += sizeInBytes;
  884. }
  885. else
  886. {
  887. * (bool *) dest = false;
  888. size32_t newOffset = offset + sizeInBytes;
  889. RtlFieldStrInfo dummyField("<set element>", NULL, child);
  890. while (source.processNextSet(field))
  891. {
  892. newOffset = child->build(builder, newOffset, &dummyField, source);
  893. }
  894. // Go back in and patch the size, remembering it may have moved
  895. rtlWriteInt4(builder.getSelf()+offset+1, newOffset - (offset+sizeInBytes));
  896. offset = newOffset;
  897. }
  898. source.processEndSet(field);
  899. return offset;
  900. }
  901. size32_t RtlSetTypeInfo::process(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IFieldProcessor & target) const
  902. {
  903. unsigned offset = sizeof(bool) + sizeof(size32_t);
  904. unsigned max = offset + rtlReadUInt4(self + sizeof(bool));
  905. unsigned elements = 0;
  906. if (!*(bool *)self)
  907. {
  908. unsigned tempOffset = sizeof(bool) + sizeof(size32_t);
  909. if (child->isFixedSize())
  910. {
  911. unsigned elemSize = child->size(NULL, NULL);
  912. elements = (max-offset) / elemSize;
  913. assert(elements*elemSize == max-offset);
  914. }
  915. else
  916. {
  917. DummyFieldProcessor dummy;
  918. while (tempOffset < max)
  919. {
  920. tempOffset += child->process(self+tempOffset, selfrow, field, dummy); // NOTE - good thing we can't have a set of sets, or this would recurse
  921. elements++;
  922. }
  923. }
  924. }
  925. if (target.processBeginSet(field, elements, *(bool *)self, self+offset))
  926. {
  927. while (offset < max)
  928. {
  929. offset += child->process(self+offset, selfrow, field, target);
  930. }
  931. }
  932. target.processEndSet(field);
  933. return max;
  934. }
  935. size32_t RtlSetTypeInfo::toXML(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IXmlWriter & target) const
  936. {
  937. unsigned offset = sizeof(bool) + sizeof(size32_t);
  938. unsigned max = offset + rtlReadUInt4(self + sizeof(bool));
  939. StringAttr outerTag;
  940. if (hasOuterXPath(field))
  941. {
  942. queryNestedOuterXPath(outerTag, field);
  943. target.outputBeginNested(outerTag, false);
  944. }
  945. if (*(bool *)self)
  946. target.outputSetAll();
  947. else
  948. {
  949. const char *innerPath = queryXPath(field);
  950. target.outputBeginArray(innerPath);
  951. while (offset < max)
  952. {
  953. child->toXML(self+offset, selfrow, field, target);
  954. offset += child->size(self+offset, selfrow);
  955. }
  956. target.outputEndArray(innerPath);
  957. }
  958. if (outerTag)
  959. target.outputEndNested(outerTag);
  960. return max;
  961. }
  962. //-------------------------------------------------------------------------------------------------------------------
  963. size32_t RtlRowTypeInfo::size(const byte * self, const byte * selfrow) const
  964. {
  965. if (isLinkCounted())
  966. return sizeof(void *);
  967. return child->size(self, selfrow);
  968. }
  969. size32_t RtlRowTypeInfo::process(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IFieldProcessor & target) const
  970. {
  971. if (isLinkCounted())
  972. {
  973. const byte * row = *(const byte * *)self;
  974. if (row)
  975. child->process(row, row, field, target);
  976. return sizeof(row);
  977. }
  978. return child->process(self, self, field, target);
  979. }
  980. size32_t RtlRowTypeInfo::toXML(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IXmlWriter & target) const
  981. {
  982. if (isLinkCounted())
  983. {
  984. const byte * row = *(const byte * *)self;
  985. child->toXML(row, row, field, target);
  986. return sizeof(row);
  987. }
  988. return child->toXML(self, self, field, target);
  989. }
  990. //-------------------------------------------------------------------------------------------------------------------
  991. size32_t RtlDatasetTypeInfo::size(const byte * self, const byte * selfrow) const
  992. {
  993. if (isLinkCounted())
  994. return sizeof(size32_t) + sizeof(void * *);
  995. return sizeof(size32_t) + rtlReadUInt4(self);
  996. }
  997. size32_t RtlDatasetTypeInfo::build(ARowBuilder &builder, size32_t offset, const RtlFieldInfo *field, IFieldSource &source) const
  998. {
  999. source.processBeginDataset(field);
  1000. if (isLinkCounted())
  1001. {
  1002. // a 32-bit record count, and a pointer to an array of record pointers
  1003. size32_t sizeInBytes = sizeof(size32_t) + sizeof(void *);
  1004. builder.ensureCapacity(offset+sizeInBytes, str(field->name));
  1005. size32_t numRows = 0;
  1006. Owned<IEngineRowAllocator> childAllocator = builder.queryAllocator()->createChildRowAllocator(child);
  1007. byte **childRows = NULL;
  1008. RtlFieldStrInfo dummyField("<nested row>", NULL, child);
  1009. while (source.processNextRow(field))
  1010. {
  1011. RtlDynamicRowBuilder childBuilder(*childAllocator);
  1012. size32_t childLen = child->build(childBuilder, 0, &dummyField, source);
  1013. childRows = childAllocator->appendRowOwn(childRows, ++numRows, (void *) childBuilder.finalizeRowClear(childLen));
  1014. }
  1015. // Go back in and patch the count, remembering it may have moved
  1016. rtlWriteInt4(builder.getSelf()+offset, numRows);
  1017. * ( const void * * ) (builder.getSelf()+offset+sizeof(size32_t)) = childRows;
  1018. offset += sizeInBytes;
  1019. }
  1020. else
  1021. {
  1022. // a 32-bit size, then rows inline
  1023. size32_t sizeInBytes = sizeof(size32_t);
  1024. builder.ensureCapacity(offset+sizeInBytes, str(field->name));
  1025. size32_t newOffset = offset + sizeInBytes;
  1026. RtlFieldStrInfo dummyField("<nested row>", NULL, child);
  1027. while (source.processNextRow(field))
  1028. newOffset = child->build(builder, newOffset, &dummyField, source);
  1029. // Go back in and patch the size, remembering it may have moved
  1030. rtlWriteInt4(builder.getSelf()+offset, newOffset - (offset+sizeInBytes));
  1031. offset = newOffset;
  1032. }
  1033. source.processEndDataset(field);
  1034. return offset;
  1035. }
  1036. size32_t RtlDatasetTypeInfo::process(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IFieldProcessor & target) const
  1037. {
  1038. if (isLinkCounted())
  1039. {
  1040. size32_t thisCount = rtlReadUInt4(self);
  1041. if (target.processBeginDataset(field, thisCount))
  1042. {
  1043. const byte * * rows = *reinterpret_cast<const byte * * const *>(self + sizeof(size32_t));
  1044. for (unsigned i= 0; i < thisCount; i++)
  1045. {
  1046. const byte * row = rows[i];
  1047. child->process(row, row, field, target);
  1048. }
  1049. target.processEndDataset(field);
  1050. }
  1051. return sizeof(size32_t) + sizeof(void * *);
  1052. }
  1053. else
  1054. {
  1055. unsigned offset = sizeof(size32_t);
  1056. unsigned max = offset + rtlReadUInt4(self);
  1057. unsigned thisCount = 0;
  1058. DummyFieldProcessor dummy;
  1059. while (offset < max)
  1060. {
  1061. offset += child->process(self+offset, self+offset, field, dummy);
  1062. thisCount++;
  1063. }
  1064. offset = sizeof(size32_t);
  1065. if (target.processBeginDataset(field, thisCount))
  1066. {
  1067. while (offset < max)
  1068. {
  1069. offset += child->process(self+offset, self+offset, field, target);
  1070. }
  1071. target.processEndDataset(field);
  1072. }
  1073. return max;
  1074. }
  1075. }
  1076. size32_t RtlDatasetTypeInfo::toXML(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IXmlWriter & target) const
  1077. {
  1078. StringAttr outerTag;
  1079. if (hasOuterXPath(field))
  1080. {
  1081. queryNestedOuterXPath(outerTag, field);
  1082. target.outputBeginNested(outerTag, false);
  1083. }
  1084. const char *innerPath = queryXPath(field);
  1085. target.outputBeginArray(innerPath);
  1086. unsigned thisSize;
  1087. if (isLinkCounted())
  1088. {
  1089. size32_t thisCount = rtlReadUInt4(self);
  1090. const byte * * rows = *reinterpret_cast<const byte * * const *>(self + sizeof(size32_t));
  1091. for (unsigned i= 0; i < thisCount; i++)
  1092. {
  1093. const byte * row = rows[i];
  1094. if (row)
  1095. child->toXML(row, row, field, target);
  1096. }
  1097. thisSize = sizeof(size32_t) + sizeof(void * *);
  1098. }
  1099. else
  1100. {
  1101. unsigned offset = sizeof(size32_t);
  1102. unsigned max = offset + rtlReadUInt4(self);
  1103. while (offset < max)
  1104. {
  1105. child->toXML(self+offset, self+offset, field, target);
  1106. offset += child->size(self+offset, self+offset);
  1107. }
  1108. thisSize = max;
  1109. }
  1110. target.outputEndArray(innerPath);
  1111. if (outerTag)
  1112. target.outputEndNested(outerTag);
  1113. return thisSize;
  1114. }
  1115. //-------------------------------------------------------------------------------------------------------------------
  1116. size32_t RtlDictionaryTypeInfo::size(const byte * self, const byte * selfrow) const
  1117. {
  1118. if (isLinkCounted())
  1119. return sizeof(size32_t) + sizeof(void * *);
  1120. return sizeof(size32_t) + rtlReadUInt4(self);
  1121. }
  1122. size32_t RtlDictionaryTypeInfo::build(ARowBuilder &builder, size32_t offset, const RtlFieldInfo *field, IFieldSource &source) const
  1123. {
  1124. source.processBeginDataset(field);
  1125. if (isLinkCounted())
  1126. {
  1127. // a 32-bit record count, and a pointer to an hash table with record pointers
  1128. size32_t sizeInBytes = sizeof(size32_t) + sizeof(void *);
  1129. builder.ensureCapacity(offset+sizeInBytes, str(field->name));
  1130. Owned<IEngineRowAllocator> childAllocator = builder.queryAllocator()->createChildRowAllocator(child);
  1131. RtlLinkedDictionaryBuilder dictBuilder(childAllocator, hashInfo);
  1132. RtlFieldStrInfo dummyField("<nested row>", NULL, child);
  1133. while (source.processNextRow(field))
  1134. {
  1135. RtlDynamicRowBuilder childBuilder(childAllocator);
  1136. size32_t childLen = child->build(childBuilder, 0, &dummyField, source);
  1137. dictBuilder.appendOwn((void *) childBuilder.finalizeRowClear(childLen));
  1138. }
  1139. // Go back in and patch the count
  1140. rtlWriteInt4(builder.getSelf()+offset, dictBuilder.getcount());
  1141. * ( const void * * ) (builder.getSelf()+offset+sizeof(size32_t)) = dictBuilder.linkrows();
  1142. offset += sizeInBytes;
  1143. }
  1144. else
  1145. UNIMPLEMENTED; // And may never be...
  1146. source.processEndDataset(field);
  1147. return offset;
  1148. }
  1149. size32_t RtlDictionaryTypeInfo::process(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IFieldProcessor & target) const
  1150. {
  1151. if (isLinkCounted())
  1152. {
  1153. size32_t thisCount = rtlReadUInt4(self);
  1154. if (target.processBeginDataset(field, thisCount))
  1155. {
  1156. const byte * * rows = *reinterpret_cast<const byte * * const *>(self + sizeof(size32_t));
  1157. for (unsigned i= 0; i < thisCount; i++)
  1158. {
  1159. const byte * row = rows[i];
  1160. if (row)
  1161. child->process(row, row, field, target);
  1162. }
  1163. target.processEndDataset(field);
  1164. }
  1165. return sizeof(size32_t) + sizeof(void * *);
  1166. }
  1167. else
  1168. {
  1169. //MORE: We could interpret serialized dictionaries if there was ever a need
  1170. UNIMPLEMENTED;
  1171. }
  1172. }
  1173. size32_t RtlDictionaryTypeInfo::toXML(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IXmlWriter & target) const
  1174. {
  1175. StringAttr outerTag;
  1176. if (hasOuterXPath(field))
  1177. {
  1178. queryNestedOuterXPath(outerTag, field);
  1179. target.outputBeginNested(outerTag, false);
  1180. }
  1181. const char *innerPath = queryXPath(field);
  1182. target.outputBeginArray(innerPath);
  1183. unsigned thisSize;
  1184. if (isLinkCounted())
  1185. {
  1186. size32_t thisCount = rtlReadUInt4(self);
  1187. const byte * * rows = *reinterpret_cast<const byte * * const *>(self + sizeof(size32_t));
  1188. for (unsigned i= 0; i < thisCount; i++)
  1189. {
  1190. const byte * row = rows[i];
  1191. if (row)
  1192. child->toXML(row, row, field, target);
  1193. }
  1194. thisSize = sizeof(size32_t) + sizeof(void * *);
  1195. }
  1196. else
  1197. {
  1198. //MORE: We could interpret serialized dictionaries if there was ever a need
  1199. UNIMPLEMENTED;
  1200. }
  1201. target.outputEndArray(innerPath);
  1202. if (outerTag)
  1203. target.outputEndNested(outerTag);
  1204. return thisSize;
  1205. }
  1206. //-------------------------------------------------------------------------------------------------------------------
  1207. size32_t RtlIfBlockTypeInfo::size(const byte * self, const byte * selfrow) const
  1208. {
  1209. if (getCondition(selfrow))
  1210. return sizeFields(fields, self, selfrow);
  1211. return 0;
  1212. }
  1213. size32_t RtlIfBlockTypeInfo::process(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IFieldProcessor & target) const
  1214. {
  1215. if (getCondition(selfrow))
  1216. return processFields(fields, self, selfrow, target);
  1217. return 0;
  1218. }
  1219. size32_t RtlIfBlockTypeInfo::toXML(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IXmlWriter & target) const
  1220. {
  1221. if (getCondition(selfrow))
  1222. return toXMLFields(fields, self, selfrow, target);
  1223. return 0;
  1224. }
  1225. //-------------------------------------------------------------------------------------------------------------------
  1226. __int64 RtlBitfieldTypeInfo::signedValue(const byte * self) const
  1227. {
  1228. __int64 value = rtlReadInt(self, getBitfieldIntSize());
  1229. unsigned shift = getBitfieldShift();
  1230. unsigned numBits = getBitfieldNumBits();
  1231. unsigned bitsInValue = sizeof(value) * 8;
  1232. value <<= (bitsInValue - shift - numBits);
  1233. return value >> (bitsInValue - numBits);
  1234. }
  1235. unsigned __int64 RtlBitfieldTypeInfo::unsignedValue(const byte * self) const
  1236. {
  1237. unsigned __int64 value = rtlReadUInt(self, getBitfieldIntSize());
  1238. unsigned shift = getBitfieldShift();
  1239. unsigned numBits = getBitfieldNumBits();
  1240. unsigned bitsInValue = sizeof(value) * 8;
  1241. value <<= (bitsInValue - shift - numBits);
  1242. return value >> (bitsInValue - numBits);
  1243. }
  1244. size32_t RtlBitfieldTypeInfo::size(const byte * self, const byte * selfrow) const
  1245. {
  1246. if (fieldType & RFTMislastbitfield)
  1247. return getBitfieldIntSize();
  1248. return 0;
  1249. }
  1250. size32_t RtlBitfieldTypeInfo::process(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IFieldProcessor & target) const
  1251. {
  1252. if (isUnsigned())
  1253. target.processUInt(unsignedValue(self), field);
  1254. else
  1255. target.processInt(signedValue(self), field);
  1256. return size(self, selfrow);
  1257. }
  1258. size32_t RtlBitfieldTypeInfo::toXML(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IXmlWriter & target) const
  1259. {
  1260. size32_t fieldsize = getBitfieldIntSize();
  1261. if (isUnsigned())
  1262. target.outputUInt(unsignedValue(self), fieldsize, queryScalarXPath(field));
  1263. else
  1264. target.outputInt(signedValue(self), fieldsize, queryScalarXPath(field));
  1265. if (fieldType & RFTMislastbitfield)
  1266. return fieldsize;
  1267. return 0;
  1268. }
  1269. //-------------------------------------------------------------------------------------------------------------------
  1270. size32_t RtlUnimplementedTypeInfo::size(const byte * self, const byte * selfrow) const
  1271. {
  1272. rtlFailUnexpected();
  1273. return 0;
  1274. }
  1275. size32_t RtlUnimplementedTypeInfo::process(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IFieldProcessor & target) const
  1276. {
  1277. rtlFailUnexpected();
  1278. return 0;
  1279. }
  1280. size32_t RtlUnimplementedTypeInfo::toXML(const byte * self, const byte * selfrow, const RtlFieldInfo * field, IXmlWriter & target) const
  1281. {
  1282. rtlFailUnexpected();
  1283. return 0;
  1284. }
  1285. //-------------------------------------------------------------------------------------------------------------------
  1286. RtlFieldStrInfo::RtlFieldStrInfo(const char * _name, const char * _xpath, const RtlTypeInfo * _type, const char *_initializer)
  1287. : RtlFieldInfo(rtlCreateFieldNameAtom(_name), _xpath, _type, _initializer)
  1288. {
  1289. }
  1290. RtlFieldStrInfo::RtlFieldStrInfo(const char * _name, const char * _xpath, const RtlTypeInfo * _type)
  1291. : RtlFieldInfo(rtlCreateFieldNameAtom(_name), _xpath, _type, NULL)
  1292. {
  1293. }
  1294. /*
  1295. Stack:
  1296. * Change hqlhtcpp so that the correct derived classes are generated.
  1297. * Test so that toXML calls the default implementaions and check that the same values are generated. (Don't if contains ifblocks/alien)
  1298. * Release
  1299. * Think about bitfields - how do I know it is the last bitfield, how am I going to keep track of the offsets.
  1300. * What code would need to be generated for alien datatypes.
  1301. * Could have alien int and alien string varieties????
  1302. * What would an ecl interpreter look like (a special workunit?) helpers are interpreted? What about the graph?
  1303. * Could I add associations to register user attributes - so a callback could know when they were assigned to?
  1304. * Could I add ctx->noteLocation() into the generated code - so could put breakpoints on variables.
  1305. * Add annotation when a member of the target dataset is updated.
  1306. ctx->noteFieldAssigned(self, <field>); - does this include temporary datasets?
  1307. ctx->noteAttributeX(<name>, Int|String|Unicode|
  1308. 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??
  1309. * Need static information about the breakpoints so debugger knows where to put valid brakpoints....
  1310. * Debugger will want to know about the type of the breakpoints.
  1311. * Should try and compress the location format - possibly have a table of <module.attributes>-># with breakpoint as 12:23
  1312. Also need some information about which datasets, and stored variables etc. are used so they can be displayed.
  1313. - Most datasets can be deduced from the parameters passed into the transform
  1314. - Some are trickier e.g., the extract, could possibly define some mappings
  1315. - options to disable projects/other more complex operations inline (so easier to walk through)
  1316. Bitfields:
  1317. - Two separate questions:
  1318. i) How is the meta information generated.
  1319. ii) How is it stored internally in an IHqlExpression * ?
  1320. * Could store the offset in the type - either in the base type of as a qualifier.
  1321. + much easier code generation.
  1322. - Doesn't provie an easy indication of the last field in a bitfield (because can't really modify after the fact)
  1323. - Problematic when fields are removed to merge them.
  1324. * Could add a bitfield container to the record.
  1325. + Makes it easier to handle the last bitfield
  1326. + Matches the structure used for the cursor.
  1327. - Everything needs to walk the bitfield containers similar to ifblocks.
  1328. - Makes it just as tricky to merge
  1329. - Harder to create the record, unless the code is implicitly handled by appendOperand().
  1330. * The type of no_select could contain a modifier to indicate the offset/islast
  1331. + the type of a no_select would have a 1:1 mapping with type info.
  1332. - A bit complicated to calculate, especially when it isn't used much of the time
  1333. => On Reflection is is probably easiest to keep the structure as it is (some comments should go in hqlexpr to avoid revisiting).
  1334. * interperet bitfield offsets and "is last bitfield" dynamically
  1335. + Greatly simplifies generating the meta - you can always use the field.
  1336. - Requires another parameter and significant extra complexity for the uncommon case. (especially incrementing self)
  1337. * Could generate from the expanded record instead of walking the record structure directly
  1338. + That already knows how the bitfields are allocated, and could easily know which is the last field.
  1339. - A field is no longer sufficient as key fr searching for the information.
  1340. - Best would be a createFieldTypeKey(select-expr) which returns field when approriate, or modified if a bitfield. Then the pain is localised.
  1341. * Output a bitfield container item into the type information
  1342. + Solves the size problem
  1343. - Individual bitfields still need to know their offsets, so doesn't solve the full problem.
  1344. =>
  1345. Change so that either use meta to generate the information, or use no_select when appropriate to fidn out the nesc. information.
  1346. Probably the latter for the moment.
  1347. a) Create a key function and make sure it is always used.
  1348. b) Need to work out how to generate no_ifblock.
  1349. - ifblock is context dependent, so need to generate as part of the parent record, and in the parent record context.
  1350. */