rtlkey.cpp 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527
  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 "jlib.hpp"
  14. #include "jsort.hpp"
  15. #include "jexcept.hpp"
  16. #include "rtlkey.hpp"
  17. #include "rtlkey2.hpp"
  18. #include "eclrtl_imp.hpp"
  19. #include "rtlrecord.hpp"
  20. #include "rtlnewkey.hpp"
  21. class CKeySegmentMonitor : implements IKeySegmentMonitor, public CInterface
  22. {
  23. protected:
  24. size32_t size;
  25. size32_t offset;
  26. unsigned fieldIdx;
  27. public:
  28. IMPLEMENT_IINTERFACE;
  29. CKeySegmentMonitor(unsigned _fieldIdx, unsigned _offset, unsigned _size);
  30. virtual bool matchesBuffer(const void * rawRow) const override = 0;
  31. virtual bool matches(const RtlRow * rawRow) const override
  32. {
  33. return matchesBuffer(rawRow->queryRow());
  34. }
  35. virtual bool increment(void *keyval) const override;
  36. virtual unsigned queryFieldIndex() const override { return fieldIdx; }
  37. virtual unsigned getOffset() const override { return offset; }
  38. virtual unsigned getSize() const override { return size; }
  39. virtual bool isWild() const override { return false; }
  40. virtual bool isEmpty() const override { return false; }
  41. virtual bool isSigned() const override { return false; }
  42. virtual bool isLittleEndian() const override { return false; }
  43. virtual unsigned numFieldsRequired() const override { return 0; } // Should rename to queryFieldIdx or similar
  44. virtual int docompare(const void * l, const void * r) const override
  45. {
  46. char *lptr = ((char *) l) + offset;
  47. char *rptr = ((char *) r) + offset;
  48. return memcmp(lptr, rptr, size);
  49. }
  50. virtual bool getBloomHash(hash64_t &hash) const override
  51. {
  52. return false;
  53. }
  54. virtual void setHigh(void *keyval) const override;
  55. virtual void copy(void * l, const void * r) const override
  56. {
  57. char *lptr = ((char *) l) + offset;
  58. char *rptr = ((char *) r) + offset;
  59. memcpy(lptr, rptr, size);
  60. }
  61. };
  62. class CWildKeySegmentMonitor : public CKeySegmentMonitor
  63. {
  64. public:
  65. CWildKeySegmentMonitor(unsigned _fieldIdx, unsigned _offset, unsigned _size);
  66. virtual bool matchesBuffer(const void *keyval) const override;
  67. virtual int docompare(const void *,const void *) const override;
  68. virtual void setLow(void *keyval) const override;
  69. virtual void endRange(void *keyval) const override;
  70. virtual bool isWild() const override { return true; }
  71. virtual bool isSimple() const override { return true; }
  72. virtual bool isWellKeyed() const override { return false; }
  73. virtual bool isOptional() const override { return true; }
  74. virtual StringBuffer &describe(StringBuffer &out, const RtlTypeInfo &type) const override { return out.append('*'); }
  75. };
  76. class CSetKeySegmentMonitor : public CKeySegmentMonitor
  77. {
  78. private:
  79. Owned<IStringSet> set;
  80. bool optional;
  81. public:
  82. CSetKeySegmentMonitor(bool _optional, IStringSet *set, unsigned _fieldIdx, unsigned _offset, unsigned _size);
  83. // IKeySegmentMonitor
  84. virtual bool increment(void *keyval) const override;
  85. virtual void setLow(void *keyval) const override;
  86. virtual bool matchesBuffer(const void *keyval) const override;
  87. virtual void endRange(void *keyval) const override;
  88. virtual bool isEmpty() const override { return set->isEmptySet(); }
  89. virtual bool isWellKeyed() const override;
  90. virtual bool isOptional() const override { return optional; }
  91. virtual bool isSimple() const override { return true; }
  92. virtual bool isSigned() const override { return set->isSigned(); }
  93. virtual bool isLittleEndian() const override { return !set->isBigEndian(); }
  94. virtual int docompare(const void * l, const void * r) const override
  95. {
  96. char *lptr = ((char *) l) + offset;
  97. char *rptr = ((char *) r) + offset;
  98. return set->memcmp(lptr, rptr, size);
  99. }
  100. virtual StringBuffer &describe(StringBuffer &out, const RtlTypeInfo &type) const override { return out.append("[...]"); } // MORE - could do better
  101. };
  102. CKeySegmentMonitor::CKeySegmentMonitor(unsigned _fieldIdx, unsigned _offset, unsigned _size)
  103. {
  104. size = _size;
  105. offset = _offset;
  106. fieldIdx = _fieldIdx;
  107. }
  108. bool CKeySegmentMonitor::increment(void *bufptr) const
  109. {
  110. char *ptr = ((char *) bufptr) + offset;
  111. int i = size;
  112. while (i--)
  113. {
  114. ptr[i]++;
  115. if (ptr[i]!=0)
  116. return true;
  117. }
  118. return false;
  119. }
  120. void CKeySegmentMonitor::setHigh(void *bufptr) const
  121. {
  122. // NOTE - effectively whenever this is called we are treating the segmonitor as if it was a wild one
  123. char *ptr = ((char *) bufptr) + offset;
  124. memset(ptr, 0xff, size);
  125. }
  126. CWildKeySegmentMonitor::CWildKeySegmentMonitor(unsigned _fieldIdx, unsigned _offset, unsigned _size)
  127. : CKeySegmentMonitor(_fieldIdx, _offset, _size)
  128. {
  129. }
  130. bool CWildKeySegmentMonitor::matchesBuffer(const void *keyval) const
  131. {
  132. return true;
  133. }
  134. int CWildKeySegmentMonitor::docompare(const void *l, const void *r) const
  135. {
  136. return 0;
  137. }
  138. void CWildKeySegmentMonitor::setLow(void *bufptr) const
  139. {
  140. char *ptr = ((char *) bufptr) + offset;
  141. memset(ptr, 0, size);
  142. }
  143. void CWildKeySegmentMonitor::endRange(void *bufptr) const
  144. {
  145. char *ptr = ((char *) bufptr) + offset;
  146. memset(ptr, 0xff, size);
  147. }
  148. CSetKeySegmentMonitor::CSetKeySegmentMonitor(bool _optional, IStringSet *_set, unsigned _fieldIdx, unsigned _offset, unsigned _size)
  149. : CKeySegmentMonitor(_fieldIdx, _offset, _size), set(_set)
  150. {
  151. optional = _optional;
  152. }
  153. bool CSetKeySegmentMonitor::increment(void *bufptr) const
  154. {
  155. char *ptr = ((char *) bufptr) + offset;
  156. bool ok = set->increment(ptr);
  157. if (ok)
  158. {
  159. unsigned nextTransition;
  160. bool res = set->inRange(ptr, nextTransition);
  161. if (!res)
  162. {
  163. if ((unsigned) -1 == nextTransition) return false;
  164. set->getTransitionValue(ptr, nextTransition);
  165. }
  166. }
  167. return ok;
  168. }
  169. void CSetKeySegmentMonitor::setLow(void *bufptr) const
  170. {
  171. char *ptr = ((char *) bufptr) + offset;
  172. if (set->transitionCount())
  173. set->getTransitionValue(ptr, 0);
  174. else
  175. memset(ptr, 0, size); // MORE - should really trap earlier
  176. }
  177. void CSetKeySegmentMonitor::endRange(void *bufptr) const
  178. {
  179. char *ptr = ((char *) bufptr) + offset;
  180. unsigned nextTransition;
  181. bool res = set->inRange(ptr, nextTransition);
  182. assertex(res);
  183. verifyex(set->getTransitionValue(ptr, nextTransition));
  184. }
  185. bool CSetKeySegmentMonitor::matchesBuffer(const void *bufptr) const
  186. {
  187. char *ptr = ((char *) bufptr) + offset;
  188. return set->inRange(ptr);
  189. }
  190. bool CSetKeySegmentMonitor::isWellKeyed() const
  191. {
  192. // This check determines whether or not keyed, opt considers this field to be keyed.
  193. // The goal is to allow sets but not ranges, slightly complicated by the fact that adjacent values in a set turn into ranges.
  194. return set->numValues() < 50;
  195. }
  196. class CSingleKeySegmentMonitorBase : public CKeySegmentMonitor
  197. {
  198. protected:
  199. void *val;
  200. bool optional;
  201. public:
  202. CSingleKeySegmentMonitorBase(bool _optional, const void *_val, unsigned _fieldIdx, unsigned _offset, unsigned _size)
  203. : CKeySegmentMonitor(_fieldIdx, _offset, _size)
  204. {
  205. if (_val)
  206. {
  207. val = malloc(_size);
  208. memcpy(val, _val, _size);
  209. }
  210. else
  211. val = NULL;
  212. optional = _optional;
  213. }
  214. CSingleKeySegmentMonitorBase(bool _optional, unsigned _fieldIdx, unsigned _offset, unsigned _size)
  215. : CKeySegmentMonitor(_fieldIdx, _offset, _size)
  216. {
  217. val = NULL;
  218. optional = _optional;
  219. }
  220. ~CSingleKeySegmentMonitorBase()
  221. {
  222. free(val);
  223. }
  224. // IKeySegmentMonitor
  225. virtual bool increment(void *bufptr) const override
  226. {
  227. // Set to next permitted value above current
  228. if (docompare(bufptr, ((char *) val)-offset) < 0) // NOTE - we subtract offset from val before passing because the compare will add it on again. Confusing or what...
  229. {
  230. char *ptr = ((char *) bufptr) + offset;
  231. memcpy(ptr, val, size);
  232. return true;
  233. }
  234. else
  235. return false;
  236. }
  237. virtual void setLow(void *bufptr) const override
  238. {
  239. // Set to lowest permitted value
  240. char *ptr = ((char *) bufptr) + offset;
  241. memcpy(ptr, val, size);
  242. }
  243. virtual bool matchesBuffer(const void *bufptr) const override
  244. {
  245. // Is current a permitted value?
  246. char *ptr = ((char *) bufptr) + offset;
  247. return memcmp(ptr, val, size) == 0;
  248. }
  249. virtual void endRange(void *bufptr) const override
  250. {
  251. // Set to last permitted value in the range that includes current (which is asserted to be valid)
  252. dbgassertex(matchesBuffer(bufptr));
  253. }
  254. virtual bool isWellKeyed() const override { return true; }
  255. virtual bool isOptional() const override { return optional; }
  256. virtual bool isSimple() const override { return true; }
  257. virtual StringBuffer &describe(StringBuffer &out, const RtlTypeInfo &type) const override
  258. {
  259. size32_t size;
  260. rtlDataAttr text;
  261. type.getString(size, text.refstr(), val);
  262. if (type.isNumeric())
  263. return out.append(size, text.getstr());
  264. else
  265. return out.appendf("'%*s'", size, text.getstr());
  266. }
  267. };
  268. class CSingleKeySegmentMonitor : public CSingleKeySegmentMonitorBase
  269. {
  270. public:
  271. CSingleKeySegmentMonitor(bool _optional, const void *_val, unsigned _fieldIdx, unsigned _offset, unsigned _size)
  272. : CSingleKeySegmentMonitorBase(_optional, _val, _fieldIdx, _offset, _size)
  273. {
  274. }
  275. virtual bool isSigned() const override { return false; }
  276. virtual bool isLittleEndian() const override { return false; }
  277. virtual bool getBloomHash(hash64_t &hash) const override
  278. {
  279. if (!val)
  280. return false;
  281. hash = rtlHash64Data(size, val, hash);
  282. return true;
  283. }
  284. };
  285. class CSingleBigSignedKeySegmentMonitor : public CSingleKeySegmentMonitorBase
  286. {
  287. public:
  288. CSingleBigSignedKeySegmentMonitor(bool _optional, const void *_val, unsigned _fieldIdx, unsigned _offset, unsigned _size)
  289. : CSingleKeySegmentMonitorBase(_optional, _val, _fieldIdx, _offset, _size)
  290. {
  291. }
  292. virtual int docompare(const void *l, const void *r) const override
  293. {
  294. return memcmpbigsigned(((char *) l) + offset, ((char *) r) + offset, size);
  295. }
  296. virtual bool isSigned() const override { return true; }
  297. virtual bool isLittleEndian() const override { return false; }
  298. };
  299. class CSingleLittleSignedKeySegmentMonitor : public CSingleKeySegmentMonitorBase
  300. {
  301. public:
  302. CSingleLittleSignedKeySegmentMonitor(bool _optional, const void *_val, unsigned _fieldIdx, unsigned _offset, unsigned _size)
  303. : CSingleKeySegmentMonitorBase(_optional, _val, _fieldIdx, _offset, _size)
  304. {
  305. }
  306. virtual int docompare(const void *l, const void *r) const
  307. {
  308. return memcmplittlesigned(((char *) l) + offset, ((char *) r) + offset, size);
  309. }
  310. virtual bool isSigned() const override { return true; }
  311. virtual bool isLittleEndian() const override { return true; }
  312. };
  313. class CSingleLittleKeySegmentMonitor : public CSingleKeySegmentMonitorBase
  314. {
  315. public:
  316. CSingleLittleKeySegmentMonitor(bool _optional, const void *_val, unsigned _fieldIdx, unsigned _offset, unsigned _size)
  317. : CSingleKeySegmentMonitorBase(_optional, _val, _fieldIdx, _offset, _size)
  318. {
  319. }
  320. virtual int docompare(const void *l, const void *r) const override
  321. {
  322. return memcmplittleunsigned(((char *) l) + offset, ((char *) r) + offset, size);
  323. }
  324. virtual bool isSigned() const override { return false; }
  325. virtual bool isLittleEndian() const override { return true; }
  326. };
  327. ECLRTL_API IStringSet *createRtlStringSet(size32_t size)
  328. {
  329. return createStringSet(size);
  330. }
  331. ECLRTL_API IStringSet *createRtlStringSetEx(size32_t size, bool bigEndian, bool isSigned)
  332. {
  333. return createStringSet(size, bigEndian, isSigned);
  334. }
  335. ECLRTL_API IStringSet * rtlUnionSet(IStringSet * lhs, IStringSet * rhs)
  336. {
  337. if (lhs->isEmptySet())
  338. return LINK(rhs);
  339. else if (lhs->isFullSet())
  340. return LINK(lhs);
  341. if (rhs->isEmptySet())
  342. return LINK(lhs);
  343. else if (rhs->isFullSet())
  344. return LINK(rhs);
  345. return lhs->unionSet(rhs);
  346. }
  347. ECLRTL_API IStringSet * rtlIntersectSet(IStringSet * lhs, IStringSet * rhs)
  348. {
  349. if (lhs->isFullSet())
  350. return LINK(rhs);
  351. else if (lhs->isEmptySet())
  352. return LINK(lhs);
  353. if (rhs->isFullSet())
  354. return LINK(lhs);
  355. else if (rhs->isEmptySet())
  356. return LINK(rhs);
  357. return lhs->intersectSet(rhs);
  358. }
  359. IKeySegmentMonitor *createKeySegmentMonitor(bool optional, IStringSet *set, unsigned _fieldIdx, unsigned _offset, unsigned _size)
  360. {
  361. if (!set)
  362. return new CWildKeySegmentMonitor(_fieldIdx, _offset, _size);
  363. Owned<IStringSet> removeSet = set; // make sure set is released if optimized out.
  364. if (set->isSingleValue())
  365. {
  366. void *data = alloca(_size);
  367. set->getTransitionValue(data, 0);
  368. if (set->isSigned())
  369. {
  370. if (set->isBigEndian())
  371. return createSingleBigSignedKeySegmentMonitor(optional, _fieldIdx, _offset, _size, data);
  372. else
  373. return createSingleLittleSignedKeySegmentMonitor(optional, _fieldIdx, _offset, _size, data);
  374. }
  375. else
  376. {
  377. if (set->isBigEndian())
  378. return createSingleKeySegmentMonitor(optional, _fieldIdx, _offset, _size, data);
  379. else
  380. return createSingleLittleKeySegmentMonitor(optional, _fieldIdx, _offset, _size, data);
  381. }
  382. }
  383. else if (set->isFullSet())
  384. return new CWildKeySegmentMonitor(_fieldIdx, _offset, _size);
  385. else
  386. return new CSetKeySegmentMonitor(optional, removeSet.getClear(), _fieldIdx, _offset, _size);
  387. }
  388. ECLRTL_API IStringSet *createRtlStringValue(size32_t size, const char * value)
  389. {
  390. IStringSet * set = createStringSet(size);
  391. set->addRange(value, value);
  392. return set;
  393. }
  394. IKeySegmentMonitor *createWildKeySegmentMonitor(unsigned _fieldIdx, unsigned _offset, unsigned _size)
  395. {
  396. return new CWildKeySegmentMonitor(_fieldIdx, _offset, _size);
  397. }
  398. IKeySegmentMonitor *createEmptyKeySegmentMonitor(bool optional, unsigned _fieldIdx, unsigned _offset, unsigned _size)
  399. {
  400. return new CSetKeySegmentMonitor(optional, createStringSet(_size), _fieldIdx, _offset, _size);
  401. }
  402. ECLRTL_API IKeySegmentMonitor *createSingleKeySegmentMonitor(bool optional, unsigned _fieldIdx, unsigned offset, unsigned size, const void * value)
  403. {
  404. return new CSingleKeySegmentMonitor(optional, value, _fieldIdx, offset, size);
  405. }
  406. ECLRTL_API IKeySegmentMonitor *createSingleBigSignedKeySegmentMonitor(bool optional, unsigned fieldIdx, unsigned offset, unsigned size, const void * value)
  407. {
  408. return new CSingleBigSignedKeySegmentMonitor(optional, value, fieldIdx, offset, size);
  409. }
  410. ECLRTL_API IKeySegmentMonitor *createSingleLittleSignedKeySegmentMonitor(bool optional, unsigned fieldIdx, unsigned offset, unsigned size, const void * value)
  411. {
  412. // MORE - common int sizes 1,2,4 (8?) might be better done with dedicated subclasses
  413. return new CSingleLittleSignedKeySegmentMonitor(optional, value, fieldIdx, offset, size);
  414. }
  415. ECLRTL_API IKeySegmentMonitor *createSingleLittleKeySegmentMonitor(bool optional, unsigned fieldIdx, unsigned offset, unsigned size, const void * value)
  416. {
  417. // MORE - common int sizes 1,2,4 (8?) might be better done with dedicated subclasses
  418. return new CSingleLittleKeySegmentMonitor(optional, value, fieldIdx, offset, size);
  419. }
  420. ECLRTL_API IKeySegmentMonitor *createDummyKeySegmentMonitor(unsigned _fieldIdx, unsigned _offset, unsigned _size, bool isSigned, bool isLittleEndian)
  421. {
  422. if (isSigned)
  423. if (isLittleEndian)
  424. return new CSingleLittleSignedKeySegmentMonitor(false, NULL, _fieldIdx, _offset, _size);
  425. else
  426. return new CSingleBigSignedKeySegmentMonitor(false, NULL, _fieldIdx, _offset, _size);
  427. else
  428. if (isLittleEndian)
  429. return new CSingleLittleKeySegmentMonitor(false, NULL, _fieldIdx, _offset, _size);
  430. else
  431. return new CSingleKeySegmentMonitor(false, NULL, _fieldIdx, _offset, _size);
  432. }
  433. ECLRTL_API int memcmpbigsigned(const void *l, const void *r, unsigned size)
  434. {
  435. signed int diff = ((signed char *) l)[0]-((signed char *) r)[0];
  436. if (diff)
  437. return diff;
  438. for(unsigned i = 1; i < size; i++)
  439. {
  440. diff = ((unsigned char *) l)[i]-((unsigned char *) r)[i];
  441. if (diff)
  442. return diff;
  443. }
  444. return 0;
  445. }
  446. ECLRTL_API int memcmplittleunsigned(const void *l, const void *r, unsigned size)
  447. {
  448. while (size)
  449. {
  450. size--;
  451. int diff = ((unsigned char *) l)[size]-((unsigned char *) r)[size];
  452. if (diff)
  453. return diff;
  454. }
  455. return 0;
  456. }
  457. ECLRTL_API int memcmplittlesigned(const void *l, const void *r, unsigned size)
  458. {
  459. size--;
  460. signed int diff = ((signed char *) l)[size]-((signed char *) r)[size];
  461. if (diff)
  462. return diff;
  463. while (size)
  464. {
  465. size--;
  466. diff = ((unsigned char *) l)[size]-((unsigned char *) r)[size];
  467. if (diff)
  468. return diff;
  469. }
  470. return 0;
  471. }
  472. class CStringSet : implements IStringSet, public CInterface
  473. {
  474. protected:
  475. size32_t size;
  476. IArrayOf<ITransition> transitions;
  477. IStringSet *unionOrIntersect(IStringSet *r, bool isUnion);
  478. virtual CStringSet *createEmptySet() = 0;
  479. virtual bool decrement(void *val) const = 0;
  480. virtual bool increment(void *val) const = 0;
  481. virtual int memcmp(const void *val1, const void *val2, size32_t size) const = 0;
  482. virtual unsigned getCardinality(const void *val1, const void *val2, size32_t size) const = 0;
  483. virtual void memset(void *ptr, int val, size32_t size) const = 0;
  484. virtual bool isLowVal(const void *val) const = 0;
  485. virtual bool isHighVal(const void *val) const = 0;
  486. bool oneless(const void *l, const void *r) const;
  487. void addTransitionAt(const void *val, bool state, unsigned pos);
  488. void appendTransition(ITransition *t);
  489. public:
  490. IMPLEMENT_IINTERFACE;
  491. CStringSet(size32_t size);
  492. // IStringSet
  493. virtual void addRange(const void *loval, const void *hival);
  494. virtual void addAll();
  495. virtual ITransition *queryTransition(unsigned idx);
  496. virtual bool getTransitionValue(void *value, unsigned idx);
  497. virtual void killRange(const void *loval, const void *hival);
  498. virtual bool inRange(const void *val) const;
  499. virtual bool inRange(const void *val, unsigned &transition) const;
  500. virtual size32_t getSize() { return size; };
  501. virtual void reset();
  502. virtual unsigned transitionCount();
  503. virtual IStringSet *invertSet();
  504. virtual IStringSet *unionSet(IStringSet *);
  505. virtual IStringSet *intersectSet(IStringSet *);
  506. virtual const char *describe(StringBuffer &ret);
  507. virtual bool isEmptySet() const { return transitions.length()==0; }
  508. virtual bool isFullSet() const
  509. {
  510. return transitions.length()==2 &&
  511. isLowVal(transitions.item(0).getValue()) &&
  512. isHighVal(transitions.item(1).getValue());
  513. }
  514. virtual bool isSingleValue() const
  515. {
  516. return transitions.length()==2 &&
  517. memcmp(transitions.item(0).getValue(), transitions.item(1).getValue(), size) == 0;
  518. }
  519. virtual unsigned numValues() const
  520. {
  521. unsigned ret = 0;
  522. unsigned idx = 0;
  523. while (transitions.isItem(idx+1))
  524. {
  525. unsigned thisrange = getCardinality(transitions.item(idx).getValue(), transitions.item(idx+1).getValue(), size);
  526. if (thisrange + ret < ret)
  527. return (unsigned) -1;
  528. ret += thisrange;
  529. idx += 2;
  530. }
  531. return ret;
  532. }
  533. };
  534. class CBigUnsignedStringSet : public CStringSet
  535. {
  536. protected:
  537. virtual CStringSet *createEmptySet()
  538. {
  539. return new CBigUnsignedStringSet(size);
  540. }
  541. virtual bool increment(void *_val) const
  542. {
  543. unsigned char *val = (unsigned char *)_val;
  544. int i = size;
  545. while (i--)
  546. {
  547. val[i]++;
  548. if (val[i]!=0)
  549. return true;
  550. }
  551. return false;
  552. }
  553. virtual bool decrement(void *_val) const
  554. {
  555. unsigned char *val = (unsigned char *)_val;
  556. int i = size;
  557. while (i--)
  558. {
  559. val[i]--;
  560. if ((unsigned char)val[i]!=0xff)
  561. return true;
  562. }
  563. return false;
  564. }
  565. virtual int memcmp(const void *val1, const void *val2, size32_t size) const
  566. {
  567. return ::memcmp(val1, val2, size);
  568. }
  569. virtual void memset(void *ptr, int val, size32_t size) const
  570. {
  571. ::memset(ptr, val, size);
  572. }
  573. virtual unsigned getCardinality(const void *val1, const void *val2, size32_t size) const
  574. {
  575. unsigned char *p1 = (unsigned char *) val1;
  576. unsigned char *p2 = (unsigned char *) val2;
  577. unsigned ret = 1;
  578. unsigned mult = 1;
  579. while (size--)
  580. {
  581. unsigned diff = p2[size] - p1[size];
  582. if (diff)
  583. {
  584. if (!mult)
  585. return (unsigned) -1;
  586. else
  587. ret += diff * mult;
  588. }
  589. if (mult*256 < mult)
  590. mult = 0;
  591. else
  592. mult *= 256;
  593. }
  594. return ret;
  595. }
  596. virtual bool isHighVal(const void *val) const
  597. {
  598. const unsigned char *vval = (const unsigned char *) val;
  599. for (unsigned i = 0; i < size; i++)
  600. if (vval[i] != 0xff)
  601. return false;
  602. return true;
  603. }
  604. virtual bool isLowVal(const void *val) const
  605. {
  606. const unsigned char *vval = (const unsigned char *) val;
  607. for (unsigned i = 0; i < size; i++)
  608. if (vval[i] != 0x00)
  609. return false;
  610. return true;
  611. }
  612. virtual bool isSigned() const { return false; }
  613. virtual bool isBigEndian() const { return true; }
  614. public:
  615. CBigUnsignedStringSet(unsigned size) : CStringSet(size) {}
  616. };
  617. class CBigSignedStringSet : public CBigUnsignedStringSet
  618. {
  619. protected:
  620. virtual CStringSet *createEmptySet()
  621. {
  622. return new CBigSignedStringSet(size);
  623. }
  624. // increment and decrement are same as unsigned
  625. virtual int memcmp(const void *val1, const void *val2, size32_t size) const
  626. {
  627. return ::memcmpbigsigned(val1, val2, size);
  628. }
  629. virtual void memset(void *ptr, int val, size32_t size) const
  630. {
  631. ::memset(ptr, val, size);
  632. switch(val)
  633. {
  634. case 0:
  635. *(unsigned char *) ptr = 0x80;
  636. break;
  637. case 0xff:
  638. *(unsigned char *) ptr = 0x7f;
  639. break;
  640. default:
  641. throwUnexpected();
  642. }
  643. }
  644. virtual bool isHighVal(const void *val) const
  645. {
  646. const unsigned char *vval = (const unsigned char *) val;
  647. if (vval[0] != 0x7f)
  648. return false;
  649. for (unsigned i = 1; i < size; i++)
  650. if (vval[i] != 0xff)
  651. return false;
  652. return true;
  653. }
  654. virtual bool isLowVal(const void *val) const
  655. {
  656. const unsigned char *vval = (const unsigned char *) val;
  657. if (vval[0] != 0x80)
  658. return false;
  659. for (unsigned i = 1; i < size; i++)
  660. if (vval[i] != 0x00)
  661. return false;
  662. return true;
  663. }
  664. virtual bool isSigned() const { return true; }
  665. virtual bool isBigEndian() const { return true; }
  666. public:
  667. CBigSignedStringSet(unsigned size) : CBigUnsignedStringSet(size) {}
  668. };
  669. class CLittleUnsignedStringSet : public CStringSet
  670. {
  671. protected:
  672. virtual CStringSet *createEmptySet()
  673. {
  674. return new CLittleUnsignedStringSet(size);
  675. }
  676. virtual bool increment(void *_val) const
  677. {
  678. unsigned char *val = (unsigned char *)_val;
  679. unsigned i = 0;
  680. while (i < size)
  681. {
  682. val[i]++;
  683. if (val[i]!=0)
  684. return true;
  685. i++;
  686. }
  687. return false;
  688. }
  689. virtual unsigned getCardinality(const void *val1, const void *val2, size32_t size) const
  690. {
  691. unsigned char *p1 = (unsigned char *) val1;
  692. unsigned char *p2 = (unsigned char *) val2;
  693. unsigned ret = 1;
  694. unsigned mult = 1;
  695. unsigned i = 0;
  696. while (i < size)
  697. {
  698. unsigned diff = p2[i] - p1[i];
  699. if (diff)
  700. {
  701. if (!mult)
  702. return (unsigned) -1;
  703. else
  704. ret += diff * mult;
  705. }
  706. if (mult*256 < mult)
  707. mult = 0;
  708. else
  709. mult *= 256;
  710. i++;
  711. }
  712. return ret;
  713. }
  714. virtual bool decrement(void *_val) const
  715. {
  716. unsigned char *val = (unsigned char *)_val;
  717. unsigned i = 0;
  718. while (i < size)
  719. {
  720. val[i]--;
  721. if ((unsigned char)val[i]!=0xff)
  722. return true;
  723. i++;
  724. }
  725. return false;
  726. }
  727. virtual int memcmp(const void *val1, const void *val2, size32_t size) const
  728. {
  729. return ::memcmplittleunsigned(val1, val2, size);
  730. }
  731. virtual void memset(void *ptr, int val, size32_t size) const
  732. {
  733. ::memset(ptr, val, size);
  734. }
  735. virtual bool isHighVal(const void *val) const
  736. {
  737. const unsigned char *vval = (const unsigned char *) val;
  738. for (unsigned i = 0; i < size; i++)
  739. if (vval[i] != 0xff)
  740. return false;
  741. return true;
  742. }
  743. virtual bool isLowVal(const void *val) const
  744. {
  745. const unsigned char *vval = (const unsigned char *) val;
  746. for (unsigned i = 0; i < size; i++)
  747. if (vval[i] != 0x00)
  748. return false;
  749. return true;
  750. }
  751. virtual bool isSigned() const { return false; }
  752. virtual bool isBigEndian() const { return false; }
  753. public:
  754. CLittleUnsignedStringSet(unsigned size) : CStringSet(size) {}
  755. };
  756. class CLittleSignedStringSet : public CLittleUnsignedStringSet
  757. {
  758. protected:
  759. virtual CStringSet *createEmptySet()
  760. {
  761. return new CLittleSignedStringSet(size);
  762. }
  763. // increment and decrement are same as unsigned
  764. virtual int memcmp(const void *val1, const void *val2, size32_t size) const
  765. {
  766. return ::memcmplittlesigned(val1, val2, size);
  767. }
  768. virtual void memset(void *ptr, int val, size32_t size) const
  769. {
  770. if (size > 1)
  771. ::memset(ptr, val, size);
  772. unsigned char *pptr = (unsigned char *) ptr;
  773. switch(val)
  774. {
  775. case 0:
  776. pptr[size-1] = 0x80;
  777. break;
  778. case 0xff:
  779. pptr[size-1] = 0x7f;
  780. break;
  781. default:
  782. throwUnexpected();
  783. }
  784. }
  785. virtual bool isHighVal(const void *val) const
  786. {
  787. const unsigned char *vval = (const unsigned char *) val;
  788. if (vval[size-1] != 0x7f)
  789. return false;
  790. for (unsigned i = 0; i < size-1; i++)
  791. if (vval[i] != 0xff)
  792. return false;
  793. return true;
  794. }
  795. virtual bool isLowVal(const void *val) const
  796. {
  797. const unsigned char *vval = (const unsigned char *) val;
  798. if (vval[size-1] != 0x80)
  799. return false;
  800. for (unsigned i = 0; i < size-1; i++)
  801. if (vval[i] != 0x00)
  802. return false;
  803. return true;
  804. }
  805. virtual bool isSigned() const { return true; }
  806. virtual bool isBigEndian() const { return false; }
  807. public:
  808. CLittleSignedStringSet(unsigned size) : CLittleUnsignedStringSet(size) {}
  809. };
  810. class CTransition : implements ITransition, public CInterface
  811. {
  812. private:
  813. bool state; // note: should move before ITransition to pack better in 64bit
  814. const void *val;
  815. public:
  816. IMPLEMENT_IINTERFACE;
  817. CTransition(const void *_val, bool _state)
  818. {
  819. val = _val;
  820. state = _state;
  821. }
  822. ~CTransition() { free((void *) val); }
  823. // ITransition
  824. virtual bool getState() const override { return state; }
  825. virtual const void *getValue() const override { return val; }
  826. };
  827. //======================================================================================
  828. CStringSet::CStringSet(size32_t _size)
  829. {
  830. size = _size;
  831. }
  832. void CStringSet::reset()
  833. {
  834. transitions.kill();
  835. }
  836. bool CStringSet::oneless(const void *l, const void *r) const
  837. {
  838. // MORE - would be more efficient to make this virtual like the memcmp...
  839. void *t = alloca(size);
  840. memcpy(t, r, size);
  841. decrement(t);
  842. return memcmp(l, t, size)==0;
  843. }
  844. unsigned CStringSet::transitionCount()
  845. {
  846. return transitions.ordinality();
  847. }
  848. void CStringSet::addTransitionAt(const void *val, bool state, unsigned pos)
  849. {
  850. void *newval = malloc(size);
  851. memcpy(newval, val, size);
  852. transitions.add(* new CTransition(newval, state), pos);
  853. }
  854. void CStringSet::appendTransition(ITransition *t)
  855. {
  856. if (t->getState() && transitions.length())
  857. {
  858. unsigned lastidx = transitions.length()-1;
  859. ITransition &prev = transitions.item(lastidx);
  860. assertex(prev.getState()==!t->getState());
  861. if (oneless(prev.getValue(), t->getValue()))
  862. {
  863. transitions.remove(lastidx);
  864. t->Release();
  865. return;
  866. }
  867. }
  868. transitions.append(*t);
  869. }
  870. void CStringSet::addRange(const void *loval, const void *hival)
  871. {
  872. if (!loval)
  873. {
  874. void *x = alloca(size);
  875. memset(x, 0, size);
  876. loval = x;
  877. }
  878. if (!hival)
  879. {
  880. void *x = alloca(size);
  881. memset(x, 0xff, size);
  882. hival = x;
  883. }
  884. if (memcmp(loval, hival, size) > 0)
  885. return;
  886. unsigned idx;
  887. bool inset = false;
  888. int b = transitions.ordinality();
  889. if (!b)
  890. {
  891. addTransitionAt(loval, true, 0);
  892. addTransitionAt(hival, false, 1);
  893. return;
  894. }
  895. else
  896. {
  897. // binchop to find last transition > val...
  898. unsigned int a = 0;
  899. int rc;
  900. while ((int)a<b)
  901. {
  902. int i = a+(b+1-a)/2;
  903. rc = memcmp(loval, transitions.item(i-1).getValue(), size);
  904. if (rc>0)
  905. a = i;
  906. else
  907. b = i-1;
  908. }
  909. if (a>0)
  910. {
  911. idx = a;
  912. ITransition &t = transitions.item(idx-1);
  913. if(!t.getState())
  914. {
  915. if (oneless(t.getValue(), loval))
  916. transitions.remove(--idx);
  917. else
  918. addTransitionAt(loval, true, idx++);
  919. }
  920. else
  921. inset = true;
  922. }
  923. else
  924. {
  925. addTransitionAt(loval, true, 0);
  926. idx = 1;
  927. }
  928. }
  929. while (transitions.isItem(idx))
  930. {
  931. ITransition &t = transitions.item(idx);
  932. int diff = memcmp(t.getValue(), hival, size);
  933. if (diff <= 0)
  934. {
  935. inset = t.getState();
  936. transitions.remove(idx);
  937. }
  938. else
  939. break;
  940. }
  941. if (!inset)
  942. {
  943. if (transitions.isItem(idx))
  944. {
  945. ITransition &t = transitions.item(idx);
  946. assertex(t.getState());
  947. if (oneless(hival, t.getValue()))
  948. {
  949. transitions.remove(idx);
  950. return;
  951. }
  952. }
  953. addTransitionAt(hival, false, idx);
  954. }
  955. }
  956. void CStringSet::killRange(const void *loval, const void *hival)
  957. {
  958. if (!loval)
  959. {
  960. void *x = alloca(size);
  961. memset(x, 0, size);
  962. loval = x;
  963. }
  964. if (!hival)
  965. {
  966. void *x = alloca(size);
  967. memset(x, 0xff, size);
  968. hival = x;
  969. }
  970. assertex(memcmp(loval, hival, size) <= 0);
  971. bool inset = false;
  972. ForEachItemIn(idx, transitions)
  973. {
  974. ITransition &t = transitions.item(idx);
  975. int diff = memcmp(t.getValue(), loval, size);
  976. if (diff < 0)
  977. inset = t.getState();
  978. else
  979. break;
  980. }
  981. if (inset)
  982. {
  983. void *nlo = alloca(size);
  984. memcpy(nlo, loval, size);
  985. decrement(nlo);
  986. addTransitionAt(nlo, false, idx++);
  987. }
  988. while (transitions.isItem(idx))
  989. {
  990. ITransition &t = transitions.item(idx);
  991. int diff = memcmp(t.getValue(), hival, size);
  992. if (diff <= 0)
  993. {
  994. inset = t.getState();
  995. transitions.remove(idx);
  996. }
  997. else
  998. break;
  999. }
  1000. if (inset)
  1001. {
  1002. void *nhi = alloca(size);
  1003. memcpy(nhi, hival, size);
  1004. increment(nhi);
  1005. addTransitionAt(nhi, true, idx);
  1006. }
  1007. }
  1008. void CStringSet::addAll()
  1009. {
  1010. reset();
  1011. void *val = alloca(size);
  1012. memset(val, 0, size);
  1013. addTransitionAt(val, true, 0);
  1014. memset(val, 0xff, size);
  1015. addTransitionAt(val, false, 1);
  1016. }
  1017. const char *CStringSet::describe(StringBuffer &ret)
  1018. {
  1019. ret.append('[');
  1020. ForEachItemIn(idx, transitions)
  1021. {
  1022. ITransition &t = transitions.item(idx);
  1023. if (t.getState())
  1024. {
  1025. if (idx)
  1026. ret.append(',');
  1027. }
  1028. else
  1029. ret.append("..");
  1030. appendURL(&ret, (char *) t.getValue(), size, true);
  1031. }
  1032. ret.append(']');
  1033. return ret.str();
  1034. }
  1035. bool CStringSet::inRange(const void *val) const
  1036. {
  1037. unsigned nextTransition;
  1038. return inRange(val, nextTransition);
  1039. }
  1040. bool CStringSet::inRange(const void *val, unsigned &nextTransition) const
  1041. {
  1042. int b = transitions.ordinality();
  1043. if (!b)
  1044. {
  1045. nextTransition = (unsigned) -1;
  1046. return false;
  1047. }
  1048. else if (b >= 4)
  1049. {
  1050. // binchop to find last transition >= val...
  1051. unsigned int a = 0;
  1052. int rc;
  1053. while ((int)a<b)
  1054. {
  1055. int i = a+(b+1-a)/2;
  1056. rc = memcmp(val, transitions.item(i-1).getValue(), size);
  1057. if (rc>=0)
  1058. a = i;
  1059. else
  1060. b = i-1;
  1061. }
  1062. if (a>0)
  1063. {
  1064. nextTransition = (a>=transitions.ordinality())? (unsigned) -1: a; // a is first transition that is > val
  1065. a--;
  1066. if (transitions.item(a).getState())
  1067. return true;
  1068. if (memcmp(val, transitions.item(a).getValue(), size)==0)
  1069. {
  1070. nextTransition = a;
  1071. return true;
  1072. }
  1073. return false;
  1074. }
  1075. else
  1076. {
  1077. nextTransition = 0;
  1078. return false;
  1079. }
  1080. }
  1081. else
  1082. {
  1083. bool inset = false;
  1084. ForEachItemIn(idx, transitions)
  1085. {
  1086. ITransition &t = transitions.item(idx);
  1087. int diff = memcmp(t.getValue(), val, size);
  1088. if (t.getState())
  1089. {
  1090. if (diff <= 0)
  1091. inset = true;
  1092. if (diff == 0)
  1093. {
  1094. idx++;
  1095. break;
  1096. }
  1097. else if (diff > 0)
  1098. break;
  1099. }
  1100. else
  1101. {
  1102. if (diff >= 0)
  1103. break;
  1104. if (diff < 0)
  1105. inset = false;
  1106. }
  1107. }
  1108. nextTransition = (idx>=transitions.ordinality())? (unsigned) -1: idx;
  1109. return inset;
  1110. }
  1111. }
  1112. IStringSet *CStringSet::unionOrIntersect(IStringSet *r, bool isUnion)
  1113. {
  1114. bool inA = false;
  1115. bool inB = false;
  1116. bool state = false;
  1117. assertex(r->getSize()==size);
  1118. int idxA = 0;
  1119. int idxB = 0;
  1120. ITransition *tA = queryTransition(idxA);
  1121. ITransition *tB = r->queryTransition(idxB);
  1122. CStringSet *result = createEmptySet();
  1123. for (;;)
  1124. {
  1125. int diff;
  1126. if (tA == NULL)
  1127. {
  1128. if (tB == NULL)
  1129. break;
  1130. else
  1131. diff = 1;
  1132. }
  1133. else if (tB == NULL)
  1134. diff = -1;
  1135. else
  1136. diff = memcmp(tA->getValue(), tB->getValue(), size);
  1137. ITransition *t = NULL;
  1138. if (!diff)
  1139. {
  1140. diff = (int) tB->getState() - (int) tA->getState(); // leading edge sorts before trailing edge for intersect...
  1141. if (isUnion)
  1142. diff = -diff; // trailing edge sorts before leading edge for union...
  1143. }
  1144. if (diff <= 0)
  1145. {
  1146. inA = tA->getState();
  1147. t = tA;
  1148. idxA++;
  1149. tA = queryTransition(idxA);
  1150. }
  1151. if (diff >= 0)
  1152. {
  1153. inB = tB->getState();
  1154. t = tB;
  1155. idxB++;
  1156. tB = r->queryTransition(idxB);
  1157. }
  1158. bool newState;
  1159. if (isUnion)
  1160. newState = inA || inB;
  1161. else
  1162. newState = inA && inB;
  1163. if (newState != state)
  1164. {
  1165. state = newState;
  1166. t->Link();
  1167. result->appendTransition(t);
  1168. }
  1169. }
  1170. return result;
  1171. }
  1172. IStringSet *CStringSet::invertSet()
  1173. {
  1174. CStringSet *result = createEmptySet();
  1175. result->addAll();
  1176. bool inset = false;
  1177. void *loval = alloca(size);
  1178. void *hival = alloca(size);
  1179. memset(loval, 0, size);
  1180. ForEachItemIn(idx, transitions)
  1181. {
  1182. ITransition &t = transitions.item(idx);
  1183. assertex(t.getState() == !inset);
  1184. if (inset)
  1185. {
  1186. memcpy(hival, t.getValue(), size);
  1187. result->killRange(loval, hival);
  1188. }
  1189. else
  1190. memcpy(loval, t.getValue(), size);
  1191. inset = t.getState();
  1192. }
  1193. if (inset)
  1194. {
  1195. memset(hival, 0xff, size);
  1196. result->killRange(loval, hival);
  1197. }
  1198. return result;
  1199. }
  1200. IStringSet *CStringSet::unionSet(IStringSet *other)
  1201. {
  1202. return unionOrIntersect(other, true);
  1203. }
  1204. IStringSet *CStringSet::intersectSet(IStringSet *other)
  1205. {
  1206. return unionOrIntersect(other, false);
  1207. }
  1208. ITransition *CStringSet::queryTransition(unsigned int idx)
  1209. {
  1210. if (transitions.isItem(idx))
  1211. {
  1212. ITransition *t = &transitions.item(idx);
  1213. return t;
  1214. }
  1215. else
  1216. return NULL;
  1217. }
  1218. bool CStringSet::getTransitionValue(void *value, unsigned int idx)
  1219. {
  1220. if (idx == (unsigned) -1 || idx >= transitions.ordinality()) return false;
  1221. ITransition &t = transitions.item(idx);
  1222. memcpy(value, t.getValue(), size);
  1223. return true;
  1224. }
  1225. IStringSet *createStringSet(size32_t size)
  1226. {
  1227. return new CBigUnsignedStringSet(size);
  1228. }
  1229. IStringSet *createStringSet(size32_t size, bool bigEndian, bool isSigned)
  1230. {
  1231. if (bigEndian)
  1232. {
  1233. if (isSigned)
  1234. return new CBigSignedStringSet(size);
  1235. else
  1236. return new CBigUnsignedStringSet(size);
  1237. }
  1238. else
  1239. {
  1240. if (isSigned)
  1241. return new CLittleSignedStringSet(size);
  1242. else
  1243. return new CLittleUnsignedStringSet(size);
  1244. }
  1245. }
  1246. //---------------------------------------------------------------------------------------------------------------------
  1247. class LegacySetCreator : implements ISetCreator
  1248. {
  1249. public:
  1250. LegacySetCreator(IStringSet & _set, size32_t _minRecordSize, const RtlTypeInfo * _fieldType)
  1251. : set(_set), fieldType(_fieldType), minRecordSize(_minRecordSize) {}
  1252. virtual void addRange(TransitionMask lowerMask, const StringBuffer & lowerString, TransitionMask upperMask, const StringBuffer & upperString) override
  1253. {
  1254. MemoryBufferBuilder lobuilder(lobuffer.clear(), minRecordSize);
  1255. fieldType->buildUtf8(lobuilder, 0, nullptr, lowerString.length(), lowerString.str());
  1256. MemoryBufferBuilder hibuilder(hibuffer.clear(), minRecordSize);
  1257. fieldType->buildUtf8(hibuilder, 0, nullptr, upperString.length(), upperString.str());
  1258. set.addRange(lobuffer.toByteArray(), hibuffer.toByteArray());
  1259. if (!(lowerMask & CMPeq))
  1260. set.killRange(lobuffer.toByteArray(), lobuffer.toByteArray());
  1261. if (!(upperMask & CMPeq))
  1262. set.killRange(hibuffer.toByteArray(), hibuffer.toByteArray());
  1263. }
  1264. protected:
  1265. IStringSet & set;
  1266. const RtlTypeInfo *fieldType;
  1267. size32_t minRecordSize;
  1268. MemoryBuffer lobuffer;
  1269. MemoryBuffer hibuffer;
  1270. };
  1271. void deserializeSet(IStringSet & set, size32_t minRecordSize, const RtlTypeInfo * fieldType, const char * filter)
  1272. {
  1273. LegacySetCreator creator(set, minRecordSize, fieldType);
  1274. deserializeSet(creator, filter);
  1275. }
  1276. #ifdef _USE_CPPUNIT
  1277. #include <cppunit/extensions/HelperMacros.h>
  1278. /*
  1279. class IStdException : extends std::exception
  1280. {
  1281. Owned<IException> jException;
  1282. public:
  1283. IStdException(IException *E) : jException(E) {};
  1284. };
  1285. */
  1286. class SegmentMonitorTest : public CppUnit::TestFixture
  1287. {
  1288. CPPUNIT_TEST_SUITE( SegmentMonitorTest );
  1289. CPPUNIT_TEST(testOptional);
  1290. CPPUNIT_TEST_SUITE_END();
  1291. protected:
  1292. void testOptional()
  1293. {
  1294. Owned<IKeySegmentMonitor> wild0_20 = createWildKeySegmentMonitor(0, 0, 20);
  1295. Owned<IKeySegmentMonitor> wild10_10 = createWildKeySegmentMonitor(1, 10,10);
  1296. Owned<IStringSet> abcdef = createStringSet(10);
  1297. abcdef->addRange("ABCDEFGHIJ", "ABCDEFGHIJ");
  1298. Owned<IKeySegmentMonitor> opt0_20 = createSingleKeySegmentMonitor(true, 0, 0,20, "abcdefghijklmnopqrst");
  1299. Owned<IKeySegmentMonitor> opt20_10 = createKeySegmentMonitor(true, LINK(abcdef), 1, 20, 10);
  1300. Owned<IKeySegmentMonitor> opt30_10 = createSingleKeySegmentMonitor(true, 2, 30, 10, "KLMNOPQRST");
  1301. Owned<IKeySegmentMonitor> nonOpt0_10 = createSingleKeySegmentMonitor(false, 0, 0,10, "abcdefghij");
  1302. Owned<IKeySegmentMonitor> nonOpt0_20 = createSingleKeySegmentMonitor(false, 0, 0,20, "abcdefghijklmnopqrst");
  1303. Owned<IKeySegmentMonitor> nonOpt20_10 = createKeySegmentMonitor(false, LINK(abcdef), 1, 20, 10);
  1304. Owned<IKeySegmentMonitor> nonOpt30_10 = createSingleKeySegmentMonitor(false, 2, 30, 10, "KLMNOPQRST");
  1305. CPPUNIT_ASSERT(wild0_20->isOptional());
  1306. CPPUNIT_ASSERT(opt20_10->isOptional());
  1307. CPPUNIT_ASSERT(opt30_10->isOptional());
  1308. CPPUNIT_ASSERT(!nonOpt0_10->isOptional());
  1309. CPPUNIT_ASSERT(!nonOpt0_20->isOptional());
  1310. CPPUNIT_ASSERT(!nonOpt20_10->isOptional());
  1311. CPPUNIT_ASSERT(!nonOpt30_10->isOptional());
  1312. #if 0
  1313. IKeySegmentMonitorArray segments;
  1314. segments.append(*LINK(wild0_20));
  1315. segments.append(*LINK(opt20_10));
  1316. CPPUNIT_ASSERT(segments.ordinality() == 1);
  1317. CPPUNIT_ASSERT(segments.item(0).isWild());
  1318. CPPUNIT_ASSERT(segments.item(0).getOffset() == 0);
  1319. CPPUNIT_ASSERT(segments.item(0).getSize() == 30);
  1320. segments.kill();
  1321. segments.append(*LINK(wild0_20));
  1322. segments.append(*LINK(opt20_10));
  1323. segments.append(*LINK(nonOpt30_10));
  1324. CPPUNIT_ASSERT(segments.ordinality() == 2);
  1325. CPPUNIT_ASSERT(segments.item(0).isWild());
  1326. CPPUNIT_ASSERT(segments.item(0).getOffset() == 0);
  1327. CPPUNIT_ASSERT(segments.item(0).getSize() == 30);
  1328. CPPUNIT_ASSERT(!segments.item(1).isWild());
  1329. CPPUNIT_ASSERT(segments.item(1).getOffset() == 30);
  1330. CPPUNIT_ASSERT(segments.item(1).getSize() == 10);
  1331. segments.kill();
  1332. segments.append(*LINK(nonOpt0_20));
  1333. segments.append(*LINK(opt20_10));
  1334. segments.append(*LINK(nonOpt30_10));
  1335. CPPUNIT_ASSERT(segments.ordinality() == 3);
  1336. CPPUNIT_ASSERT(!segments.item(1).isWild());
  1337. CPPUNIT_ASSERT(segments.item(1).getOffset() == 20);
  1338. CPPUNIT_ASSERT(segments.item(1).getSize() == 10);
  1339. segments.kill();
  1340. segments.append(*LINK(nonOpt0_10));
  1341. segments.append(*LINK(wild10_10));
  1342. segments.append(*LINK(opt20_10));
  1343. segments.append(*LINK(nonOpt30_10));
  1344. CPPUNIT_ASSERT(segments.ordinality() == 3);
  1345. CPPUNIT_ASSERT(!segments.item(0).isWild());
  1346. CPPUNIT_ASSERT(segments.item(1).isWild());
  1347. CPPUNIT_ASSERT(segments.item(1).getOffset() == 10);
  1348. CPPUNIT_ASSERT(segments.item(1).getSize() == 20);
  1349. segments.kill();
  1350. segments.append(*LINK(opt0_20));
  1351. segments.append(*LINK(opt20_10));
  1352. segments.append(*LINK(nonOpt30_10));
  1353. CPPUNIT_ASSERT(segments.ordinality() == 3);
  1354. CPPUNIT_ASSERT(!segments.item(0).isWild());
  1355. CPPUNIT_ASSERT(!segments.item(1).isWild());
  1356. CPPUNIT_ASSERT(segments.item(1).getOffset() == 20);
  1357. CPPUNIT_ASSERT(segments.item(1).getSize() == 10);
  1358. #endif
  1359. }
  1360. };
  1361. CPPUNIT_TEST_SUITE_REGISTRATION( SegmentMonitorTest );
  1362. CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( SegmentMonitorTest, "SegmentMonitorTest" );
  1363. #endif