12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901 |
- /*##############################################################################
- HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems®.
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ############################################################################## */
- #include "jlib.hpp"
- #include "jsort.hpp"
- #include "jexcept.hpp"
- #include "rtlkey.hpp"
- #include "rtlkey2.hpp"
- #include "eclrtl_imp.hpp"
- #include "rtlrecord.hpp"
- #include "rtlnewkey.hpp"
- class CKeySegmentMonitor : implements IKeySegmentMonitor, public CInterface
- {
- protected:
- size32_t size;
- size32_t offset;
- unsigned fieldIdx;
- unsigned hash;
- public:
- IMPLEMENT_IINTERFACE;
- CKeySegmentMonitor(unsigned _fieldIdx, unsigned _offset, unsigned _size);
- CKeySegmentMonitor(MemoryBuffer &mb)
- {
- mb.read(size).read(offset).read(fieldIdx).read(hash);
- }
- virtual bool matchesBuffer(const void * rawRow) const override = 0;
- virtual bool matches(const RtlRow * rawRow) const override
- {
- return matchesBuffer(rawRow->queryRow());
- }
- virtual bool increment(void *keyval) const override;
- virtual unsigned getFieldIdx() const override { return fieldIdx; }
- virtual unsigned getOffset() const override { return offset; }
- virtual unsigned getSize() const override { return size; }
- virtual bool isWild() const override { return false; }
- virtual bool isEmpty() const override { return false; }
- virtual bool isSigned() const override { return false; }
- virtual bool isLittleEndian() const override { return false; }
- virtual unsigned numFieldsRequired() const override { return 0; } // Should rename to queryFieldIdx or similar
- virtual int docompare(const void * l, const void * r) const override
- {
- char *lptr = ((char *) l) + offset;
- char *rptr = ((char *) r) + offset;
- return memcmp(lptr, rptr, size);
- }
- virtual bool equivalentTo(const IKeySegmentMonitor &other) const override
- {
- return offset==other.getOffset()
- && size==other.getSize()
- && isSigned()==other.isSigned()
- && isLittleEndian()==other.isLittleEndian();
- }
- virtual unsigned queryHashCode() const override
- {
- return hash;
- }
- virtual bool setOffset(unsigned _offset) override
- {
- offset = _offset;
- return true;
- }
- virtual void setHigh(void *keyval) const override;
- virtual void copy(void * l, const void * r) const override
- {
- char *lptr = ((char *) l) + offset;
- char *rptr = ((char *) r) + offset;
- memcpy(lptr, rptr, size);
- }
- virtual MemoryBuffer &serialize(MemoryBuffer &mb) const override
- {
- KeySegmentMonitorSerializeType typ = serializeType();
- assertex(typ!=KSMST_none);
- return mb.append((byte)typ).append(size).append(offset).append(hash);
- }
- virtual KeySegmentMonitorSerializeType serializeType() const override = 0;
- };
- class CWildKeySegmentMonitor : public CKeySegmentMonitor
- {
- public:
- CWildKeySegmentMonitor(unsigned _fieldIdx, unsigned _offset, unsigned _size);
- CWildKeySegmentMonitor(MemoryBuffer &mb)
- : CKeySegmentMonitor(mb)
- {
- }
- virtual bool matchesBuffer(const void *keyval) const override;
- virtual int docompare(const void *,const void *) const override;
- virtual void setLow(void *keyval) const override;
- virtual void endRange(void *keyval) const override;
- virtual bool isWild() const override { return true; }
- virtual bool isSimple() const override { return true; }
- virtual bool isWellKeyed() const override { return false; }
- virtual bool isOptional() const override { return true; }
- virtual IKeySegmentMonitor *clone() const override;
- virtual KeySegmentMonitorSerializeType serializeType() const override { return KSMST_WILDKEYSEGMENTMONITOR; }
- };
- class CSetKeySegmentMonitor : public CKeySegmentMonitor
- {
- private:
- Owned<IStringSet> set;
- bool optional;
- public:
- CSetKeySegmentMonitor(bool _optional, IStringSet *set, unsigned _fieldIdx, unsigned _offset, unsigned _size);
- CSetKeySegmentMonitor(MemoryBuffer &mb)
- : CKeySegmentMonitor(mb)
- {
- set.setown(deserializeStringSet(mb));
- mb.read(optional);
- }
- // IKeySegmentMonitor
- virtual bool increment(void *keyval) const override;
- virtual void setLow(void *keyval) const override;
- virtual bool matchesBuffer(const void *keyval) const override;
- virtual void endRange(void *keyval) const override;
- virtual bool isEmpty() const override { return set->isEmptySet(); }
- virtual bool isWellKeyed() const override;
- virtual bool isOptional() const override { return optional; }
- virtual bool isSimple() const override { return true; }
- virtual bool isSigned() const override { return set->isSigned(); }
- virtual bool isLittleEndian() const override { return !set->isBigEndian(); }
- virtual IKeySegmentMonitor *clone() const override;
- virtual int docompare(const void * l, const void * r) const override
- {
- char *lptr = ((char *) l) + offset;
- char *rptr = ((char *) r) + offset;
- return set->memcmp(lptr, rptr, size);
- }
- virtual MemoryBuffer &serialize(MemoryBuffer &mb) const override
- {
- CKeySegmentMonitor::serialize(mb);
- set->serialize(mb);
- return mb.append(optional);
- }
- virtual KeySegmentMonitorSerializeType serializeType() const override { return KSMST_SETKEYSEGMENTMONITOR; }
- };
- CKeySegmentMonitor::CKeySegmentMonitor(unsigned _fieldIdx, unsigned _offset, unsigned _size)
- {
- size = _size;
- offset = _offset;
- fieldIdx = _fieldIdx;
- hash = 123456;
- hash = hashc((unsigned char *) &offset, sizeof(offset), hash);
- hash = hashc((unsigned char *) &size, sizeof(size), hash);
- }
- bool CKeySegmentMonitor::increment(void *bufptr) const
- {
- char *ptr = ((char *) bufptr) + offset;
- int i = size;
- while (i--)
- {
- ptr[i]++;
- if (ptr[i]!=0)
- return true;
- }
- return false;
- }
- void CKeySegmentMonitor::setHigh(void *bufptr) const
- {
- // NOTE - effectively whenever this is called we are treating the segmonitor as if it was a wild one
- char *ptr = ((char *) bufptr) + offset;
- memset(ptr, 0xff, size);
- }
- CWildKeySegmentMonitor::CWildKeySegmentMonitor(unsigned _fieldIdx, unsigned _offset, unsigned _size)
- : CKeySegmentMonitor(_fieldIdx, _offset, _size)
- {
- }
- IKeySegmentMonitor *CWildKeySegmentMonitor::clone() const
- {
- return new CWildKeySegmentMonitor(fieldIdx, offset, size);
- }
- bool CWildKeySegmentMonitor::matchesBuffer(const void *keyval) const
- {
- return true;
- }
- int CWildKeySegmentMonitor::docompare(const void *l, const void *r) const
- {
- return 0;
- }
- void CWildKeySegmentMonitor::setLow(void *bufptr) const
- {
- char *ptr = ((char *) bufptr) + offset;
- memset(ptr, 0, size);
- }
- void CWildKeySegmentMonitor::endRange(void *bufptr) const
- {
- char *ptr = ((char *) bufptr) + offset;
- memset(ptr, 0xff, size);
- }
- CSetKeySegmentMonitor::CSetKeySegmentMonitor(bool _optional, IStringSet *_set, unsigned _fieldIdx, unsigned _offset, unsigned _size)
- : set(_set), CKeySegmentMonitor(_fieldIdx, _offset, _size)
- {
- optional = _optional;
- hash = FNV_32_HASHONE_VALUE(hash, (byte) set->isSigned());
- hash = FNV_32_HASHONE_VALUE(hash, (byte) !set->isBigEndian());
- }
- IKeySegmentMonitor *CSetKeySegmentMonitor::clone() const
- {
- return new CSetKeySegmentMonitor(optional, set.getLink(), fieldIdx, offset, size);
- }
- bool CSetKeySegmentMonitor::increment(void *bufptr) const
- {
- char *ptr = ((char *) bufptr) + offset;
- bool ok = set->increment(ptr);
- if (ok)
- {
- unsigned nextTransition;
- bool res = set->inRange(ptr, nextTransition);
- if (!res)
- {
- if (-1 == nextTransition) return false;
- set->getTransitionValue(ptr, nextTransition);
- }
- }
- return ok;
- }
- void CSetKeySegmentMonitor::setLow(void *bufptr) const
- {
- char *ptr = ((char *) bufptr) + offset;
- if (set->transitionCount())
- set->getTransitionValue(ptr, 0);
- else
- memset(ptr, 0, size); // MORE - should really trap earlier
- }
- void CSetKeySegmentMonitor::endRange(void *bufptr) const
- {
- char *ptr = ((char *) bufptr) + offset;
- unsigned nextTransition;
- bool res = set->inRange(ptr, nextTransition);
- assertex(res);
- verifyex(set->getTransitionValue(ptr, nextTransition));
- }
- bool CSetKeySegmentMonitor::matchesBuffer(const void *bufptr) const
- {
- char *ptr = ((char *) bufptr) + offset;
- return set->inRange(ptr);
- }
- bool CSetKeySegmentMonitor::isWellKeyed() const
- {
- // This check determines whether or not keyed, opt considers this field to be keyed.
- // The goal is to allow sets but not ranges, slightly complicated by the fact that adjacent values in a set turn into ranges.
- return set->numValues() < 50;
- }
- class CSingleKeySegmentMonitorBase : public CKeySegmentMonitor
- {
- protected:
- void *val;
- bool optional;
- public:
- CSingleKeySegmentMonitorBase(bool _optional, const void *_val, unsigned _fieldIdx, unsigned _offset, unsigned _size)
- : CKeySegmentMonitor(_fieldIdx, _offset, _size)
- {
- if (_val)
- {
- val = malloc(_size);
- memcpy(val, _val, _size);
- }
- else
- val = NULL;
- optional = _optional;
- }
- CSingleKeySegmentMonitorBase(bool _optional, unsigned _fieldIdx, unsigned _offset, unsigned _size)
- : CKeySegmentMonitor(_fieldIdx, _offset, _size)
- {
- val = NULL;
- optional = _optional;
- }
- CSingleKeySegmentMonitorBase(MemoryBuffer &mb)
- : CKeySegmentMonitor(mb)
- {
- bool hasval;
- mb.read(hasval);
- if (hasval) {
- val = malloc(size);
- memcpy(val,mb.readDirect(size),size);
- }
- else
- val = NULL;
- mb.read(optional);
- }
- ~CSingleKeySegmentMonitorBase()
- {
- free(val);
- }
- // IKeySegmentMonitor
- virtual bool increment(void *bufptr) const override
- {
- // Set to next permitted value above current
- if (docompare(bufptr, ((char *) val)-offset) < 0)
- {
- char *ptr = ((char *) bufptr) + offset;
- memcpy(ptr, val, size);
- return true;
- }
- else
- return false;
- }
- virtual void setLow(void *bufptr) const override
- {
- // Set to lowest permitted value
- char *ptr = ((char *) bufptr) + offset;
- memcpy(ptr, val, size);
- }
- virtual bool matchesBuffer(const void *bufptr) const override
- {
- // Is current a permitted value?
- char *ptr = ((char *) bufptr) + offset;
- return memcmp(ptr, val, size) == 0;
- }
- virtual void endRange(void *bufptr) const override
- {
- // Set to last permitted value in the range that includes current (which is asserted to be valid)
- #ifdef DEBUG
- assertex(matchesBuffer(bufptr));
- #endif
- }
- virtual bool isWellKeyed() const override { return true; }
- virtual bool isOptional() const override { return optional; }
- virtual bool isSimple() const override { return true; }
- virtual MemoryBuffer &serialize(MemoryBuffer &mb) const override
- {
- CKeySegmentMonitor::serialize(mb);
- if (val)
- mb.append((bool)true).append(size,val);
- else
- mb.append((bool)false);
- return mb.append(optional);
- }
- };
- class CSingleKeySegmentMonitor : public CSingleKeySegmentMonitorBase
- {
- public:
- CSingleKeySegmentMonitor(bool _optional, const void *_val, unsigned _fieldIdx, unsigned _offset, unsigned _size)
- : CSingleKeySegmentMonitorBase(_optional, _val, _fieldIdx, _offset, _size)
- {
- hash = FNV_32_HASHONE_VALUE(hash, (byte) 0);
- hash = FNV_32_HASHONE_VALUE(hash, (byte) 0);
- }
- CSingleKeySegmentMonitor(MemoryBuffer &mb)
- : CSingleKeySegmentMonitorBase(mb)
- {
- }
- virtual IKeySegmentMonitor *clone() const override
- {
- return new CSingleKeySegmentMonitor(optional, val, fieldIdx, offset, size);
- }
- virtual bool isSigned() const override { return false; }
- virtual bool isLittleEndian() const override { return false; }
- virtual KeySegmentMonitorSerializeType serializeType() const override { return KSMST_SINGLEKEYSEGMENTMONITOR; }
- };
- class CSingleBigSignedKeySegmentMonitor : public CSingleKeySegmentMonitorBase
- {
- public:
- CSingleBigSignedKeySegmentMonitor(bool _optional, const void *_val, unsigned _fieldIdx, unsigned _offset, unsigned _size)
- : CSingleKeySegmentMonitorBase(_optional, _val, _fieldIdx, _offset, _size)
- {
- hash = FNV_32_HASHONE_VALUE(hash, (byte) 1);
- hash = FNV_32_HASHONE_VALUE(hash, (byte) 0);
- }
- CSingleBigSignedKeySegmentMonitor(MemoryBuffer &mb)
- : CSingleKeySegmentMonitorBase(mb)
- {
- }
- virtual IKeySegmentMonitor *clone() const override
- {
- return new CSingleBigSignedKeySegmentMonitor(optional, val, fieldIdx, offset, size);
- }
- virtual int docompare(const void *l, const void *r) const override
- {
- return memcmpbigsigned(((char *) l) + offset, ((char *) r) + offset, size);
- }
- virtual bool isSigned() const override { return true; }
- virtual bool isLittleEndian() const override { return false; }
- virtual KeySegmentMonitorSerializeType serializeType() const override { return KSMST_SINGLEBIGSIGNEDKEYSEGMENTMONITOR; }
- };
- class CSingleLittleSignedKeySegmentMonitor : public CSingleKeySegmentMonitorBase
- {
- public:
- CSingleLittleSignedKeySegmentMonitor(bool _optional, const void *_val, unsigned _fieldIdx, unsigned _offset, unsigned _size)
- : CSingleKeySegmentMonitorBase(_optional, _val, _fieldIdx, _offset, _size)
- {
- hash = FNV_32_HASHONE_VALUE(hash, (byte) 1);
- hash = FNV_32_HASHONE_VALUE(hash, (byte) 1);
- }
- CSingleLittleSignedKeySegmentMonitor(MemoryBuffer &mb)
- : CSingleKeySegmentMonitorBase(mb)
- {
- }
- virtual IKeySegmentMonitor *clone() const override
- {
- return new CSingleLittleSignedKeySegmentMonitor(optional, val, fieldIdx, offset, size);
- }
- virtual int docompare(const void *l, const void *r) const
- {
- return memcmplittlesigned(((char *) l) + offset, ((char *) r) + offset, size);
- }
- virtual bool isSigned() const override { return true; }
- virtual bool isLittleEndian() const override { return true; }
- virtual KeySegmentMonitorSerializeType serializeType() const override { return KSMST_SINGLELITTLESIGNEDKEYSEGMENTMONITOR; }
- };
- class CSingleLittleKeySegmentMonitor : public CSingleKeySegmentMonitorBase
- {
- public:
- CSingleLittleKeySegmentMonitor(bool _optional, const void *_val, unsigned _fieldIdx, unsigned _offset, unsigned _size)
- : CSingleKeySegmentMonitorBase(_optional, _val, _fieldIdx, _offset, _size)
- {
- hash = FNV_32_HASHONE_VALUE(hash, (byte) 0);
- hash = FNV_32_HASHONE_VALUE(hash, (byte) 1);
- }
- CSingleLittleKeySegmentMonitor(MemoryBuffer &mb)
- : CSingleKeySegmentMonitorBase(mb)
- {
- }
- virtual IKeySegmentMonitor *clone() const override
- {
- return new CSingleLittleKeySegmentMonitor(optional, val, fieldIdx, offset, size);
- }
- virtual int docompare(const void *l, const void *r) const override
- {
- return memcmplittleunsigned(((char *) l) + offset, ((char *) r) + offset, size);
- }
- virtual bool isSigned() const override { return false; }
- virtual bool isLittleEndian() const override { return true; }
- virtual KeySegmentMonitorSerializeType serializeType() const override { return KSMST_CSINGLELITTLEKEYSEGMENTMONITOR; }
- };
- class COverrideableKeySegmentMonitor : public IOverrideableKeySegmentMonitor, public CInterface
- {
- const void *overridden;
- unsigned hash;
- public:
- IMPLEMENT_IINTERFACE
- COverrideableKeySegmentMonitor(IKeySegmentMonitor * _base)
- {
- base.setown(_base);
- overridden = NULL;
- hash = base->queryHashCode();
- hash = FNV_32_HASHONE_VALUE(hash, (byte) 123);
- }
- COverrideableKeySegmentMonitor(MemoryBuffer &mb)
- {
- mb.read(hash);
- base.setown(deserializeKeySegmentMonitor(mb));
- overridden = NULL;
- }
- virtual void setOverrideBuffer(const void *ptr) override
- {
- overridden = ptr;
- }
- virtual unsigned queryHashCode() const override
- {
- return hash;
- }
- virtual bool matchesBuffer(const void *keyval) const override
- {
- if (overridden)
- {
- unsigned offset = base->getOffset();
- return memcmp((char *) keyval+offset, (char *) overridden+offset, base->getSize()) == 0;
- }
- else
- return base->matchesBuffer(keyval);
- }
- virtual bool matches(const RtlRow *keyval) const override
- {
- return matchesBuffer(keyval->queryRow());
- }
- virtual bool increment(void *keyval) const override
- {
- if (overridden)
- {
- // Set to next permitted value above current
- unsigned offset = base->getOffset();
- if (memcmp((char *) keyval+offset, (char *) overridden+offset, base->getSize()) < 0)
- {
- memcpy((char *) keyval+offset, (char *) overridden+offset, base->getSize());
- return true;
- }
- return false;
- }
- else
- return base->increment(keyval);
- }
- virtual void setLow(void *keyval) const override
- {
- if (overridden)
- {
- unsigned offset = base->getOffset();
- memcpy((char *) keyval+offset, (char *) overridden+offset, base->getSize());
- }
- else
- base->setLow(keyval);
- }
- virtual void setHigh(void *keyval) const override
- {
- if (overridden)
- {
- unsigned offset = base->getOffset();
- memcpy((char *) keyval+offset, (char *) overridden+offset, base->getSize());
- }
- else
- base->setHigh(keyval);
- }
- virtual void endRange(void *keyval) const override
- {
- if (overridden)
- {
- unsigned offset = base->getOffset();
- memcpy((char *) keyval+offset, (char *) overridden+offset, base->getSize());
- }
- base->endRange(keyval);
- }
- virtual void copy(void * expandedRow, const void *rawRight) const override
- {
- base->copy(expandedRow, rawRight);
- }
- virtual bool isWild() const override { return overridden ? false : base->isWild(); }
- virtual unsigned getFieldIdx() const override { return base->getFieldIdx(); }
- virtual unsigned getOffset() const override { return base->getOffset(); }
- virtual unsigned getSize() const override { return base->getSize(); }
- virtual bool isEmpty() const override { return base->isEmpty(); }
- virtual bool isSigned() const override { return base->isSigned(); }
- virtual bool isLittleEndian() const override { return base->isLittleEndian(); }
- virtual bool isWellKeyed() const override { return overridden ? true : base->isWellKeyed(); }
- virtual bool isOptional() const override { return base->isOptional(); }
- virtual unsigned numFieldsRequired() const override { return base->numFieldsRequired(); }
- virtual bool isSimple() const override { return base->isSimple(); }
- virtual bool equivalentTo(const IKeySegmentMonitor &other) const override { throwUnexpected(); }
- virtual int docompare(const void * expandedLeft, const void *rawRight) const override { throwUnexpected(); }
- virtual bool setOffset(unsigned _offset) override { throwUnexpected(); }
- virtual MemoryBuffer &serialize(MemoryBuffer &mb) const override { throwUnexpected(); }
- virtual KeySegmentMonitorSerializeType serializeType() const override { throwUnexpected(); }
- virtual IKeySegmentMonitor *clone() const override { throwUnexpected(); }
- protected:
- Owned<IKeySegmentMonitor> base;
- };
- ECLRTL_API IStringSet *createRtlStringSet(size32_t size)
- {
- return createStringSet(size);
- }
- ECLRTL_API IStringSet *createRtlStringSetEx(size32_t size, bool bigEndian, bool isSigned)
- {
- return createStringSet(size, bigEndian, isSigned);
- }
- ECLRTL_API IStringSet * rtlUnionSet(IStringSet * lhs, IStringSet * rhs)
- {
- if (lhs->isEmptySet())
- return LINK(rhs);
- else if (lhs->isFullSet())
- return LINK(lhs);
- if (rhs->isEmptySet())
- return LINK(lhs);
- else if (rhs->isFullSet())
- return LINK(rhs);
- return lhs->unionSet(rhs);
- }
- ECLRTL_API IStringSet * rtlIntersectSet(IStringSet * lhs, IStringSet * rhs)
- {
- if (lhs->isFullSet())
- return LINK(rhs);
- else if (lhs->isEmptySet())
- return LINK(lhs);
- if (rhs->isFullSet())
- return LINK(lhs);
- else if (rhs->isEmptySet())
- return LINK(rhs);
- return lhs->intersectSet(rhs);
- }
- IKeySegmentMonitor *createKeySegmentMonitor(bool optional, IStringSet *set, unsigned _fieldIdx, unsigned _offset, unsigned _size)
- {
- if (!set)
- return new CWildKeySegmentMonitor(_fieldIdx, _offset, _size);
- Owned<IStringSet> removeSet = set; // make sure set is released if optimized out.
- if (set->isSingleValue())
- {
- void *data = alloca(_size);
- set->getTransitionValue(data, 0);
- if (set->isSigned())
- {
- if (set->isBigEndian())
- return createSingleBigSignedKeySegmentMonitor(optional, _fieldIdx, _offset, _size, data);
- else
- return createSingleLittleSignedKeySegmentMonitor(optional, _fieldIdx, _offset, _size, data);
- }
- else
- {
- if (set->isBigEndian())
- return createSingleKeySegmentMonitor(optional, _fieldIdx, _offset, _size, data);
- else
- return createSingleLittleKeySegmentMonitor(optional, _fieldIdx, _offset, _size, data);
- }
- }
- else if (set->isFullSet())
- return new CWildKeySegmentMonitor(_fieldIdx, _offset, _size);
- else
- return new CSetKeySegmentMonitor(optional, removeSet.getClear(), _fieldIdx, _offset, _size);
- }
- ECLRTL_API IStringSet *createRtlStringValue(size32_t size, const char * value)
- {
- IStringSet * set = createStringSet(size);
- set->addRange(value, value);
- return set;
- }
- IKeySegmentMonitor *createWildKeySegmentMonitor(unsigned _fieldIdx, unsigned _offset, unsigned _size)
- {
- return new CWildKeySegmentMonitor(_fieldIdx, _offset, _size);
- }
- IKeySegmentMonitor *createEmptyKeySegmentMonitor(bool optional, unsigned _fieldIdx, unsigned _offset, unsigned _size)
- {
- return new CSetKeySegmentMonitor(optional, createStringSet(_size), _fieldIdx, _offset, _size);
- }
- ECLRTL_API IKeySegmentMonitor *createSingleKeySegmentMonitor(bool optional, unsigned _fieldIdx, unsigned offset, unsigned size, const void * value)
- {
- return new CSingleKeySegmentMonitor(optional, value, _fieldIdx, offset, size);
- }
- ECLRTL_API IOverrideableKeySegmentMonitor *createOverrideableKeySegmentMonitor(IKeySegmentMonitor *base)
- {
- return new COverrideableKeySegmentMonitor(base);
- }
- ECLRTL_API IKeySegmentMonitor *createSingleBigSignedKeySegmentMonitor(bool optional, unsigned fieldIdx, unsigned offset, unsigned size, const void * value)
- {
- return new CSingleBigSignedKeySegmentMonitor(optional, value, fieldIdx, offset, size);
- }
- ECLRTL_API IKeySegmentMonitor *createSingleLittleSignedKeySegmentMonitor(bool optional, unsigned fieldIdx, unsigned offset, unsigned size, const void * value)
- {
- // MORE - common int sizes 1,2,4 (8?) might be better done with dedicated subclasses
- return new CSingleLittleSignedKeySegmentMonitor(optional, value, fieldIdx, offset, size);
- }
- ECLRTL_API IKeySegmentMonitor *createSingleLittleKeySegmentMonitor(bool optional, unsigned fieldIdx, unsigned offset, unsigned size, const void * value)
- {
- // MORE - common int sizes 1,2,4 (8?) might be better done with dedicated subclasses
- return new CSingleLittleKeySegmentMonitor(optional, value, fieldIdx, offset, size);
- }
- ECLRTL_API IKeySegmentMonitor *createDummyKeySegmentMonitor(unsigned _fieldIdx, unsigned _offset, unsigned _size, bool isSigned, bool isLittleEndian)
- {
- if (isSigned)
- if (isLittleEndian)
- return new CSingleLittleSignedKeySegmentMonitor(false, NULL, _fieldIdx, _offset, _size);
- else
- return new CSingleBigSignedKeySegmentMonitor(false, NULL, _fieldIdx, _offset, _size);
- else
- if (isLittleEndian)
- return new CSingleLittleKeySegmentMonitor(false, NULL, _fieldIdx, _offset, _size);
- else
- return new CSingleKeySegmentMonitor(false, NULL, _fieldIdx, _offset, _size);
- }
- ECLRTL_API IKeySegmentMonitor *deserializeKeySegmentMonitor(MemoryBuffer &mb)
- {
- byte typ;
- mb.read(typ);
- switch ((KeySegmentMonitorSerializeType)typ) {
- case KSMST_WILDKEYSEGMENTMONITOR:
- return new CWildKeySegmentMonitor(mb);
- case KSMST_SETKEYSEGMENTMONITOR:
- return new CSetKeySegmentMonitor(mb);
- case KSMST_SINGLEKEYSEGMENTMONITOR:
- return new CSingleKeySegmentMonitor(mb);
- case KSMST_SINGLEBIGSIGNEDKEYSEGMENTMONITOR:
- return new CSingleBigSignedKeySegmentMonitor(mb);
- case KSMST_SINGLELITTLESIGNEDKEYSEGMENTMONITOR:
- return new CSingleLittleSignedKeySegmentMonitor(mb);
- case KSMST_CSINGLELITTLEKEYSEGMENTMONITOR:
- return new CSingleLittleKeySegmentMonitor(mb);
- case KSMST_OVERRIDEABLEKEYSEGMENTMONITOR:
- return new COverrideableKeySegmentMonitor(mb);
- }
- return NULL; // up to caller to check
- }
- enum StringSetSerializeType
- {
- SSST_none,
- SSST_BIGUNSIGNEDSTRINGSET,
- SSST_BIGSIGNEDSTRINGSET,
- SSST_LITTLEUNSIGNEDSTRINGSET,
- SSST_LITTLESIGNEDSTRINGSET,
- SSST_max
- };
- ECLRTL_API int memcmpbigsigned(const void *l, const void *r, unsigned size)
- {
- signed int diff = ((signed char *) l)[0]-((signed char *) r)[0];
- if (diff)
- return diff;
- for(unsigned i = 1; i < size; i++)
- {
- diff = ((unsigned char *) l)[i]-((unsigned char *) r)[i];
- if (diff)
- return diff;
- }
- return 0;
- }
- ECLRTL_API int memcmplittleunsigned(const void *l, const void *r, unsigned size)
- {
- while (size)
- {
- size--;
- int diff = ((unsigned char *) l)[size]-((unsigned char *) r)[size];
- if (diff)
- return diff;
- }
- return 0;
- }
- ECLRTL_API int memcmplittlesigned(const void *l, const void *r, unsigned size)
- {
- size--;
- signed int diff = ((signed char *) l)[size]-((signed char *) r)[size];
- if (diff)
- return diff;
- while (size)
- {
- size--;
- diff = ((unsigned char *) l)[size]-((unsigned char *) r)[size];
- if (diff)
- return diff;
- }
- return 0;
- }
- class CStringSet : implements IStringSet, public CInterface
- {
- protected:
- size32_t size;
- IArrayOf<ITransition> transitions;
- IStringSet *unionOrIntersect(IStringSet *r, bool isUnion);
- virtual CStringSet *createEmptySet() = 0;
- virtual bool decrement(void *val) const = 0;
- virtual bool increment(void *val) const = 0;
- virtual int memcmp(const void *val1, const void *val2, size32_t size) const = 0;
- virtual unsigned getCardinality(const void *val1, const void *val2, size32_t size) const = 0;
- virtual void memset(void *ptr, int val, size32_t size) const = 0;
- virtual bool isLowVal(const void *val) const = 0;
- virtual bool isHighVal(const void *val) const = 0;
- bool oneless(const void *l, const void *r) const;
- void addTransitionAt(const void *val, bool state, unsigned pos);
- void appendTransition(ITransition *t);
- public:
- IMPLEMENT_IINTERFACE;
- CStringSet(size32_t size);
- CStringSet(MemoryBuffer &mb);
- // IStringSet
- virtual void addRange(const void *loval, const void *hival);
- virtual void addAll();
- virtual ITransition *queryTransition(unsigned idx);
- virtual bool getTransitionValue(void *value, unsigned idx);
- virtual void killRange(const void *loval, const void *hival);
- virtual bool inRange(const void *val) const;
- virtual bool inRange(const void *val, unsigned &transition) const;
- virtual size32_t getSize() { return size; };
- virtual void reset();
- virtual unsigned transitionCount();
- virtual IStringSet *invertSet();
- virtual IStringSet *unionSet(IStringSet *);
- virtual IStringSet *intersectSet(IStringSet *);
- virtual const char *describe(StringBuffer &ret);
- virtual bool isEmptySet() const { return transitions.length()==0; }
- virtual bool isFullSet() const
- {
- return transitions.length()==2 &&
- isLowVal(transitions.item(0).getValue()) &&
- isHighVal(transitions.item(1).getValue());
- }
- virtual bool isSingleValue() const
- {
- return transitions.length()==2 &&
- memcmp(transitions.item(0).getValue(), transitions.item(1).getValue(), size) == 0;
- }
- virtual unsigned numValues() const
- {
- unsigned ret = 0;
- unsigned idx = 0;
- while (transitions.isItem(idx+1))
- {
- unsigned thisrange = getCardinality(transitions.item(idx).getValue(), transitions.item(idx+1).getValue(), size);
- if (thisrange + ret < ret)
- return (unsigned) -1;
- ret += thisrange;
- idx += 2;
- }
- return ret;
- }
- virtual MemoryBuffer &serialize(MemoryBuffer &mb) const
- {
- StringSetSerializeType typ = serializeType();
- assertex(typ!=SSST_none);
- mb.append((byte)typ).append(size).append(transitions.ordinality());
- ForEachItemIn(i,transitions) {
- transitions.item(i).serialize(size,mb);
- }
- return mb;
- }
- virtual StringSetSerializeType serializeType() const = 0;
- };
- class CBigUnsignedStringSet : public CStringSet
- {
- protected:
- virtual CStringSet *createEmptySet()
- {
- return new CBigUnsignedStringSet(size);
- }
- virtual bool increment(void *_val) const
- {
- unsigned char *val = (unsigned char *)_val;
- int i = size;
- while (i--)
- {
- val[i]++;
- if (val[i]!=0)
- return true;
- }
- return false;
- }
- virtual bool decrement(void *_val) const
- {
- unsigned char *val = (unsigned char *)_val;
- int i = size;
- while (i--)
- {
- val[i]--;
- if ((unsigned char)val[i]!=0xff)
- return true;
- }
- return false;
- }
- virtual int memcmp(const void *val1, const void *val2, size32_t size) const
- {
- return ::memcmp(val1, val2, size);
- }
- virtual void memset(void *ptr, int val, size32_t size) const
- {
- ::memset(ptr, val, size);
- }
- virtual unsigned getCardinality(const void *val1, const void *val2, size32_t size) const
- {
- unsigned char *p1 = (unsigned char *) val1;
- unsigned char *p2 = (unsigned char *) val2;
- unsigned ret = 1;
- unsigned mult = 1;
- while (size--)
- {
- unsigned diff = p2[size] - p1[size];
- if (diff)
- {
- if (!mult)
- return (unsigned) -1;
- else
- ret += diff * mult;
- }
- if (mult*256 < mult)
- mult = 0;
- else
- mult *= 256;
- }
- return ret;
- }
- virtual bool isHighVal(const void *val) const
- {
- const unsigned char *vval = (const unsigned char *) val;
- for (unsigned i = 0; i < size; i++)
- if (vval[i] != 0xff)
- return false;
- return true;
- }
- virtual bool isLowVal(const void *val) const
- {
- const unsigned char *vval = (const unsigned char *) val;
- for (unsigned i = 0; i < size; i++)
- if (vval[i] != 0x00)
- return false;
- return true;
- }
- virtual bool isSigned() const { return false; }
- virtual bool isBigEndian() const { return true; }
- virtual StringSetSerializeType serializeType() const
- {
- return SSST_BIGUNSIGNEDSTRINGSET;
- }
- public:
- CBigUnsignedStringSet(unsigned size) : CStringSet(size) {}
- CBigUnsignedStringSet(MemoryBuffer &mb) : CStringSet(mb) {}
- };
- class CBigSignedStringSet : public CBigUnsignedStringSet
- {
- protected:
- virtual CStringSet *createEmptySet()
- {
- return new CBigSignedStringSet(size);
- }
- // increment and decrement are same as unsigned
- virtual int memcmp(const void *val1, const void *val2, size32_t size) const
- {
- return ::memcmpbigsigned(val1, val2, size);
- }
- virtual void memset(void *ptr, int val, size32_t size) const
- {
- ::memset(ptr, val, size);
- switch(val)
- {
- case 0:
- *(unsigned char *) ptr = 0x80;
- break;
- case 0xff:
- *(unsigned char *) ptr = 0x7f;
- break;
- default:
- throwUnexpected();
- }
- }
- virtual bool isHighVal(const void *val) const
- {
- const unsigned char *vval = (const unsigned char *) val;
- if (vval[0] != 0x7f)
- return false;
- for (unsigned i = 1; i < size; i++)
- if (vval[i] != 0xff)
- return false;
- return true;
- }
- virtual bool isLowVal(const void *val) const
- {
- const unsigned char *vval = (const unsigned char *) val;
- if (vval[0] != 0x80)
- return false;
- for (unsigned i = 1; i < size; i++)
- if (vval[i] != 0x00)
- return false;
- return true;
- }
- virtual bool isSigned() const { return true; }
- virtual bool isBigEndian() const { return true; }
- virtual StringSetSerializeType serializeType() const
- {
- return SSST_BIGSIGNEDSTRINGSET;
- }
- public:
- CBigSignedStringSet(unsigned size) : CBigUnsignedStringSet(size) {}
- CBigSignedStringSet(MemoryBuffer &mb) : CBigUnsignedStringSet(mb) {}
- };
- class CLittleUnsignedStringSet : public CStringSet
- {
- protected:
- virtual CStringSet *createEmptySet()
- {
- return new CLittleUnsignedStringSet(size);
- }
- virtual bool increment(void *_val) const
- {
- unsigned char *val = (unsigned char *)_val;
- unsigned i = 0;
- while (i < size)
- {
- val[i]++;
- if (val[i]!=0)
- return true;
- i++;
- }
- return false;
- }
- virtual unsigned getCardinality(const void *val1, const void *val2, size32_t size) const
- {
- unsigned char *p1 = (unsigned char *) val1;
- unsigned char *p2 = (unsigned char *) val2;
- unsigned ret = 1;
- unsigned mult = 1;
- unsigned i = 0;
- while (i < size)
- {
- unsigned diff = p2[i] - p1[i];
- if (diff)
- {
- if (!mult)
- return (unsigned) -1;
- else
- ret += diff * mult;
- }
- if (mult*256 < mult)
- mult = 0;
- else
- mult *= 256;
- i++;
- }
- return ret;
- }
- virtual bool decrement(void *_val) const
- {
- unsigned char *val = (unsigned char *)_val;
- unsigned i = 0;
- while (i < size)
- {
- val[i]--;
- if ((unsigned char)val[i]!=0xff)
- return true;
- i++;
- }
- return false;
- }
- virtual int memcmp(const void *val1, const void *val2, size32_t size) const
- {
- return ::memcmplittleunsigned(val1, val2, size);
- }
- virtual void memset(void *ptr, int val, size32_t size) const
- {
- ::memset(ptr, val, size);
- }
- virtual bool isHighVal(const void *val) const
- {
- const unsigned char *vval = (const unsigned char *) val;
- for (unsigned i = 0; i < size; i++)
- if (vval[i] != 0xff)
- return false;
- return true;
- }
- virtual bool isLowVal(const void *val) const
- {
- const unsigned char *vval = (const unsigned char *) val;
- for (unsigned i = 0; i < size; i++)
- if (vval[i] != 0x00)
- return false;
- return true;
- }
- virtual bool isSigned() const { return false; }
- virtual bool isBigEndian() const { return false; }
- virtual StringSetSerializeType serializeType() const
- {
- return SSST_LITTLEUNSIGNEDSTRINGSET;
- }
- public:
- CLittleUnsignedStringSet(unsigned size) : CStringSet(size) {}
- CLittleUnsignedStringSet(MemoryBuffer &mb) : CStringSet(mb) {}
- };
- class CLittleSignedStringSet : public CLittleUnsignedStringSet
- {
- protected:
- virtual CStringSet *createEmptySet()
- {
- return new CLittleSignedStringSet(size);
- }
- // increment and decrement are same as unsigned
- virtual int memcmp(const void *val1, const void *val2, size32_t size) const
- {
- return ::memcmplittlesigned(val1, val2, size);
- }
- virtual void memset(void *ptr, int val, size32_t size) const
- {
- if (size > 1)
- ::memset(ptr, val, size);
- unsigned char *pptr = (unsigned char *) ptr;
- switch(val)
- {
- case 0:
- pptr[size-1] = 0x80;
- break;
- case 0xff:
- pptr[size-1] = 0x7f;
- break;
- default:
- throwUnexpected();
- }
- }
- virtual bool isHighVal(const void *val) const
- {
- const unsigned char *vval = (const unsigned char *) val;
- if (vval[size-1] != 0x7f)
- return false;
- for (unsigned i = 0; i < size-1; i++)
- if (vval[i] != 0xff)
- return false;
- return true;
- }
- virtual bool isLowVal(const void *val) const
- {
- const unsigned char *vval = (const unsigned char *) val;
- if (vval[size-1] != 0x80)
- return false;
- for (unsigned i = 0; i < size-1; i++)
- if (vval[i] != 0x00)
- return false;
- return true;
- }
- virtual bool isSigned() const { return true; }
- virtual bool isBigEndian() const { return false; }
- virtual StringSetSerializeType serializeType() const
- {
- return SSST_LITTLESIGNEDSTRINGSET;
- }
- public:
- CLittleSignedStringSet(unsigned size) : CLittleUnsignedStringSet(size) {}
- CLittleSignedStringSet(MemoryBuffer &mb) : CLittleUnsignedStringSet(mb) {}
- };
- class CTransition : implements ITransition, public CInterface
- {
- private:
- bool state; // note: should move before ITransition to pack better in 64bit
- const void *val;
- public:
- IMPLEMENT_IINTERFACE;
- CTransition(const void *_val, bool _state)
- {
- val = _val;
- state = _state;
- }
- CTransition(MemoryBuffer &mb,size32_t size)
- {
- mb.read(state);
- val = malloc(size);
- memcpy((void *)val,mb.readDirect(size),size);
- }
- ~CTransition() { free((void *) val); }
- // ITransition
- bool getState() const { return state; }
- const void *getValue() const { return val; }
- MemoryBuffer &serialize(size32_t size, MemoryBuffer &mb) const
- {
- mb.append(state);
- memcpy(mb.reserve(size),val,size);
- return mb;
- }
- bool canSerialize() const { return true; }
- };
- //======================================================================================
- CStringSet::CStringSet(size32_t _size)
- {
- size = _size;
- }
- CStringSet::CStringSet(MemoryBuffer &mb)
- {
- mb.read(size);
- unsigned n;
- mb.read(n);
- while(n--)
- transitions.append(*new CTransition(mb,size));
- }
- void CStringSet::reset()
- {
- transitions.kill();
- }
- bool CStringSet::oneless(const void *l, const void *r) const
- {
- // MORE - would be more efficient to make this virtual like the memcmp...
- void *t = alloca(size);
- memcpy(t, r, size);
- decrement(t);
- return memcmp(l, t, size)==0;
- }
- unsigned CStringSet::transitionCount()
- {
- return transitions.ordinality();
- }
- void CStringSet::addTransitionAt(const void *val, bool state, unsigned pos)
- {
- void *newval = malloc(size);
- memcpy(newval, val, size);
- transitions.add(* new CTransition(newval, state), pos);
- }
- void CStringSet::appendTransition(ITransition *t)
- {
- if (t->getState() && transitions.length())
- {
- unsigned lastidx = transitions.length()-1;
- ITransition &prev = transitions.item(lastidx);
- assertex(prev.getState()==!t->getState());
- if (oneless(prev.getValue(), t->getValue()))
- {
- transitions.remove(lastidx);
- t->Release();
- return;
- }
- }
- transitions.append(*t);
- }
- void CStringSet::addRange(const void *loval, const void *hival)
- {
- if (!loval)
- {
- void *x = alloca(size);
- memset(x, 0, size);
- loval = x;
- }
- if (!hival)
- {
- void *x = alloca(size);
- memset(x, 0xff, size);
- hival = x;
- }
- if (memcmp(loval, hival, size) > 0)
- return;
- unsigned idx;
- bool inset = false;
- int b = transitions.ordinality();
- if (!b)
- {
- addTransitionAt(loval, true, 0);
- addTransitionAt(hival, false, 1);
- return;
- }
- else
- {
- // binchop to find last transition > val...
- unsigned int a = 0;
- int rc;
- while ((int)a<b)
- {
- int i = a+(b+1-a)/2;
- rc = memcmp(loval, transitions.item(i-1).getValue(), size);
- if (rc>0)
- a = i;
- else
- b = i-1;
- }
- if (a>0)
- {
- idx = a;
- ITransition &t = transitions.item(idx-1);
- if(!t.getState())
- {
- if (oneless(t.getValue(), loval))
- transitions.remove(--idx);
- else
- addTransitionAt(loval, true, idx++);
- }
- else
- inset = true;
- }
- else
- {
- addTransitionAt(loval, true, 0);
- idx = 1;
- }
- }
- while (transitions.isItem(idx))
- {
- ITransition &t = transitions.item(idx);
- int diff = memcmp(t.getValue(), hival, size);
- if (diff <= 0)
- {
- inset = t.getState();
- transitions.remove(idx);
- }
- else
- break;
- }
- if (!inset)
- {
- if (transitions.isItem(idx))
- {
- ITransition &t = transitions.item(idx);
- assertex(t.getState());
- if (oneless(hival, t.getValue()))
- {
- transitions.remove(idx);
- return;
- }
- }
- addTransitionAt(hival, false, idx);
- }
- }
- void CStringSet::killRange(const void *loval, const void *hival)
- {
- if (!loval)
- {
- void *x = alloca(size);
- memset(x, 0, size);
- loval = x;
- }
- if (!hival)
- {
- void *x = alloca(size);
- memset(x, 0xff, size);
- hival = x;
- }
- assertex(memcmp(loval, hival, size) <= 0);
- bool inset = false;
- ForEachItemIn(idx, transitions)
- {
- ITransition &t = transitions.item(idx);
- int diff = memcmp(t.getValue(), loval, size);
- if (diff < 0)
- inset = t.getState();
- else
- break;
- }
- if (inset)
- {
- void *nlo = alloca(size);
- memcpy(nlo, loval, size);
- decrement(nlo);
- addTransitionAt(nlo, false, idx++);
- }
- while (transitions.isItem(idx))
- {
- ITransition &t = transitions.item(idx);
- int diff = memcmp(t.getValue(), hival, size);
- if (diff <= 0)
- {
- inset = t.getState();
- transitions.remove(idx);
- }
- else
- break;
- }
- if (inset)
- {
- void *nhi = alloca(size);
- memcpy(nhi, hival, size);
- increment(nhi);
- addTransitionAt(nhi, true, idx);
- }
- }
- void CStringSet::addAll()
- {
- reset();
- void *val = alloca(size);
- memset(val, 0, size);
- addTransitionAt(val, true, 0);
- memset(val, 0xff, size);
- addTransitionAt(val, false, 1);
- }
- const char *CStringSet::describe(StringBuffer &ret)
- {
- ret.append('[');
- ForEachItemIn(idx, transitions)
- {
- ITransition &t = transitions.item(idx);
- if (t.getState())
- {
- if (idx)
- ret.append(',');
- }
- else
- ret.append("..");
- appendURL(&ret, (char *) t.getValue(), size, true);
- }
- ret.append(']');
- return ret.str();
- }
- bool CStringSet::inRange(const void *val) const
- {
- unsigned nextTransition;
- return inRange(val, nextTransition);
- }
- bool CStringSet::inRange(const void *val, unsigned &nextTransition) const
- {
- int b = transitions.ordinality();
- if (!b)
- {
- nextTransition = (unsigned) -1;
- return false;
- }
- else if (b >= 4)
- {
- // binchop to find last transition >= val...
- unsigned int a = 0;
- int rc;
- while ((int)a<b)
- {
- int i = a+(b+1-a)/2;
- rc = memcmp(val, transitions.item(i-1).getValue(), size);
- if (rc>=0)
- a = i;
- else
- b = i-1;
- }
- if (a>0)
- {
- nextTransition = (a>=transitions.ordinality())? (unsigned) -1: a; // a is first transition that is > val
- a--;
- if (transitions.item(a).getState())
- return true;
- if (memcmp(val, transitions.item(a).getValue(), size)==0)
- {
- nextTransition = a;
- return true;
- }
- return false;
- }
- else
- {
- nextTransition = 0;
- return false;
- }
- }
- else
- {
- bool inset = false;
- ForEachItemIn(idx, transitions)
- {
- ITransition &t = transitions.item(idx);
- int diff = memcmp(t.getValue(), val, size);
- if (t.getState())
- {
- if (diff <= 0)
- inset = true;
- if (diff == 0)
- {
- idx++;
- break;
- }
- else if (diff > 0)
- break;
- }
- else
- {
- if (diff >= 0)
- break;
- if (diff < 0)
- inset = false;
- }
- }
- nextTransition = (idx>=transitions.ordinality())? (unsigned) -1: idx;
- return inset;
- }
- }
- IStringSet *CStringSet::unionOrIntersect(IStringSet *r, bool isUnion)
- {
- bool inA = false;
- bool inB = false;
- bool state = false;
- assertex(r->getSize()==size);
- int idxA = 0;
- int idxB = 0;
- ITransition *tA = queryTransition(idxA);
- ITransition *tB = r->queryTransition(idxB);
- CStringSet *result = createEmptySet();
- for (;;)
- {
- int diff;
- if (tA == NULL)
- {
- if (tB == NULL)
- break;
- else
- diff = 1;
- }
- else if (tB == NULL)
- diff = -1;
- else
- diff = memcmp(tA->getValue(), tB->getValue(), size);
- ITransition *t = NULL;
- if (!diff)
- {
- diff = (int) tB->getState() - (int) tA->getState(); // leading edge sorts before trailing edge for intersect...
- if (isUnion)
- diff = -diff; // trailing edge sorts before leading edge for union...
- }
- if (diff <= 0)
- {
- inA = tA->getState();
- t = tA;
- idxA++;
- tA = queryTransition(idxA);
- }
- if (diff >= 0)
- {
- inB = tB->getState();
- t = tB;
- idxB++;
- tB = r->queryTransition(idxB);
- }
- bool newState;
- if (isUnion)
- newState = inA || inB;
- else
- newState = inA && inB;
- if (newState != state)
- {
- state = newState;
- t->Link();
- result->appendTransition(t);
- }
- }
- return result;
- }
- IStringSet *CStringSet::invertSet()
- {
- CStringSet *result = createEmptySet();
- result->addAll();
- bool inset = false;
- void *loval = alloca(size);
- void *hival = alloca(size);
- memset(loval, 0, size);
- ForEachItemIn(idx, transitions)
- {
- ITransition &t = transitions.item(idx);
- assertex(t.getState() == !inset);
- if (inset)
- {
- memcpy(hival, t.getValue(), size);
- result->killRange(loval, hival);
- }
- else
- memcpy(loval, t.getValue(), size);
- inset = t.getState();
- }
- if (inset)
- {
- memset(hival, 0xff, size);
- result->killRange(loval, hival);
- }
- return result;
- }
- IStringSet *CStringSet::unionSet(IStringSet *other)
- {
- return unionOrIntersect(other, true);
- }
- IStringSet *CStringSet::intersectSet(IStringSet *other)
- {
- return unionOrIntersect(other, false);
- }
- ITransition *CStringSet::queryTransition(unsigned int idx)
- {
- if (transitions.isItem(idx))
- {
- ITransition *t = &transitions.item(idx);
- return t;
- }
- else
- return NULL;
- }
- bool CStringSet::getTransitionValue(void *value, unsigned int idx)
- {
- if (idx == (unsigned) -1 || idx >= transitions.ordinality()) return false;
- ITransition &t = transitions.item(idx);
- memcpy(value, t.getValue(), size);
- return true;
- }
- IStringSet *createStringSet(size32_t size)
- {
- return new CBigUnsignedStringSet(size);
- }
- IStringSet *createStringSet(size32_t size, bool bigEndian, bool isSigned)
- {
- if (bigEndian)
- {
- if (isSigned)
- return new CBigSignedStringSet(size);
- else
- return new CBigUnsignedStringSet(size);
- }
- else
- {
- if (isSigned)
- return new CLittleSignedStringSet(size);
- else
- return new CLittleUnsignedStringSet(size);
- }
- }
- ECLRTL_API IStringSet *deserializeStringSet(MemoryBuffer &mb)
- {
- byte typ;
- mb.read(typ);
- switch((StringSetSerializeType)typ) {
- case SSST_BIGUNSIGNEDSTRINGSET:
- return new CBigUnsignedStringSet(mb);
- case SSST_BIGSIGNEDSTRINGSET:
- return new CBigSignedStringSet(mb);
- case SSST_LITTLEUNSIGNEDSTRINGSET:
- return new CLittleUnsignedStringSet(mb);
- case SSST_LITTLESIGNEDSTRINGSET:
- return new CLittleSignedStringSet(mb);
- }
- return NULL; // up to caller to check
- };
- //---------------------------------------------------------------------------------------------------------------------
- class LegacySetCreator : implements ISetCreator
- {
- public:
- LegacySetCreator(IStringSet & _set, size32_t _minRecordSize, const RtlTypeInfo * _fieldType)
- : set(_set), minRecordSize(_minRecordSize), fieldType(_fieldType) {}
- virtual void addRange(TransitionMask lowerMask, const StringBuffer & lowerString, TransitionMask upperMask, const StringBuffer & upperString) override
- {
- MemoryBufferBuilder lobuilder(lobuffer.clear(), minRecordSize);
- fieldType->buildUtf8(lobuilder, 0, nullptr, lowerString.length(), lowerString.str());
- MemoryBufferBuilder hibuilder(hibuffer.clear(), minRecordSize);
- fieldType->buildUtf8(hibuilder, 0, nullptr, upperString.length(), upperString.str());
- set.addRange(lobuffer.toByteArray(), hibuffer.toByteArray());
- if (!(lowerMask & CMPeq))
- set.killRange(lobuffer.toByteArray(), lobuffer.toByteArray());
- if (!(upperMask & CMPeq))
- set.killRange(hibuffer.toByteArray(), hibuffer.toByteArray());
- }
- protected:
- IStringSet & set;
- const RtlTypeInfo *fieldType;
- size32_t minRecordSize;
- MemoryBuffer lobuffer;
- MemoryBuffer hibuffer;
- };
- void deserializeSet(IStringSet & set, size32_t minRecordSize, const RtlTypeInfo * fieldType, const char * filter)
- {
- LegacySetCreator creator(set, minRecordSize, fieldType);
- deserializeSet(creator, filter);
- }
- #ifdef _USE_CPPUNIT
- #include <cppunit/extensions/HelperMacros.h>
- /*
- class IStdException : extends std::exception
- {
- Owned<IException> jException;
- public:
- IStdException(IException *E) : jException(E) {};
- };
- */
- class SegmentMonitorTest : public CppUnit::TestFixture
- {
- CPPUNIT_TEST_SUITE( SegmentMonitorTest );
- CPPUNIT_TEST(testOptional);
- CPPUNIT_TEST_SUITE_END();
- protected:
- void testOptional()
- {
- Owned<IKeySegmentMonitor> wild0_20 = createWildKeySegmentMonitor(0, 0, 20);
- Owned<IKeySegmentMonitor> wild10_10 = createWildKeySegmentMonitor(1, 10,10);
- Owned<IStringSet> abcdef = createStringSet(10);
- abcdef->addRange("ABCDEFGHIJ", "ABCDEFGHIJ");
- Owned<IKeySegmentMonitor> opt0_20 = createSingleKeySegmentMonitor(true, 0, 0,20, "abcdefghijklmnopqrst");
- Owned<IKeySegmentMonitor> opt20_10 = createKeySegmentMonitor(true, LINK(abcdef), 1, 20, 10);
- Owned<IKeySegmentMonitor> opt30_10 = createSingleKeySegmentMonitor(true, 2, 30, 10, "KLMNOPQRST");
- Owned<IKeySegmentMonitor> nonOpt0_10 = createSingleKeySegmentMonitor(false, 0, 0,10, "abcdefghij");
- Owned<IKeySegmentMonitor> nonOpt0_20 = createSingleKeySegmentMonitor(false, 0, 0,20, "abcdefghijklmnopqrst");
- Owned<IKeySegmentMonitor> nonOpt20_10 = createKeySegmentMonitor(false, LINK(abcdef), 1, 20, 10);
- Owned<IKeySegmentMonitor> nonOpt30_10 = createSingleKeySegmentMonitor(false, 2, 30, 10, "KLMNOPQRST");
- CPPUNIT_ASSERT(wild0_20->isOptional());
- CPPUNIT_ASSERT(opt20_10->isOptional());
- CPPUNIT_ASSERT(opt30_10->isOptional());
- CPPUNIT_ASSERT(!nonOpt0_10->isOptional());
- CPPUNIT_ASSERT(!nonOpt0_20->isOptional());
- CPPUNIT_ASSERT(!nonOpt20_10->isOptional());
- CPPUNIT_ASSERT(!nonOpt30_10->isOptional());
- #if 0
- IKeySegmentMonitorArray segments;
- segments.append(*LINK(wild0_20));
- segments.append(*LINK(opt20_10));
-
- CPPUNIT_ASSERT(segments.ordinality() == 1);
- CPPUNIT_ASSERT(segments.item(0).isWild());
- CPPUNIT_ASSERT(segments.item(0).getOffset() == 0);
- CPPUNIT_ASSERT(segments.item(0).getSize() == 30);
- segments.kill();
- segments.append(*LINK(wild0_20));
- segments.append(*LINK(opt20_10));
- segments.append(*LINK(nonOpt30_10));
- CPPUNIT_ASSERT(segments.ordinality() == 2);
- CPPUNIT_ASSERT(segments.item(0).isWild());
- CPPUNIT_ASSERT(segments.item(0).getOffset() == 0);
- CPPUNIT_ASSERT(segments.item(0).getSize() == 30);
- CPPUNIT_ASSERT(!segments.item(1).isWild());
- CPPUNIT_ASSERT(segments.item(1).getOffset() == 30);
- CPPUNIT_ASSERT(segments.item(1).getSize() == 10);
- segments.kill();
- segments.append(*LINK(nonOpt0_20));
- segments.append(*LINK(opt20_10));
- segments.append(*LINK(nonOpt30_10));
- CPPUNIT_ASSERT(segments.ordinality() == 3);
- CPPUNIT_ASSERT(!segments.item(1).isWild());
- CPPUNIT_ASSERT(segments.item(1).getOffset() == 20);
- CPPUNIT_ASSERT(segments.item(1).getSize() == 10);
- segments.kill();
- segments.append(*LINK(nonOpt0_10));
- segments.append(*LINK(wild10_10));
- segments.append(*LINK(opt20_10));
- segments.append(*LINK(nonOpt30_10));
- CPPUNIT_ASSERT(segments.ordinality() == 3);
- CPPUNIT_ASSERT(!segments.item(0).isWild());
- CPPUNIT_ASSERT(segments.item(1).isWild());
- CPPUNIT_ASSERT(segments.item(1).getOffset() == 10);
- CPPUNIT_ASSERT(segments.item(1).getSize() == 20);
- segments.kill();
- segments.append(*LINK(opt0_20));
- segments.append(*LINK(opt20_10));
- segments.append(*LINK(nonOpt30_10));
- CPPUNIT_ASSERT(segments.ordinality() == 3);
- CPPUNIT_ASSERT(!segments.item(0).isWild());
- CPPUNIT_ASSERT(!segments.item(1).isWild());
- CPPUNIT_ASSERT(segments.item(1).getOffset() == 20);
- CPPUNIT_ASSERT(segments.item(1).getSize() == 10);
- #endif
- }
- };
- CPPUNIT_TEST_SUITE_REGISTRATION( SegmentMonitorTest );
- CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( SegmentMonitorTest, "SegmentMonitorTest" );
- #endif
|