generics.collections.pas 116 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481
  1. {
  2. This file is part of the Free Pascal/NewPascal run time library.
  3. Copyright (c) 2014 by Maciej Izak (hnb)
  4. member of the NewPascal development team (http://newpascal.org)
  5. Copyright(c) 2004-2018 DaThoX
  6. It contains the generics collections library
  7. See the file COPYING.FPC, included in this distribution,
  8. for details about the copyright.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  12. Acknowledgment
  13. Thanks to Sphere 10 Software (http://sphere10.com) for sponsoring
  14. many new types and major refactoring of entire library
  15. Thanks to mORMot (http://synopse.info) project for the best implementations
  16. of hashing functions like crc32c and xxHash32 :)
  17. **********************************************************************}
  18. {$IFNDEF FPC_DOTTEDUNITS}
  19. unit Generics.Collections;
  20. {$ENDIF}
  21. {$MODE DELPHI}{$H+}
  22. {$MACRO ON}
  23. {$COPERATORS ON}
  24. {$DEFINE CUSTOM_DICTIONARY_CONSTRAINTS := TKey, TValue, THashFactory}
  25. {$DEFINE OPEN_ADDRESSING_CONSTRAINTS := TKey, TValue, THashFactory, TProbeSequence}
  26. {$DEFINE CUCKOO_CONSTRAINTS := TKey, TValue, THashFactory, TCuckooCfg}
  27. {$DEFINE TREE_CONSTRAINTS := TKey, TValue, TInfo}
  28. {$WARNINGS OFF}
  29. {$HINTS OFF}
  30. {$NOTES OFF}
  31. {$OVERFLOWCHECKS OFF}
  32. {$RANGECHECKS OFF}
  33. {$POINTERMATH ON}
  34. interface
  35. {$IFDEF FPC_DOTTEDUNITS}
  36. uses
  37. System.RtlConsts, System.Classes, System.SysUtils, System.Generics.MemoryExpanders, System.Generics.Defaults,
  38. System.Generics.Helpers, System.Generics.Strings, System.Types, System.Rtti;
  39. {$ELSE FPC_DOTTEDUNITS}
  40. uses
  41. RtlConsts, Classes, SysUtils, Generics.MemoryExpanders, Generics.Defaults,
  42. Generics.Helpers, Generics.Strings, Types, Rtti;
  43. {$ENDIF FPC_DOTTEDUNITS}
  44. {.$define EXTRA_WARNINGS}
  45. {.$define ENABLE_METHODS_WITH_TEnumerableWithPointers}
  46. type
  47. EAVLTree = class(Exception);
  48. EIndexedAVLTree = class(EAVLTree);
  49. TDuplicates = {$IFDEF FPC_DOTTEDUNITS}System.{$ENDIF}Classes.TDuplicates;
  50. // bug #24254 workaround
  51. // should be TArray = record class procedure Sort<T>(...) etc.
  52. TBinarySearchResult = record
  53. FoundIndex, CandidateIndex: SizeInt;
  54. CompareResult: SizeInt;
  55. end;
  56. TCustomArrayHelper<T> = class abstract
  57. private
  58. type
  59. // bug #24282
  60. TComparerBugHack = TComparer<T>;
  61. protected
  62. class procedure QuickSort(var AValues: array of T; ALeft, ARight: SizeInt; const AComparer: IComparer<T>);
  63. virtual; abstract;
  64. public
  65. class procedure Sort(var AValues: array of T); overload;
  66. class procedure Sort(var AValues: array of T;
  67. const AComparer: IComparer<T>); overload;
  68. class procedure Sort(var AValues: array of T;
  69. const AComparer: IComparer<T>; AIndex, ACount: SizeInt); overload;
  70. class function BinarySearch(const AValues: array of T; const AItem: T;
  71. out ASearchResult: TBinarySearchResult; const AComparer: IComparer<T>;
  72. AIndex, ACount: SizeInt): Boolean; virtual; abstract; overload;
  73. class function BinarySearch(const AValues: array of T; const AItem: T;
  74. out AFoundIndex: SizeInt; const AComparer: IComparer<T>;
  75. AIndex, ACount: SizeInt): Boolean; virtual; abstract; overload;
  76. class function BinarySearch(const AValues: array of T; const AItem: T;
  77. out AFoundIndex: SizeInt; const AComparer: IComparer<T>): Boolean; overload;
  78. class function BinarySearch(const AValues: array of T; const AItem: T;
  79. out AFoundIndex: SizeInt): Boolean; overload;
  80. class function BinarySearch(const AValues: array of T; const AItem: T;
  81. out ASearchResult: TBinarySearchResult; const AComparer: IComparer<T>): Boolean; overload;
  82. class function BinarySearch(const AValues: array of T; const AItem: T;
  83. out ASearchResult: TBinarySearchResult): Boolean; overload;
  84. end {$ifdef EXTRA_WARNINGS}experimental{$endif}; // will be renamed to TCustomArray (bug #24254)
  85. TArrayHelper<T> = class(TCustomArrayHelper<T>)
  86. private
  87. type
  88. PT = ^T;
  89. class procedure QSort(p: PT; n, reasonable: SizeUint; const cmp: IComparer<T>); static;
  90. class function Median(p: PT; n: SizeUint; const cmp: IComparer<T>): PT; static;
  91. class procedure HeapSort(p: PT; n: SizeUint; const cmp: IComparer<T>); static;
  92. class procedure HeapReplacePessimistic(q: PT; nq, id: SizeUint; const item: T; const cmp: IComparer<T>); static;
  93. protected
  94. class procedure QuickSort(var AValues: array of T; ALeft, ARight: SizeInt; const AComparer: IComparer<T>); override;
  95. public
  96. class function BinarySearch(const AValues: array of T; const AItem: T;
  97. out ASearchResult: TBinarySearchResult; const AComparer: IComparer<T>;
  98. AIndex, ACount: SizeInt): Boolean; override; overload;
  99. class function BinarySearch(const AValues: array of T; const AItem: T;
  100. out AFoundIndex: SizeInt; const AComparer: IComparer<T>;
  101. AIndex, ACount: SizeInt): Boolean; override; overload;
  102. class function Concat(const Args: array of TArray<T>): TArray<T>; static;
  103. class procedure Copy(const aSource: array of T; var aDestination: array of T; aCount: NativeInt); overload;
  104. class procedure Copy(const aSource: array of T; var aDestination: array of T; aSourceIndex, aDestIndex, aCount: SizeInt); overload;
  105. end {$ifdef EXTRA_WARNINGS}experimental{$endif}; // will be renamed to TArray (bug #24254)
  106. TCollectionNotification = (cnAdding, cnAdded, cnDeleting, cnRemoved, cnExtracting, cnExtracted);
  107. TCollectionNotifyEvent<T> = procedure(ASender: TObject; const AItem: T; AAction: TCollectionNotification)
  108. of object;
  109. { TEnumerator }
  110. TEnumerator<T> = class abstract
  111. protected
  112. function DoGetCurrent: T; virtual; abstract;
  113. function DoMoveNext: boolean; virtual;
  114. public
  115. property Current: T read DoGetCurrent;
  116. function MoveNext: boolean;
  117. end;
  118. { TEnumerable }
  119. TEnumerable<T> = class abstract
  120. public type
  121. PT = ^T;
  122. protected // no forward generics declarations (needed by TPointersCollection<T, PT>), this should be moved into TEnumerableWithPointers
  123. function GetPtrEnumerator: TEnumerator<PT>; virtual; abstract;
  124. protected
  125. function ToArrayImpl(ACount: SizeInt): TArray<T>; overload; // used by descendants
  126. protected
  127. function DoGetEnumerator: TEnumerator<T>; virtual; abstract;
  128. public
  129. function GetEnumerator: TEnumerator<T>; inline;
  130. function ToArray: TArray<T>; virtual; overload;
  131. end;
  132. // error: no memory left for TCustomPointersEnumerator<PT> version
  133. TCustomPointersEnumerator<T, PT> = class abstract(TEnumerator<PT>);
  134. TCustomPointersCollection<T, PT> = object
  135. strict private type
  136. TLocalEnumerable = TEnumerable<T>; // compiler has bug for directly usage of TEnumerable<T>
  137. protected
  138. function Enumerable: TLocalEnumerable; inline;
  139. public
  140. function GetEnumerator: TEnumerator<PT>;
  141. end;
  142. TEnumerableWithPointers<T> = class(TEnumerable<T>)
  143. strict private type
  144. TPointersCollection = TCustomPointersCollection<T, PT>;
  145. PPointersCollection = ^TPointersCollection;
  146. private
  147. function GetPtr: PPointersCollection; inline;
  148. public
  149. property Ptr: PPointersCollection read GetPtr;
  150. end;
  151. // More info: http://stackoverflow.com/questions/5232198/about-vectors-growth
  152. // TODO: custom memory managers (as constraints)
  153. {$DEFINE CUSTOM_LIST_CAPACITY_INC := Result + Result div 2} // ~approximation to golden ratio: n = n * 1.5 }
  154. // {$DEFINE CUSTOM_LIST_CAPACITY_INC := Result * 2} // standard inc
  155. TCustomList<T> = class abstract(TEnumerableWithPointers<T>)
  156. public type
  157. PT = ^T;
  158. protected
  159. type // bug #24282
  160. TArrayHelperBugHack = TArrayHelper<T>;
  161. TArrayOfT = array of T;
  162. private
  163. FOnNotify: TCollectionNotifyEvent<T>;
  164. function GetCapacity: SizeInt; inline;
  165. protected
  166. FLength: SizeInt;
  167. FItems: TArrayOfT;
  168. function PrepareAddingItem: SizeInt; virtual;
  169. function PrepareAddingRange(ACount: SizeInt): SizeInt; virtual;
  170. procedure Notify(const AValue: T; ACollectionNotification: TCollectionNotification); virtual;
  171. function DoRemove(AIndex: SizeInt; ACollectionNotification: TCollectionNotification): T; virtual;
  172. procedure SetCapacity(AValue: SizeInt); virtual; abstract;
  173. function GetCount: SizeInt; virtual;
  174. public
  175. function ToArray: TArray<T>; override; final;
  176. property Count: SizeInt read GetCount;
  177. property Capacity: SizeInt read GetCapacity write SetCapacity;
  178. property List: TArrayOfT read FItems;
  179. property OnNotify: TCollectionNotifyEvent<T> read FOnNotify write FOnNotify;
  180. procedure TrimExcess; virtual; abstract;
  181. end;
  182. TCustomListEnumerator<T> = class abstract(TEnumerator<T>)
  183. private
  184. FList: TCustomList<T>;
  185. FIndex: SizeInt;
  186. protected
  187. function DoMoveNext: boolean; override;
  188. function DoGetCurrent: T; override;
  189. function GetCurrent: T; virtual;
  190. public
  191. constructor Create(AList: TCustomList<T>);
  192. end;
  193. TCustomListWithPointers<T> = class(TCustomList<T>)
  194. public type
  195. TPointersEnumerator = class(TCustomPointersEnumerator<T, PT>)
  196. protected
  197. FList: TCustomListWithPointers<T>;
  198. FIndex: SizeInt;
  199. function DoMoveNext: boolean; override;
  200. function DoGetCurrent: PT; override;
  201. public
  202. constructor Create(AList: TCustomListWithPointers<T>);
  203. end;
  204. protected
  205. function GetPtrEnumerator: TEnumerator<PT>; override;
  206. end;
  207. TList<T> = class(TCustomListWithPointers<T>)
  208. private var
  209. FComparer: IComparer<T>;
  210. protected
  211. // bug #24287 - workaround for generics type name conflict (Identifier not found)
  212. // next bug workaround - for another error related to previous workaround
  213. // change order (method must be declared before TEnumerator declaration)
  214. function DoGetEnumerator: {Generics.Collections.}TEnumerator<T>; override;
  215. public
  216. // with this type declaration i found #24285, #24285
  217. type
  218. // bug workaround
  219. TEnumerator = class(TCustomListEnumerator<T>);
  220. TEmptyFunc = reference to function (const L, R: T): Boolean;
  221. function GetEnumerator: TEnumerator; reintroduce;
  222. protected
  223. procedure SetCapacity(AValue: SizeInt); override;
  224. procedure SetCount(AValue: SizeInt);
  225. procedure InitializeList; virtual;
  226. procedure InternalInsert(AIndex: SizeInt; const AValue: T);
  227. private
  228. function GetItem(AIndex: SizeInt): T;
  229. procedure SetItem(AIndex: SizeInt; const AValue: T);
  230. public
  231. constructor Create; overload;
  232. constructor Create(const AComparer: IComparer<T>); overload;
  233. constructor Create(ACollection: TEnumerable<T>); overload;
  234. constructor Create(aValues : Array of T); overload;
  235. {$IFDEF ENABLE_METHODS_WITH_TEnumerableWithPointers}
  236. constructor Create(ACollection: TEnumerableWithPointers<T>); overload;
  237. {$ENDIF}
  238. destructor Destroy; override;
  239. function Add(const AValue: T): SizeInt; virtual;
  240. procedure AddRange(const AValues: array of T); virtual; overload;
  241. procedure AddRange(const AEnumerable: IEnumerable<T>); overload;
  242. procedure AddRange(AEnumerable: TEnumerable<T>); overload;
  243. {$IFDEF ENABLE_METHODS_WITH_TEnumerableWithPointers}
  244. procedure AddRange(AEnumerable: TEnumerableWithPointers<T>); overload;
  245. {$ENDIF}
  246. procedure Insert(AIndex: SizeInt; const AValue: T); virtual;
  247. procedure InsertRange(AIndex: SizeInt; const AValues: array of T); virtual; overload;
  248. procedure InsertRange(AIndex: SizeInt; const AEnumerable: IEnumerable<T>); overload;
  249. procedure InsertRange(AIndex: SizeInt; const AEnumerable: TEnumerable<T>); overload;
  250. {$IFDEF ENABLE_METHODS_WITH_TEnumerableWithPointers}
  251. procedure InsertRange(AIndex: SizeInt; const AEnumerable: TEnumerableWithPointers<T>); overload;
  252. {$ENDIF}
  253. procedure Pack; overload;
  254. procedure Pack(const IsEmpty: TEmptyFunc); overload;
  255. function Remove(const AValue: T): SizeInt;
  256. function RemoveItem(const Value: T; Direction: TDirection): SizeInt;
  257. procedure Delete(AIndex: SizeInt); inline;
  258. procedure DeleteRange(AIndex, ACount: SizeInt);
  259. function ExtractIndex(const AIndex: SizeInt): T; overload;
  260. Function ExtractAt(const AIndex: SizeInt): T; inline;
  261. function Extract(const AValue: T): T; overload;
  262. procedure Exchange(AIndex1, AIndex2: SizeInt); virtual;
  263. procedure Move(AIndex, ANewIndex: SizeInt); virtual;
  264. function First: T; inline;
  265. function Last: T; inline;
  266. procedure Clear;
  267. function Contains(const AValue: T): Boolean; inline;
  268. function IndexOf(const AValue: T): SizeInt; virtual;
  269. function LastIndexOf(const AValue: T): SizeInt; virtual;
  270. procedure Reverse;
  271. procedure TrimExcess; override;
  272. procedure Sort; overload;
  273. procedure Sort(const AComparer: IComparer<T>); overload;
  274. function BinarySearch(const AItem: T; out AIndex: SizeInt): Boolean; overload;
  275. function BinarySearch(const AItem: T; out AIndex: SizeInt; const AComparer: IComparer<T>): Boolean; overload;
  276. property Count: SizeInt read FLength write SetCount;
  277. property Items[Index: SizeInt]: T read GetItem write SetItem; default;
  278. end;
  279. TCollectionSortStyle = (cssNone,cssUser,cssAuto);
  280. TCollectionSortStyles = Set of TCollectionSortStyle;
  281. TSortedList<T> = class(TList<T>)
  282. private
  283. FDuplicates: TDuplicates;
  284. FSortStyle: TCollectionSortStyle;
  285. function GetSorted: boolean;
  286. procedure SetSorted(AValue: boolean);
  287. procedure SetSortStyle(AValue: TCollectionSortStyle);
  288. protected
  289. procedure InitializeList; override;
  290. public
  291. function Add(const AValue: T): SizeInt; override; overload;
  292. procedure AddRange(const AValues: array of T); override; overload;
  293. procedure Insert(AIndex: SizeInt; const AValue: T); override;
  294. procedure Exchange(AIndex1, AIndex2: SizeInt); override;
  295. procedure Move(AIndex, ANewIndex: SizeInt); override;
  296. procedure InsertRange(AIndex: SizeInt; const AValues: array of T); override; overload;
  297. property Duplicates: TDuplicates read FDuplicates write FDuplicates;
  298. property Sorted: Boolean read GetSorted write SetSorted;
  299. property SortStyle: TCollectionSortStyle read FSortStyle write SetSortStyle;
  300. function ConsistencyCheck(ARaiseException: boolean = true): boolean; virtual;
  301. end;
  302. TThreadList<T> = class
  303. private
  304. FList: TList<T>;
  305. FDuplicates: TDuplicates;
  306. FLock: TRTLCriticalSection;
  307. public
  308. constructor Create;
  309. destructor Destroy; override;
  310. procedure Add(const AValue: T);
  311. procedure Remove(const AValue: T);
  312. procedure Clear;
  313. function LockList: TList<T>;
  314. procedure UnlockList; inline;
  315. property Duplicates: TDuplicates read FDuplicates write FDuplicates;
  316. end;
  317. TQueue<T> = class(TCustomList<T>)
  318. public type
  319. TPointersEnumerator = class(TCustomPointersEnumerator<T, PT>)
  320. protected
  321. FQueue: TQueue<T>;
  322. FIndex: SizeInt;
  323. function DoMoveNext: boolean; override;
  324. function DoGetCurrent: PT; override;
  325. public
  326. constructor Create(AQueue: TQueue<T>);
  327. end;
  328. protected
  329. function PrepareAddingItem: SizeInt; override;
  330. function GetPtrEnumerator: TEnumerator<PT>; override;
  331. protected
  332. // bug #24287 - workaround for generics type name conflict (Identifier not found)
  333. // next bug workaround - for another error related to previous workaround
  334. // change order (function must be declared before TEnumerator declaration}
  335. function DoGetEnumerator: {Generics.Collections.}TEnumerator<T>; override;
  336. public
  337. type
  338. TEnumerator = class(TCustomListEnumerator<T>)
  339. public
  340. constructor Create(AQueue: TQueue<T>);
  341. end;
  342. function GetEnumerator: TEnumerator; reintroduce;
  343. private
  344. FLow: SizeInt;
  345. procedure MoveToFront;
  346. protected
  347. procedure SetCapacity(AValue: SizeInt); override;
  348. function DoRemove(AIndex: SizeInt; ACollectionNotification: TCollectionNotification): T; override;
  349. function GetCount: SizeInt; override;
  350. public
  351. constructor Create(ACollection: TEnumerable<T>); overload;
  352. {$IFDEF ENABLE_METHODS_WITH_TEnumerableWithPointers}
  353. constructor Create(ACollection: TEnumerableWithPointers<T>); overload;
  354. {$ENDIF}
  355. destructor Destroy; override;
  356. procedure Enqueue(const AValue: T);
  357. function Dequeue: T;
  358. function Extract: T;
  359. function Peek: T;
  360. procedure Clear;
  361. procedure TrimExcess; override;
  362. end;
  363. TStack<T> = class(TCustomListWithPointers<T>)
  364. protected
  365. // bug #24287 - workaround for generics type name conflict (Identifier not found)
  366. // next bug workaround - for another error related to previous workaround
  367. // change order (function must be declared before TEnumerator declaration}
  368. function DoGetEnumerator: {Generics.Collections.}TEnumerator<T>; override;
  369. public
  370. type
  371. TEnumerator = class(TCustomListEnumerator<T>);
  372. function GetEnumerator: TEnumerator; reintroduce;
  373. protected
  374. function DoRemove(AIndex: SizeInt; ACollectionNotification: TCollectionNotification): T; override;
  375. procedure SetCapacity(AValue: SizeInt); override;
  376. public
  377. constructor Create(ACollection: TEnumerable<T>); overload;
  378. {$IFDEF ENABLE_METHODS_WITH_TEnumerableWithPointers}
  379. constructor Create(ACollection: TEnumerableWithPointers<T>); overload;
  380. {$ENDIF}
  381. destructor Destroy; override;
  382. procedure Clear;
  383. procedure Push(const AValue: T);
  384. function Pop: T; inline;
  385. function Peek: T;
  386. function Extract: T; inline;
  387. procedure TrimExcess; override;
  388. end;
  389. TObjectList<T: class> = class(TList<T>)
  390. private
  391. FObjectsOwner: Boolean;
  392. protected
  393. procedure Notify(const AValue: T; ACollectionNotification: TCollectionNotification); override;
  394. public
  395. constructor Create(AOwnsObjects: Boolean = True); overload;
  396. constructor Create(const AComparer: IComparer<T>; AOwnsObjects: Boolean = True); overload;
  397. constructor Create(ACollection: TEnumerable<T>; AOwnsObjects: Boolean = True); overload;
  398. {$IFDEF ENABLE_METHODS_WITH_TEnumerableWithPointers}
  399. constructor Create(ACollection: TEnumerableWithPointers<T>; AOwnsObjects: Boolean = True); overload;
  400. {$ENDIF}
  401. property OwnsObjects: Boolean read FObjectsOwner write FObjectsOwner;
  402. end;
  403. TObjectQueue<T: class> = class(TQueue<T>)
  404. private
  405. FObjectsOwner: Boolean;
  406. protected
  407. procedure Notify(const AValue: T; ACollectionNotification: TCollectionNotification); override;
  408. public
  409. constructor Create(AOwnsObjects: Boolean = True); overload;
  410. constructor Create(ACollection: TEnumerable<T>; AOwnsObjects: Boolean = True); overload;
  411. {$IFDEF ENABLE_METHODS_WITH_TEnumerableWithPointers}
  412. constructor Create(ACollection: TEnumerableWithPointers<T>; AOwnsObjects: Boolean = True); overload;
  413. {$ENDIF}
  414. procedure Dequeue;
  415. property OwnsObjects: Boolean read FObjectsOwner write FObjectsOwner;
  416. end;
  417. TObjectStack<T: class> = class(TStack<T>)
  418. private
  419. FObjectsOwner: Boolean;
  420. protected
  421. procedure Notify(const AValue: T; ACollectionNotification: TCollectionNotification); override;
  422. public
  423. constructor Create(AOwnsObjects: Boolean = True); overload;
  424. constructor Create(ACollection: TEnumerable<T>; AOwnsObjects: Boolean = True); overload;
  425. {$IFDEF ENABLE_METHODS_WITH_TEnumerableWithPointers}
  426. constructor Create(ACollection: TEnumerableWithPointers<T>; AOwnsObjects: Boolean = True); overload;
  427. {$ENDIF}
  428. function Pop: T;
  429. property OwnsObjects: Boolean read FObjectsOwner write FObjectsOwner;
  430. end;
  431. PObject = ^TObject;
  432. {$I inc\generics.dictionariesh.inc}
  433. { TCustomHashSet<T> }
  434. TCustomSet<T> = class(TEnumerableWithPointers<T>)
  435. protected
  436. FOnNotify: TCollectionNotifyEvent<T>;
  437. public type
  438. PT = ^T;
  439. protected type
  440. TCustomSetEnumerator = class(TEnumerator<T>)
  441. protected var
  442. FEnumerator: TEnumerator<T>;
  443. function DoMoveNext: boolean; override;
  444. function DoGetCurrent: T; override;
  445. function GetCurrent: T; virtual; abstract;
  446. public
  447. constructor Create(ASet: TCustomSet<T>); virtual; abstract;
  448. destructor Destroy; override;
  449. end;
  450. protected
  451. function DoGetEnumerator: TEnumerator<T>; override;
  452. function GetCount: SizeInt; virtual; abstract;
  453. function GetCapacity: SizeInt; virtual; abstract;
  454. procedure SetCapacity(AValue: SizeInt); virtual; abstract;
  455. function GetOnNotify: TCollectionNotifyEvent<T>; virtual; abstract;
  456. procedure SetOnNotify(AValue: TCollectionNotifyEvent<T>); virtual; abstract;
  457. public
  458. constructor Create; virtual; abstract; overload;
  459. constructor Create(ACollection: TEnumerable<T>); overload;
  460. {$IFDEF ENABLE_METHODS_WITH_TEnumerableWithPointers}
  461. constructor Create(ACollection: TEnumerableWithPointers<T>); overload;
  462. {$ENDIF}
  463. function GetEnumerator: TCustomSetEnumerator; reintroduce; virtual; abstract;
  464. function Add(const AValue: T): Boolean; virtual; abstract;
  465. function Remove(const AValue: T): Boolean; virtual; abstract;
  466. function Extract(const AValue: T): T; virtual; abstract;
  467. procedure Clear; virtual; abstract;
  468. function Contains(const AValue: T): Boolean; virtual; abstract;
  469. function AddRange(const AValues: array of T): Boolean; overload;
  470. function AddRange(const AEnumerable: IEnumerable<T>): Boolean; overload;
  471. function AddRange(AEnumerable: TEnumerable<T>): Boolean; overload;
  472. {$IFDEF ENABLE_METHODS_WITH_TEnumerableWithPointers}
  473. function AddRange(AEnumerable: TEnumerableWithPointers<T>): Boolean; overload;
  474. {$ENDIF}
  475. procedure UnionWith(AHashSet: TCustomSet<T>);
  476. procedure IntersectWith(AHashSet: TCustomSet<T>);
  477. procedure ExceptWith(AHashSet: TCustomSet<T>);
  478. procedure SymmetricExceptWith(AHashSet: TCustomSet<T>);
  479. property Count: SizeInt read GetCount;
  480. property Capacity: SizeInt read GetCapacity write SetCapacity;
  481. procedure TrimExcess; virtual; abstract;
  482. property OnNotify: TCollectionNotifyEvent<T> read GetOnNotify write SetOnNotify;
  483. end;
  484. { THashSet<T> }
  485. THashSet<T> = class(TCustomSet<T>)
  486. private
  487. procedure InternalDictionaryNotify(ASender: TObject; const AItem: T; AAction: TCollectionNotification);
  488. protected
  489. FInternalDictionary: TOpenAddressingLP<T, TEmptyRecord>;
  490. public type
  491. THashSetEnumerator = class(TCustomSetEnumerator)
  492. protected type
  493. TDictionaryEnumerator = TDictionary<T, TEmptyRecord>.TKeyEnumerator;
  494. function GetCurrent: T; override;
  495. public
  496. constructor Create(ASet: TCustomSet<T>); override;
  497. end;
  498. TPointersEnumerator = class(TCustomPointersEnumerator<T, PT>)
  499. protected
  500. FEnumerator: TEnumerator<PT>;
  501. function DoMoveNext: boolean; override;
  502. function DoGetCurrent: PT; override;
  503. public
  504. constructor Create(AHashSet: THashSet<T>);
  505. end;
  506. protected
  507. function GetPtrEnumerator: TEnumerator<PT>; override;
  508. function GetCount: SizeInt; override;
  509. function GetCapacity: SizeInt; override;
  510. procedure SetCapacity(AValue: SizeInt); override;
  511. function GetOnNotify: TCollectionNotifyEvent<T>; override;
  512. procedure SetOnNotify(AValue: TCollectionNotifyEvent<T>); override;
  513. public
  514. constructor Create; override; overload;
  515. constructor Create(const AComparer: IEqualityComparer<T>); virtual; overload;
  516. destructor Destroy; override;
  517. function GetEnumerator: TCustomSetEnumerator; override;
  518. function Add(const AValue: T): Boolean; override;
  519. function Remove(const AValue: T): Boolean; override;
  520. function Extract(const AValue: T): T; override;
  521. procedure Clear; override;
  522. function Contains(const AValue: T): Boolean; override;
  523. procedure TrimExcess; override;
  524. end;
  525. TPair<TKey, TValue, TInfo> = record
  526. public
  527. Key: TKey;
  528. Value: TValue;
  529. Info: TInfo;
  530. end;
  531. TAVLTreeNode<TREE_CONSTRAINTS, TTree> = record
  532. private type
  533. TNodePair = TPair<TREE_CONSTRAINTS>;
  534. public type
  535. PNode = ^TAVLTreeNode<TREE_CONSTRAINTS, TTree>;
  536. public
  537. Parent, Left, Right: PNode;
  538. Balance: Integer;
  539. Data: TNodePair;
  540. function Successor: PNode;
  541. function Precessor: PNode;
  542. function TreeDepth: integer;
  543. procedure ConsistencyCheck(ATree: TObject); // workaround for internal error 2012101001 (no generic forward declarations)
  544. function GetCount: SizeInt;
  545. property Key: TKey read Data.Key write Data.Key;
  546. property Value: TValue read Data.Value write Data.Value;
  547. property Info: TInfo read Data.Info write Data.Info;
  548. end;
  549. TCustomTreeEnumerator<T, PNode, TTree> = class abstract(TEnumerator<T>)
  550. protected
  551. FCurrent: PNode;
  552. FTree: TTree;
  553. function DoGetCurrent: T; override;
  554. function GetCurrent: T; virtual; abstract;
  555. public
  556. constructor Create(ATree: TObject);
  557. property Current: T read GetCurrent;
  558. end;
  559. TTreeEnumerable<TTreeEnumerator, TTreePointersEnumerator,
  560. T, PT, PNode, TTree> = class abstract(TEnumerableWithPointers<T>)
  561. private
  562. FTree: TTree;
  563. function GetCount: SizeInt; inline;
  564. protected
  565. function GetPtrEnumerator: TEnumerator<PT>; override;
  566. function DoGetEnumerator: TTreeEnumerator; override;
  567. public
  568. constructor Create(ATree: TTree);
  569. function ToArray: TArray<T>; override; final;
  570. property Count: SizeInt read GetCount;
  571. end;
  572. TAVLTreeEnumerator<T, PNode, TTree> = class(TCustomTreeEnumerator<T, PNode, TTree>)
  573. protected
  574. FLowToHigh: boolean;
  575. function DoMoveNext: Boolean; override;
  576. public
  577. constructor Create(ATree: TObject; ALowToHigh: boolean = true);
  578. property LowToHigh: boolean read FLowToHigh;
  579. end;
  580. TNodeNotifyEvent<PNode> = procedure(ASender: TObject; ANode: PNode; AAction: TCollectionNotification; ADispose: boolean) of object;
  581. TCustomAVLTreeMap<TREE_CONSTRAINTS> = class
  582. private type
  583. TTree = TCustomAVLTreeMap<TREE_CONSTRAINTS>;
  584. public type
  585. TNode = TAVLTreeNode<TREE_CONSTRAINTS, TTree>;
  586. PNode = ^TNode;
  587. PPNode = ^PNode;
  588. TTreePair = TPair<TKey, TValue>;
  589. PKey = ^TKey;
  590. PValue = ^TValue;
  591. private type
  592. // type exist only for generic constraint in TNodeCollection (non functional - PPNode has no sense)
  593. TPNodeEnumerator = TAVLTreeEnumerator<PPNode, PNode, TTree>;
  594. private var
  595. FDuplicates: TDuplicates;
  596. FComparer: IComparer<TKey>;
  597. protected
  598. FCount: SizeInt;
  599. FRoot: PNode;
  600. FKeys: TEnumerable<TKey>;
  601. FValues: TEnumerable<TValue>;
  602. FOnNodeNotify: TNodeNotifyEvent<PNode>;
  603. FOnKeyNotify: TCollectionNotifyEvent<TKey>;
  604. FOnValueNotify: TCollectionNotifyEvent<TValue>;
  605. procedure NodeAdded(ANode: PNode); virtual;
  606. procedure DeletingNode(ANode: PNode; AOrigin: boolean); virtual;
  607. function DoRemove(ANode: PNode; ACollectionNotification: TCollectionNotification; ADispose: boolean): TValue;
  608. procedure DisposeAllNodes(ANode: PNode); overload;
  609. function Compare(const ALeft, ARight: TKey): Integer; inline;
  610. function FindPredecessor(ANode: PNode): PNode;
  611. function FindInsertNode(ANode: PNode; out AInsertNode: PNode): Integer;
  612. procedure RotateRightRight(ANode: PNode); virtual;
  613. procedure RotateLeftLeft(ANode: PNode); virtual;
  614. procedure RotateRightLeft(ANode: PNode); virtual;
  615. procedure RotateLeftRight(ANode: PNode); virtual;
  616. procedure KeyNotify(const AKey: TKey; ACollectionNotification: TCollectionNotification); inline;
  617. procedure ValueNotify(const AValue: TValue; ACollectionNotification: TCollectionNotification); inline;
  618. procedure NodeNotify(ANode: PNode; ACollectionNotification: TCollectionNotification; ADispose: boolean); inline;
  619. procedure SetValue(var AValue: TValue; const ANewValue: TValue);
  620. function GetItem(const AKey: TKey): TValue;
  621. procedure SetItem(const AKey: TKey; const AValue: TValue);
  622. property Items[Index: TKey]: TValue read GetItem write SetItem;
  623. // for reporting
  624. procedure WriteStr(AStream: TStream; const AText: string);
  625. public type
  626. TPairEnumerator = class(TAVLTreeEnumerator<TTreePair, PNode, TTree>)
  627. protected
  628. function GetCurrent: TTreePair; override;
  629. end;
  630. TNodeEnumerator = class(TAVLTreeEnumerator<PNode, PNode, TTree>)
  631. protected
  632. function GetCurrent: PNode; override;
  633. end;
  634. TKeyEnumerator = class(TAVLTreeEnumerator<TKey, PNode, TTree>)
  635. protected
  636. function GetCurrent: TKey; override;
  637. end;
  638. TPKeyEnumerator = class(TAVLTreeEnumerator<PKey, PNode, TTree>)
  639. protected
  640. function GetCurrent: PKey; override;
  641. end;
  642. TValueEnumerator = class(TAVLTreeEnumerator<TValue, PNode, TTree>)
  643. protected
  644. function GetCurrent: TValue; override;
  645. end;
  646. TPValueEnumerator = class(TAVLTreeEnumerator<PValue, PNode, TTree>)
  647. protected
  648. function GetCurrent: PValue; override;
  649. end;
  650. TNodeCollection = class(TTreeEnumerable<TNodeEnumerator, TPNodeEnumerator, PNode, PPNode, PNode, TTree>)
  651. private
  652. property Ptr; // PPNode has no sense, so hide enumerator for PPNode
  653. end;
  654. TKeyCollection = class(TTreeEnumerable<TKeyEnumerator, TPKeyEnumerator, TKey, PKey, PNode, TTree>);
  655. TValueCollection = class(TTreeEnumerable<TValueEnumerator, TPValueEnumerator, TValue, PValue, PNode, TTree>);
  656. private
  657. FNodes: TNodeCollection;
  658. function GetNodeCollection: TNodeCollection;
  659. procedure InternalAdd(ANode, AParent: PNode); overload;
  660. function InternalAdd(ANode: PNode; ADispisable: boolean): PNode; overload;
  661. procedure InternalDelete(ANode: PNode);
  662. function GetKeys: TKeyCollection;
  663. function GetValues: TValueCollection;
  664. public
  665. constructor Create; virtual; overload;
  666. constructor Create(const AComparer: IComparer<TKey>); virtual; overload;
  667. function NewNode: PNode;
  668. function NewNodeArray(ACount: SizeInt): PNode; overload;
  669. procedure NewNodeArray(out AArray: TArray<PNode>; ACount: SizeInt); overload;
  670. procedure DisposeNode(ANode: PNode);
  671. procedure DisposeNodeArray(ANode: PNode; ACount: SizeInt); overload;
  672. procedure DisposeNodeArray(var AArray: TArray<PNode>); overload;
  673. destructor Destroy; override;
  674. function AddNode(ANode: PNode): boolean; overload; inline;
  675. function Add(const APair: TTreePair): PNode; overload; inline;
  676. function Add(const AKey: TKey; const AValue: TValue): PNode; overload; inline;
  677. function Remove(const AKey: TKey; ADisposeNode: boolean = true): boolean;
  678. function ExtractPair(const AKey: TKey; ADisposeNode: boolean = true): TTreePair; overload;
  679. function ExtractPair(const ANode: PNode; ADispose: boolean = true): TTreePair; overload;
  680. function Extract(const AKey: TKey; ADisposeNode: boolean): PNode;
  681. function ExtractNode(ANode: PNode; ADispose: boolean): PNode;
  682. procedure Delete(ANode: PNode; ADispose: boolean = true); inline;
  683. function GetEnumerator: TPairEnumerator;
  684. property Nodes: TNodeCollection read GetNodeCollection;
  685. procedure Clear(ADisposeNodes: Boolean = true); virtual;
  686. function FindLowest: PNode;
  687. function FindHighest: PNode;
  688. property Count: SizeInt read FCount;
  689. property Root: PNode read FRoot;
  690. function Find(const AKey: TKey): PNode;
  691. function ContainsKey(const AKey: TKey; out ANode: PNode): boolean; overload; inline;
  692. function ContainsKey(const AKey: TKey): boolean; overload; inline;
  693. procedure ConsistencyCheck; virtual;
  694. procedure WriteTreeNode(AStream: TStream; ANode: PNode);
  695. procedure WriteReportToStream(AStream: TStream);
  696. function NodeToReportStr(ANode: PNode): string; virtual;
  697. function ReportAsString: string;
  698. property Keys: TKeyCollection read GetKeys;
  699. property Values: TValueCollection read GetValues;
  700. property Duplicates: TDuplicates read FDuplicates write FDuplicates;
  701. property OnNodeNotify: TNodeNotifyEvent<PNode> read FOnNodeNotify write FOnNodeNotify;
  702. property OnKeyNotify: TCollectionNotifyEvent<TKey> read FOnKeyNotify write FOnKeyNotify;
  703. property OnValueNotify: TCollectionNotifyEvent<TValue> read FOnValueNotify write FOnValueNotify;
  704. end;
  705. TAVLTreeMap<TKey, TValue> = class(TCustomAVLTreeMap<TKey, TValue, TEmptyRecord>)
  706. public
  707. property Items; default;
  708. end;
  709. TIndexedAVLTreeMap<TKey, TValue> = class(TCustomAVLTreeMap<TKey, TValue, SizeInt>)
  710. protected
  711. FLastNode: PNode;
  712. FLastIndex: SizeInt;
  713. procedure RotateRightRight(ANode: PNode); override;
  714. procedure RotateLeftLeft(ANode: PNode); override;
  715. procedure RotateRightLeft(ANode: PNode); override;
  716. procedure RotateLeftRight(ANode: PNode); override;
  717. procedure NodeAdded(ANode: PNode); override;
  718. procedure DeletingNode(ANode: PNode; AOrigin: boolean); override;
  719. public
  720. function GetNodeAtIndex(AIndex: SizeInt): PNode;
  721. function NodeToIndex(ANode: PNode): SizeInt;
  722. procedure ConsistencyCheck; override;
  723. function NodeToReportStr(ANode: PNode): string; override;
  724. end;
  725. TAVLTree<T> = class(TAVLTreeMap<T, TEmptyRecord>)
  726. protected
  727. property OnKeyNotify;
  728. property OnValueNotify;
  729. property Items;
  730. public type
  731. TItemEnumerator = TKeyEnumerator;
  732. public
  733. function Add(const AValue: T): PNode; reintroduce; inline;
  734. function AddNode(ANode: PNode): boolean; reintroduce; inline;
  735. property OnNotify: TCollectionNotifyEvent<T> read FOnKeyNotify write FOnKeyNotify;
  736. end;
  737. TIndexedAVLTree<T> = class(TIndexedAVLTreeMap<T, TEmptyRecord>)
  738. protected
  739. property OnKeyNotify;
  740. property OnValueNotify;
  741. public type
  742. TItemEnumerator = TKeyEnumerator;
  743. public
  744. function Add(const AValue: T): PNode; reintroduce; inline;
  745. function AddNode(ANode: PNode): boolean; reintroduce; inline;
  746. property OnNotify: TCollectionNotifyEvent<T> read FOnKeyNotify write FOnKeyNotify;
  747. end;
  748. TSortedSet<T> = class(TCustomSet<T>)
  749. private
  750. procedure InternalAVLTreeNotify(ASender: TObject; const AItem: T; AAction: TCollectionNotification);
  751. protected
  752. FInternalTree: TAVLTree<T>;
  753. public type
  754. TSortedSetEnumerator = class(TCustomSetEnumerator)
  755. protected type
  756. TTreeEnumerator = TAVLTree<T>.TItemEnumerator;
  757. function GetCurrent: T; override;
  758. public
  759. constructor Create(ASet: TCustomSet<T>); override;
  760. end;
  761. TPointersEnumerator = class(TCustomPointersEnumerator<T, PT>)
  762. protected
  763. FEnumerator: TEnumerator<PT>;
  764. function DoMoveNext: boolean; override;
  765. function DoGetCurrent: PT; override;
  766. public
  767. constructor Create(ASortedSet: TSortedSet<T>);
  768. end;
  769. protected
  770. function GetPtrEnumerator: TEnumerator<PT>; override;
  771. function GetCount: SizeInt; override;
  772. function GetCapacity: SizeInt; override;
  773. procedure SetCapacity(AValue: SizeInt); override;
  774. function GetOnNotify: TCollectionNotifyEvent<T>; override;
  775. procedure SetOnNotify(AValue: TCollectionNotifyEvent<T>); override;
  776. public
  777. constructor Create; override; overload;
  778. constructor Create(const AComparer: IComparer<T>); virtual; overload;
  779. destructor Destroy; override;
  780. function GetEnumerator: TCustomSetEnumerator; override;
  781. function Add(const AValue: T): Boolean; override;
  782. function Remove(const AValue: T): Boolean; override;
  783. function Extract(const AValue: T): T; override;
  784. procedure Clear; override;
  785. function Contains(const AValue: T): Boolean; override;
  786. procedure TrimExcess; override;
  787. end;
  788. TSortedHashSet<T> = class(TCustomSet<T>)
  789. private
  790. procedure InternalDictionaryNotify(ASender: TObject; const AItem: PT; AAction: TCollectionNotification);
  791. protected
  792. FInternalDictionary: TOpenAddressingLP<PT, TEmptyRecord>;
  793. FInternalTree: TAVLTree<T>;
  794. function DoGetEnumerator: TEnumerator<T>; override;
  795. function GetCount: SizeInt; override;
  796. function GetCapacity: SizeInt; override;
  797. procedure SetCapacity(AValue: SizeInt); override;
  798. function GetOnNotify: TCollectionNotifyEvent<T>; override;
  799. procedure SetOnNotify(AValue: TCollectionNotifyEvent<T>); override;
  800. protected type
  801. TSortedHashSetEqualityComparer = class(TInterfacedObject, IEqualityComparer<PT>)
  802. private
  803. FComparer: IComparer<T>;
  804. FEqualityComparer: IEqualityComparer<T>;
  805. function Equals(const ALeft, ARight: PT): Boolean;
  806. function GetHashCode(const AValue: PT): UInt32;
  807. public
  808. constructor Create(const AComparer: IComparer<T>); overload;
  809. constructor Create(const AEqualityComparer: IEqualityComparer<T>); overload;
  810. constructor Create(const AComparer: IComparer<T>; const AEqualityComparer: IEqualityComparer<T>); overload;
  811. end;
  812. public type
  813. TSortedHashSetEnumerator = class(TCustomSetEnumerator)
  814. protected type
  815. TTreeEnumerator = TAVLTree<T>.TItemEnumerator;
  816. function GetCurrent: T; override;
  817. public
  818. constructor Create(ASet: TCustomSet<T>); override;
  819. end;
  820. TPointersEnumerator = class(TCustomPointersEnumerator<T, PT>)
  821. protected
  822. FEnumerator: TEnumerator<PT>;
  823. function DoMoveNext: boolean; override;
  824. function DoGetCurrent: PT; override;
  825. public
  826. constructor Create(ASortedHashSet: TSortedHashSet<T>);
  827. end;
  828. protected
  829. function GetPtrEnumerator: TEnumerator<PT>; override;
  830. public
  831. constructor Create; override; overload;
  832. constructor Create(const AComparer: IEqualityComparer<T>); overload;
  833. constructor Create(const AComparer: IComparer<T>); overload;
  834. constructor Create(const AComparer: IComparer<T>; const AEqualityComparer: IEqualityComparer<T>); overload;
  835. destructor Destroy; override;
  836. function GetEnumerator: TCustomSetEnumerator; override;
  837. function Add(const AValue: T): Boolean; override;
  838. function Remove(const AValue: T): Boolean; override;
  839. function Extract(const AValue: T): T; override;
  840. procedure Clear; override;
  841. function Contains(const AValue: T): Boolean; override;
  842. procedure TrimExcess; override;
  843. end;
  844. function InCircularRange(ABottom, AItem, ATop: SizeInt): Boolean;
  845. procedure ErrorArgumentOutOfRange; overload;
  846. procedure ErrorArgumentOutOfRange(aIndex, aMaxIndex: SizeInt; aListObj: TObject); overload;
  847. procedure ErrorArgumentOutOfRange(aIndex, aMaxIndex: SizeInt); overload;
  848. var
  849. EmptyRecord: TEmptyRecord;
  850. implementation
  851. procedure ErrorArgumentOutOfRange;
  852. begin
  853. raise EArgumentOutOfRangeException.Create(SArgumentOutOfRange);
  854. end;
  855. procedure ErrorArgumentOutOfRange(aIndex, aMaxIndex: SizeInt; aListObj: TObject); overload;
  856. begin
  857. raise EArgumentOutOfRangeException.Create(ListIndexErrorMsg(aIndex,aMaxIndex,aListObj));
  858. end;
  859. procedure ErrorArgumentOutOfRange(aIndex, aMaxIndex: SizeInt); overload;
  860. begin
  861. raise EArgumentOutOfRangeException.Create(ListIndexErrorMsg(aIndex,aMaxIndex,''));
  862. end;
  863. function InCircularRange(ABottom, AItem, ATop: SizeInt): Boolean;
  864. begin
  865. Result :=
  866. (ABottom < AItem) and (AItem <= ATop )
  867. or (ATop < ABottom) and (AItem > ABottom)
  868. or (ATop < ABottom ) and (AItem <= ATop );
  869. end;
  870. { TCustomArrayHelper<T> }
  871. class function TCustomArrayHelper<T>.BinarySearch(const AValues: array of T; const AItem: T;
  872. out AFoundIndex: SizeInt; const AComparer: IComparer<T>): Boolean;
  873. begin
  874. Result := BinarySearch(AValues, AItem, AFoundIndex, AComparer, Low(AValues), Length(AValues));
  875. end;
  876. class function TCustomArrayHelper<T>.BinarySearch(const AValues: array of T; const AItem: T;
  877. out AFoundIndex: SizeInt): Boolean;
  878. begin
  879. Result := BinarySearch(AValues, AItem, AFoundIndex, TComparerBugHack.Default, Low(AValues), Length(AValues));
  880. end;
  881. class function TCustomArrayHelper<T>.BinarySearch(const AValues: array of T; const AItem: T;
  882. out ASearchResult: TBinarySearchResult; const AComparer: IComparer<T>): Boolean;
  883. begin
  884. Result := BinarySearch(AValues, AItem, ASearchResult, AComparer, Low(AValues), Length(AValues));
  885. end;
  886. class function TCustomArrayHelper<T>.BinarySearch(const AValues: array of T; const AItem: T;
  887. out ASearchResult: TBinarySearchResult): Boolean;
  888. begin
  889. Result := BinarySearch(AValues, AItem, ASearchResult, TComparerBugHack.Default, Low(AValues), Length(AValues));
  890. end;
  891. class procedure TCustomArrayHelper<T>.Sort(var AValues: array of T);
  892. begin
  893. QuickSort(AValues, Low(AValues), High(AValues), TComparerBugHack.Default);
  894. end;
  895. class procedure TCustomArrayHelper<T>.Sort(var AValues: array of T;
  896. const AComparer: IComparer<T>);
  897. begin
  898. QuickSort(AValues, Low(AValues), High(AValues), AComparer);
  899. end;
  900. class procedure TCustomArrayHelper<T>.Sort(var AValues: array of T;
  901. const AComparer: IComparer<T>; AIndex, ACount: SizeInt);
  902. begin
  903. if ACount <= 1 then
  904. Exit;
  905. QuickSort(AValues, AIndex, Pred(AIndex + ACount), AComparer);
  906. end;
  907. { TArrayHelper<T> }
  908. class procedure TArrayHelper<T>.QSort(p: PT; n, reasonable: SizeUint; const cmp: IComparer<T>);
  909. const
  910. INSERTION_SORT_THRESHOLD = 10;
  911. var
  912. L, R: SizeInt;
  913. pivot, temp: T;
  914. begin
  915. Prefetch(p);
  916. while (n > INSERTION_SORT_THRESHOLD) and (reasonable > 0) do
  917. begin
  918. { If 'reasonable' reaches zero, the algorithm changes to heapsort }
  919. Dec(reasonable);
  920. pivot := Median(p, n, cmp)^;
  921. R := 0;
  922. L := n - 1;
  923. repeat
  924. while cmp.Compare((p + R)^, pivot) < 0 do
  925. inc(R);
  926. while cmp.Compare(pivot, (p + L)^) < 0 do
  927. dec(L);
  928. if R <= L then
  929. begin
  930. temp := (p + R)^; (p + R)^ := (p + L)^; (p + L)^ := temp;
  931. inc(R);
  932. dec(L);
  933. end;
  934. until R > L;
  935. { [0 .. L], [R .. n - 1]. Possible edge cases are L = -1 or R = n. Recurse into the smaller half. }
  936. if n - R <= L then
  937. begin
  938. QSort(p + R, n - R, reasonable, cmp);
  939. n := L + 1;
  940. end else
  941. begin
  942. QSort(p, L + 1, reasonable, cmp);
  943. p := p + R;
  944. n := n - R;
  945. end;
  946. end;
  947. { When the partition is small, switch to insertion sort }
  948. if (n <= INSERTION_SORT_THRESHOLD) then
  949. begin
  950. L := 1;
  951. while L < n do
  952. begin
  953. pivot := (P + L)^;
  954. R := L - 1;
  955. while (R >= 0) and (cmp.compare((p + R)^, pivot) > 0) do
  956. begin
  957. (p + (R + 1))^ := (p + R)^;
  958. Dec(R);
  959. end;
  960. (p + (R + 1))^ := pivot;
  961. Inc(L);
  962. end;
  963. end else
  964. HeapSort(p, n, cmp);
  965. end;
  966. class function TArrayHelper<T>.Median(p: PT; n: SizeUint; const cmp: IComparer<T>): PT;
  967. var
  968. a, b, c, temp: PT;
  969. begin
  970. a := p;
  971. b := p + n div 2;
  972. c := p + (n - 1);
  973. if cmp.Compare(b^, a^) < 0 then begin temp := a; a := b; b := temp; end;
  974. if cmp.Compare(c^, b^) < 0 then begin temp := b; b := c; c := temp; end;
  975. if cmp.Compare(b^, a^) < 0 then result := a else result := b;
  976. end;
  977. class procedure TArrayHelper<T>.HeapSort(p: PT; n: SizeUint; const cmp: IComparer<T>);
  978. var
  979. temp: T;
  980. i: SizeInt;
  981. begin
  982. for i := SizeUint(n - 2) div 2 downto 0 do
  983. begin
  984. temp := (p + i)^;
  985. HeapReplacePessimistic(p, n, i, temp, cmp);
  986. end;
  987. for i := n - 1 downto 1 do
  988. begin
  989. temp := (p + i)^;
  990. (p + i)^ := p^;
  991. HeapReplacePessimistic(p, i, 0, temp, cmp);
  992. end;
  993. end;
  994. { HeapReplacePessimistic replaces q[id] with 'item' by doing something like
  995. startId := id;
  996. q[id] := item;
  997. id := HeapDownThoroughly(q, nq, id);
  998. id := HeapUpToId(q, nq, id, startId);
  999. Where 'HeapDownThoroughly' sinks the element all the way down, without stopping at the correct position, so it must float up afterwards.
  1000. See Python's 'heapq' module for explanation why this is an improvement over simple HeapDown.
  1001. TL;DR: HeapDownThoroughly uses 1 fewer comparison per level, and the item usually ends up close to the bottom, so these savings pay off.
  1002. Moreover, heap invariant assumed for q[id .. nq - 1] rather than whole q[0 .. nq - 1] which matters when heapifying the array from the end. }
  1003. class procedure TArrayHelper<T>.HeapReplacePessimistic(q: PT; nq, id: SizeUint; const item: T; const cmp: IComparer<T>);
  1004. var
  1005. iChild, iParent, start: SizeUint;
  1006. begin
  1007. start := id;
  1008. repeat
  1009. iChild := 2 * id + 1; { childs of q[id] are q[2 * id + 1] ... q[2 * id + 2]. }
  1010. if iChild >= nq then
  1011. break;
  1012. if (iChild + 1 < nq) and (cmp.Compare((q + iChild)^, (q + iChild + 1)^) < 0) then
  1013. iChild := iChild + 1;
  1014. (q + id)^ := (q + iChild)^;
  1015. id := iChild;
  1016. until false;
  1017. while id > start do
  1018. begin
  1019. iParent := SizeUint(id - 1) div 2;
  1020. if cmp.Compare((q + iParent)^, item) >= 0 then
  1021. break;
  1022. (q + id)^ := (q + iParent)^;
  1023. id := iParent;
  1024. end;
  1025. (q + id)^ := item;
  1026. end;
  1027. class procedure TArrayHelper<T>.QuickSort(var AValues: array of T; ALeft, ARight: SizeInt;
  1028. const AComparer: IComparer<T>);
  1029. var
  1030. N: SizeInt;
  1031. begin
  1032. N := ARight - ALeft + 1;
  1033. if N > 1 then
  1034. { Use BSR as a base-2 logarithm }
  1035. QSort(
  1036. PT(AValues) + ALeft,
  1037. N,
  1038. {$if defined(CPU64)}
  1039. 2 * BsrQWord(QWord(N)),
  1040. {$elseif defined(CPU32)}
  1041. 2 * BsrDWord(LongWord(N)),
  1042. {$elseif defined(CPU16)}
  1043. 2 * BsrWord(Word(N)),
  1044. {$endif}
  1045. AComparer
  1046. );
  1047. end;
  1048. class function TArrayHelper<T>.BinarySearch(const AValues: array of T; const AItem: T;
  1049. out ASearchResult: TBinarySearchResult; const AComparer: IComparer<T>;
  1050. AIndex, ACount: SizeInt): Boolean;
  1051. var
  1052. imin, imax, imid: Int32;
  1053. begin
  1054. if Length(AValues) = 0 then
  1055. begin
  1056. ASearchResult.CompareResult := 0;
  1057. ASearchResult.FoundIndex := -1;
  1058. ASearchResult.CandidateIndex := -1;
  1059. Exit(False);
  1060. end;
  1061. // continually narrow search until just one element remains
  1062. imin := AIndex;
  1063. imax := Pred(AIndex + ACount);
  1064. // http://en.wikipedia.org/wiki/Binary_search_algorithm
  1065. while (imin < imax) do
  1066. begin
  1067. imid := imin + ((imax - imin) shr 1);
  1068. // code must guarantee the interval is reduced at each iteration
  1069. // assert(imid < imax);
  1070. // note: 0 <= imin < imax implies imid will always be less than imax
  1071. ASearchResult.CompareResult := AComparer.Compare(AValues[imid], AItem);
  1072. // reduce the search
  1073. if (ASearchResult.CompareResult < 0) then
  1074. imin := imid + 1
  1075. else
  1076. begin
  1077. imax := imid;
  1078. if ASearchResult.CompareResult = 0 then
  1079. begin
  1080. ASearchResult.FoundIndex := imid;
  1081. ASearchResult.CandidateIndex := imid;
  1082. Exit(True);
  1083. end;
  1084. end;
  1085. end;
  1086. // At exit of while:
  1087. // if A[] is empty, then imax < imin
  1088. // otherwise imax == imin
  1089. // deferred test for equality
  1090. if (imax = imin) then
  1091. begin
  1092. ASearchResult.CompareResult := AComparer.Compare(AValues[imin], AItem);
  1093. ASearchResult.CandidateIndex := imin;
  1094. if (ASearchResult.CompareResult = 0) then
  1095. begin
  1096. ASearchResult.FoundIndex := imin;
  1097. Exit(True);
  1098. end else
  1099. begin
  1100. ASearchResult.FoundIndex := -1;
  1101. Exit(False);
  1102. end;
  1103. end
  1104. else
  1105. begin
  1106. ASearchResult.CompareResult := 0;
  1107. ASearchResult.FoundIndex := -1;
  1108. ASearchResult.CandidateIndex := -1;
  1109. Exit(False);
  1110. end;
  1111. end;
  1112. class procedure TArrayHelper<T>.Copy(const aSource: array of T; var aDestination: array of T; aCount: NativeInt);
  1113. begin
  1114. Copy(aSource,aDestination,0,0,aCount);
  1115. end;
  1116. class procedure TArrayHelper<T>.Copy(const aSource: array of T; var aDestination: array of T; aSourceIndex, aDestIndex, aCount: SizeInt);
  1117. var
  1118. I : Integer;
  1119. begin
  1120. if (Length(aSource)>0) and (Length(aDestination)>0) and ((@aSource[0]) = (@aDestination[0])) then
  1121. raise EArgumentException.Create(SErrSameArrays);
  1122. if (aCount<0) or
  1123. (aCount>(Length(aSource)-aSourceIndex)) or
  1124. (aCount>(Length(aDestination)-aDestIndex)) then
  1125. ErrorArgumentOutOfRange;
  1126. if IsManagedType(T) then
  1127. begin
  1128. // maybe this can be optimized too ?
  1129. For I:=0 to aCount-1 do
  1130. aDestination[aDestIndex+i]:=aSource[aSourceIndex+i];
  1131. end
  1132. else
  1133. Move(Pointer(@aSource[aSourceIndex])^, Pointer(@aDestination[aDestIndex])^, SizeOf(T)*aCount);
  1134. end;
  1135. class function TArrayHelper<T>.Concat(const Args: array of TArray<T>): TArray<T>;
  1136. var
  1137. TotalLen: SizeInt;
  1138. CurLen,Dest,i: SizeInt;
  1139. begin
  1140. Result:=Nil;
  1141. TotalLen:=0;
  1142. for i:=0 to Length(Args)-1 do
  1143. Inc(TotalLen,Length(Args[i]));
  1144. SetLength(Result,TotalLen);
  1145. Dest:=0;
  1146. for i:=0 to Length(Args)-1 do
  1147. begin
  1148. CurLen:=Length(Args[i]);
  1149. if CurLen>0 then
  1150. begin
  1151. Copy(Args[i],Result,0,Dest,CurLen);
  1152. Inc(Dest,CurLen);
  1153. end;
  1154. end;
  1155. end;
  1156. class function TArrayHelper<T>.BinarySearch(const AValues: array of T; const AItem: T;
  1157. out AFoundIndex: SizeInt; const AComparer: IComparer<T>;
  1158. AIndex, ACount: SizeInt): Boolean;
  1159. var
  1160. imin, imax, imid: Int32;
  1161. LCompare: SizeInt;
  1162. begin
  1163. if Length(AValues) = 0 then
  1164. begin
  1165. AFoundIndex := -1;
  1166. Exit(False);
  1167. end;
  1168. // continually narrow search until just one element remains
  1169. imin := AIndex;
  1170. imax := Pred(AIndex + ACount);
  1171. // http://en.wikipedia.org/wiki/Binary_search_algorithm
  1172. while (imin < imax) do
  1173. begin
  1174. imid := imin + ((imax - imin) shr 1);
  1175. // code must guarantee the interval is reduced at each iteration
  1176. // assert(imid < imax);
  1177. // note: 0 <= imin < imax implies imid will always be less than imax
  1178. LCompare := AComparer.Compare(AValues[imid], AItem);
  1179. // reduce the search
  1180. if (LCompare < 0) then
  1181. imin := imid + 1
  1182. else
  1183. begin
  1184. imax := imid;
  1185. if LCompare = 0 then
  1186. begin
  1187. AFoundIndex := imid;
  1188. Exit(True);
  1189. end;
  1190. end;
  1191. end;
  1192. // At exit of while:
  1193. // if A[] is empty, then imax < imin
  1194. // otherwise imax == imin
  1195. // deferred test for equality
  1196. AFoundIndex := imin;
  1197. LCompare := AComparer.Compare(AValues[imin], AItem);
  1198. Result := (imax = imin) and (LCompare = 0);
  1199. if not Result and (LCompare < 0) then
  1200. Inc(AFoundIndex);
  1201. end;
  1202. { TEnumerator<T> }
  1203. function TEnumerator<T>.DoMoveNext: boolean;
  1204. begin
  1205. Result:=False;
  1206. end;
  1207. function TEnumerator<T>.MoveNext: boolean;
  1208. begin
  1209. Exit(DoMoveNext);
  1210. end;
  1211. { TEnumerable<T> }
  1212. function TEnumerable<T>.ToArrayImpl(ACount: SizeInt): TArray<T>;
  1213. var
  1214. i: SizeInt;
  1215. LEnumerator: TEnumerator<T>;
  1216. begin
  1217. Result := nil;
  1218. SetLength(Result, ACount);
  1219. try
  1220. LEnumerator := GetEnumerator;
  1221. i := 0;
  1222. while LEnumerator.MoveNext do
  1223. begin
  1224. Result[i] := LEnumerator.Current;
  1225. Inc(i);
  1226. end;
  1227. finally
  1228. LEnumerator.Free;
  1229. end;
  1230. end;
  1231. function TEnumerable<T>.GetEnumerator: TEnumerator<T>;
  1232. begin
  1233. Exit(DoGetEnumerator);
  1234. end;
  1235. function TEnumerable<T>.ToArray: TArray<T>;
  1236. var
  1237. LEnumerator: TEnumerator<T>;
  1238. LBuffer: TList<T>;
  1239. begin
  1240. LBuffer := TList<T>.Create;
  1241. try
  1242. LEnumerator := GetEnumerator;
  1243. while LEnumerator.MoveNext do
  1244. LBuffer.Add(LEnumerator.Current);
  1245. Result := LBuffer.ToArray;
  1246. finally
  1247. LBuffer.Free;
  1248. LEnumerator.Free;
  1249. end;
  1250. end;
  1251. { TCustomPointersCollection<T, PT> }
  1252. function TCustomPointersCollection<T, PT>.Enumerable: TLocalEnumerable;
  1253. begin
  1254. Result := TLocalEnumerable(@Self);
  1255. end;
  1256. function TCustomPointersCollection<T, PT>.GetEnumerator: TEnumerator<PT>;
  1257. begin
  1258. Result := Enumerable.GetPtrEnumerator;
  1259. end;
  1260. { TEnumerableWithPointers<T> }
  1261. function TEnumerableWithPointers<T>.GetPtr: PPointersCollection;
  1262. begin
  1263. Result := PPointersCollection(Self);
  1264. end;
  1265. { TCustomList<T> }
  1266. function TCustomList<T>.PrepareAddingItem: SizeInt;
  1267. begin
  1268. Result := Length(FItems);
  1269. if (FLength < 4) and (Result < 4) then
  1270. SetLength(FItems, 4)
  1271. else if FLength = High(FLength) then
  1272. OutOfMemoryError
  1273. else if FLength = Result then
  1274. SetLength(FItems, CUSTOM_LIST_CAPACITY_INC);
  1275. Result := FLength;
  1276. Inc(FLength);
  1277. end;
  1278. function TCustomList<T>.PrepareAddingRange(ACount: SizeInt): SizeInt;
  1279. begin
  1280. if ACount < 0 then
  1281. raise EArgumentOutOfRangeException.CreateRes(@SArgumentOutOfRange);
  1282. if ACount = 0 then
  1283. Exit(FLength - 1);
  1284. if (FLength = 0) and (Length(FItems) = 0) then
  1285. SetLength(FItems, 4)
  1286. else if FLength = High(FLength) then
  1287. OutOfMemoryError;
  1288. Result := Length(FItems);
  1289. while Pred(FLength + ACount) >= Result do
  1290. begin
  1291. SetLength(FItems, CUSTOM_LIST_CAPACITY_INC);
  1292. Result := Length(FItems);
  1293. end;
  1294. Result := FLength;
  1295. Inc(FLength, ACount);
  1296. end;
  1297. function TCustomList<T>.ToArray: TArray<T>;
  1298. begin
  1299. Result := ToArrayImpl(Count);
  1300. end;
  1301. function TCustomList<T>.GetCount: SizeInt;
  1302. begin
  1303. Result := FLength;
  1304. end;
  1305. procedure TCustomList<T>.Notify(const AValue: T; ACollectionNotification: TCollectionNotification);
  1306. begin
  1307. if Assigned(FOnNotify) then
  1308. FOnNotify(Self, AValue, ACollectionNotification);
  1309. end;
  1310. function TCustomList<T>.DoRemove(AIndex: SizeInt; ACollectionNotification: TCollectionNotification): T;
  1311. begin
  1312. if (AIndex < 0) or (AIndex >= FLength) then
  1313. raise EArgumentOutOfRangeException.CreateRes(@SArgumentOutOfRange);
  1314. Result := FItems[AIndex];
  1315. Dec(FLength);
  1316. FItems[AIndex] := Default(T);
  1317. if AIndex <> FLength then
  1318. begin
  1319. System.Move(FItems[AIndex + 1], FItems[AIndex], (FLength - AIndex) * SizeOf(T));
  1320. FillChar(FItems[FLength], SizeOf(T), 0);
  1321. end;
  1322. Notify(Result, ACollectionNotification);
  1323. end;
  1324. function TCustomList<T>.GetCapacity: SizeInt;
  1325. begin
  1326. Result := Length(FItems);
  1327. end;
  1328. { TCustomListEnumerator<T> }
  1329. function TCustomListEnumerator<T>.DoMoveNext: boolean;
  1330. begin
  1331. Inc(FIndex);
  1332. Result := (FList.FLength <> 0) and (FIndex < FList.FLength)
  1333. end;
  1334. function TCustomListEnumerator<T>.DoGetCurrent: T;
  1335. begin
  1336. Result := GetCurrent;
  1337. end;
  1338. function TCustomListEnumerator<T>.GetCurrent: T;
  1339. begin
  1340. Result := FList.FItems[FIndex];
  1341. end;
  1342. constructor TCustomListEnumerator<T>.Create(AList: TCustomList<T>);
  1343. begin
  1344. inherited Create;
  1345. FIndex := -1;
  1346. FList := AList;
  1347. end;
  1348. { TCustomListWithPointers<T>.TPointersEnumerator }
  1349. function TCustomListWithPointers<T>.TPointersEnumerator.DoMoveNext: boolean;
  1350. begin
  1351. Inc(FIndex);
  1352. Result := (FList.FLength <> 0) and (FIndex < FList.FLength)
  1353. end;
  1354. function TCustomListWithPointers<T>.TPointersEnumerator.DoGetCurrent: PT;
  1355. begin
  1356. Result := @FList.FItems[FIndex];;
  1357. end;
  1358. constructor TCustomListWithPointers<T>.TPointersEnumerator.Create(AList: TCustomListWithPointers<T>);
  1359. begin
  1360. inherited Create;
  1361. FIndex := -1;
  1362. FList := AList;
  1363. end;
  1364. { TCustomListWithPointers<T> }
  1365. function TCustomListWithPointers<T>.GetPtrEnumerator: TEnumerator<PT>;
  1366. begin
  1367. Result := TPointersEnumerator.Create(Self);
  1368. end;
  1369. { TList<T> }
  1370. procedure TList<T>.InitializeList;
  1371. begin
  1372. end;
  1373. constructor TList<T>.Create;
  1374. begin
  1375. InitializeList;
  1376. FComparer := TComparer<T>.Default;
  1377. end;
  1378. constructor TList<T>.Create(const AComparer: IComparer<T>);
  1379. begin
  1380. InitializeList;
  1381. FComparer := AComparer;
  1382. end;
  1383. constructor TList<T>.Create(ACollection: TEnumerable<T>);
  1384. var
  1385. LItem: T;
  1386. begin
  1387. Create;
  1388. for LItem in ACollection do
  1389. Add(LItem);
  1390. end;
  1391. constructor TList<T>.Create(aValues : Array of T);
  1392. var
  1393. LItem: T;
  1394. begin
  1395. Create;
  1396. for LItem in aValues do
  1397. Add(LItem);
  1398. end;
  1399. {$IFDEF ENABLE_METHODS_WITH_TEnumerableWithPointers}
  1400. constructor TList<T>.Create(ACollection: TEnumerableWithPointers<T>);
  1401. var
  1402. LItem: PT;
  1403. begin
  1404. Create;
  1405. for LItem in ACollection.Ptr^ do
  1406. Add(LItem^);
  1407. end;
  1408. {$ENDIF}
  1409. destructor TList<T>.Destroy;
  1410. begin
  1411. SetCapacity(0);
  1412. end;
  1413. procedure TList<T>.SetCapacity(AValue: SizeInt);
  1414. begin
  1415. if AValue < Count then
  1416. Count := AValue;
  1417. SetLength(FItems, AValue);
  1418. end;
  1419. procedure TList<T>.SetCount(AValue: SizeInt);
  1420. begin
  1421. if AValue < 0 then
  1422. raise EArgumentOutOfRangeException.CreateRes(@SArgumentOutOfRange);
  1423. if AValue > Capacity then
  1424. Capacity := AValue;
  1425. if AValue < Count then
  1426. DeleteRange(AValue, Count - AValue);
  1427. FLength := AValue;
  1428. end;
  1429. function TList<T>.GetItem(AIndex: SizeInt): T;
  1430. begin
  1431. if (AIndex < 0) or (AIndex >= Count) then
  1432. raise EArgumentOutOfRangeException.CreateRes(@SArgumentOutOfRange);
  1433. Result := FItems[AIndex];
  1434. end;
  1435. procedure TList<T>.SetItem(AIndex: SizeInt; const AValue: T);
  1436. begin
  1437. if (AIndex < 0) or (AIndex >= Count) then
  1438. raise EArgumentOutOfRangeException.CreateRes(@SArgumentOutOfRange);
  1439. Notify(FItems[AIndex], cnRemoved);
  1440. FItems[AIndex] := AValue;
  1441. Notify(AValue, cnAdded);
  1442. end;
  1443. function TList<T>.GetEnumerator: TEnumerator;
  1444. begin
  1445. Result := TEnumerator.Create(Self);
  1446. end;
  1447. function TList<T>.DoGetEnumerator: {Generics.Collections.}TEnumerator<T>;
  1448. begin
  1449. Result := GetEnumerator;
  1450. end;
  1451. function TList<T>.Add(const AValue: T): SizeInt;
  1452. begin
  1453. Result := PrepareAddingItem;
  1454. FItems[Result] := AValue;
  1455. Notify(AValue, cnAdded);
  1456. end;
  1457. procedure TList<T>.AddRange(const AValues: array of T);
  1458. begin
  1459. InsertRange(Count, AValues);
  1460. end;
  1461. procedure TList<T>.AddRange(const AEnumerable: IEnumerable<T>);
  1462. var
  1463. LValue: T;
  1464. begin
  1465. for LValue in AEnumerable do
  1466. Add(LValue);
  1467. end;
  1468. procedure TList<T>.AddRange(AEnumerable: TEnumerable<T>);
  1469. var
  1470. LValue: T;
  1471. begin
  1472. for LValue in AEnumerable do
  1473. Add(LValue);
  1474. end;
  1475. {$IFDEF ENABLE_METHODS_WITH_TEnumerableWithPointers}
  1476. procedure TList<T>.AddRange(AEnumerable: TEnumerableWithPointers<T>);
  1477. var
  1478. LValue: PT;
  1479. begin
  1480. for LValue in AEnumerable.Ptr^ do
  1481. Add(LValue^);
  1482. end;
  1483. {$ENDIF}
  1484. procedure TList<T>.InternalInsert(AIndex: SizeInt; const AValue: T);
  1485. begin
  1486. if AIndex <> PrepareAddingItem then
  1487. begin
  1488. System.Move(FItems[AIndex], FItems[AIndex + 1], ((Count - AIndex) - 1) * SizeOf(T));
  1489. FillChar(FItems[AIndex], SizeOf(T), 0);
  1490. end;
  1491. FItems[AIndex] := AValue;
  1492. Notify(AValue, cnAdded);
  1493. end;
  1494. procedure TList<T>.Insert(AIndex: SizeInt; const AValue: T);
  1495. begin
  1496. if (AIndex < 0) or (AIndex > Count) then
  1497. raise EArgumentOutOfRangeException.CreateRes(@SArgumentOutOfRange);
  1498. InternalInsert(AIndex, AValue);
  1499. end;
  1500. procedure TList<T>.InsertRange(AIndex: SizeInt; const AValues: array of T);
  1501. var
  1502. i: SizeInt;
  1503. LLength: SizeInt;
  1504. LValue: ^T;
  1505. begin
  1506. if (AIndex < 0) or (AIndex > Count) then
  1507. raise EArgumentOutOfRangeException.CreateRes(@SArgumentOutOfRange);
  1508. LLength := Length(AValues);
  1509. if LLength = 0 then
  1510. Exit;
  1511. if AIndex <> PrepareAddingRange(LLength) then
  1512. begin
  1513. System.Move(FItems[AIndex], FItems[AIndex + LLength], ((Count - AIndex) - LLength) * SizeOf(T));
  1514. FillChar(FItems[AIndex], SizeOf(T) * LLength, 0);
  1515. end;
  1516. LValue := @AValues[0];
  1517. for i := AIndex to Pred(AIndex + LLength) do
  1518. begin
  1519. FItems[i] := LValue^;
  1520. Notify(LValue^, cnAdded);
  1521. Inc(LValue);
  1522. end;
  1523. end;
  1524. procedure TList<T>.InsertRange(AIndex: SizeInt; const AEnumerable: IEnumerable<T>);
  1525. var
  1526. LValue: T;
  1527. i: SizeInt;
  1528. begin
  1529. if (AIndex < 0) or (AIndex > Count) then
  1530. raise EArgumentOutOfRangeException.CreateRes(@SArgumentOutOfRange);
  1531. i := 0;
  1532. for LValue in AEnumerable do
  1533. begin
  1534. InternalInsert(Aindex + i, LValue);
  1535. Inc(i);
  1536. end;
  1537. end;
  1538. procedure TList<T>.InsertRange(AIndex: SizeInt; const AEnumerable: TEnumerable<T>);
  1539. var
  1540. LValue: T;
  1541. i: SizeInt;
  1542. begin
  1543. if (AIndex < 0) or (AIndex > Count) then
  1544. raise EArgumentOutOfRangeException.CreateRes(@SArgumentOutOfRange);
  1545. i := 0;
  1546. for LValue in AEnumerable do
  1547. begin
  1548. InternalInsert(Aindex + i, LValue);
  1549. Inc(i);
  1550. end;
  1551. end;
  1552. procedure TList<T>.Pack;
  1553. begin
  1554. Pack(
  1555. function(const L, R: T): Boolean
  1556. begin
  1557. Result := FComparer.Compare(L, R) = 0;
  1558. end);
  1559. end;
  1560. procedure TList<T>.Pack(const IsEmpty: TEmptyFunc);
  1561. var
  1562. I: Integer;
  1563. begin
  1564. for I := Count - 1 downto 0 do
  1565. if IsEmpty(List[I], Default(T)) then
  1566. DoRemove(I, cnRemoved);
  1567. end;
  1568. {$IFDEF ENABLE_METHODS_WITH_TEnumerableWithPointers}
  1569. procedure TList<T>.InsertRange(AIndex: SizeInt; const AEnumerable: TEnumerableWithPointers<T>);
  1570. var
  1571. LValue: PT;
  1572. i: SizeInt;
  1573. begin
  1574. if (AIndex < 0) or (AIndex > Count) then
  1575. raise EArgumentOutOfRangeException.CreateRes(@SArgumentOutOfRange);
  1576. i := 0;
  1577. for LValue in AEnumerable.Ptr^ do
  1578. begin
  1579. InternalInsert(Aindex + i, LValue^);
  1580. Inc(i);
  1581. end;
  1582. end;
  1583. {$ENDIF}
  1584. function TList<T>.Remove(const AValue: T): SizeInt;
  1585. begin
  1586. Result := IndexOf(AValue);
  1587. if Result >= 0 then
  1588. DoRemove(Result, cnRemoved);
  1589. end;
  1590. function TList<T>.RemoveItem(const Value: T; Direction: TDirection): SizeInt;
  1591. begin
  1592. if Direction=TDirection.FromBeginning then
  1593. Result:=Remove(Value)
  1594. else
  1595. begin
  1596. Result:=LastIndexOf(Value);
  1597. if Result>=0 then
  1598. DoRemove(Result, cnRemoved);
  1599. end;
  1600. end;
  1601. procedure TList<T>.Delete(AIndex: SizeInt);
  1602. begin
  1603. DoRemove(AIndex, cnRemoved);
  1604. end;
  1605. procedure TList<T>.DeleteRange(AIndex, ACount: SizeInt);
  1606. var
  1607. LDeleted: array of T;
  1608. i: SizeInt;
  1609. LMoveDelta: SizeInt;
  1610. begin
  1611. if ACount = 0 then
  1612. Exit;
  1613. if (ACount < 0) or (AIndex < 0) or (AIndex + ACount > Count) then
  1614. raise EArgumentOutOfRangeException.CreateRes(@SArgumentOutOfRange);
  1615. LDeleted := nil;
  1616. SetLength(LDeleted, ACount);
  1617. System.Move(FItems[AIndex], LDeleted[0], ACount * SizeOf(T));
  1618. LMoveDelta := Count - (AIndex + ACount);
  1619. if LMoveDelta = 0 then
  1620. FillChar(FItems[AIndex], ACount * SizeOf(T), #0)
  1621. else
  1622. begin
  1623. System.Move(FItems[AIndex + ACount], FItems[AIndex], LMoveDelta * SizeOf(T));
  1624. FillChar(FItems[Count - ACount], ACount * SizeOf(T), #0);
  1625. end;
  1626. Dec(FLength, ACount);
  1627. for i := 0 to High(LDeleted) do
  1628. Notify(LDeleted[i], cnRemoved);
  1629. end;
  1630. function TList<T>.ExtractIndex(const AIndex: SizeInt): T;
  1631. begin
  1632. Result := DoRemove(AIndex, cnExtracted);
  1633. end;
  1634. function TList<T>.ExtractAt(const AIndex: SizeInt): T;
  1635. begin
  1636. Result:=ExtractIndex(AIndex);
  1637. end;
  1638. function TList<T>.Extract(const AValue: T): T;
  1639. var
  1640. LIndex: SizeInt;
  1641. begin
  1642. LIndex := IndexOf(AValue);
  1643. if LIndex < 0 then
  1644. Exit(Default(T));
  1645. Result := DoRemove(LIndex, cnExtracted);
  1646. end;
  1647. procedure TList<T>.Exchange(AIndex1, AIndex2: SizeInt);
  1648. var
  1649. LTemp: T;
  1650. begin
  1651. LTemp := FItems[AIndex1];
  1652. FItems[AIndex1] := FItems[AIndex2];
  1653. FItems[AIndex2] := LTemp;
  1654. end;
  1655. procedure TList<T>.Move(AIndex, ANewIndex: SizeInt);
  1656. var
  1657. LTemp: T;
  1658. begin
  1659. if ANewIndex = AIndex then
  1660. Exit;
  1661. if (ANewIndex < 0) or (ANewIndex >= Count) then
  1662. raise EArgumentOutOfRangeException.CreateRes(@SArgumentOutOfRange);
  1663. LTemp := FItems[AIndex];
  1664. FItems[AIndex] := Default(T);
  1665. if AIndex < ANewIndex then
  1666. System.Move(FItems[Succ(AIndex)], FItems[AIndex], (ANewIndex - AIndex) * SizeOf(T))
  1667. else
  1668. System.Move(FItems[ANewIndex], FItems[Succ(ANewIndex)], (AIndex - ANewIndex) * SizeOf(T));
  1669. FillChar(FItems[ANewIndex], SizeOf(T), #0);
  1670. FItems[ANewIndex] := LTemp;
  1671. end;
  1672. function TList<T>.First: T;
  1673. begin
  1674. Result := Items[0];
  1675. end;
  1676. function TList<T>.Last: T;
  1677. begin
  1678. Result := Items[Pred(Count)];
  1679. end;
  1680. procedure TList<T>.Clear;
  1681. begin
  1682. SetCount(0);
  1683. SetCapacity(0);
  1684. end;
  1685. procedure TList<T>.TrimExcess;
  1686. begin
  1687. SetCapacity(Count);
  1688. end;
  1689. function TList<T>.Contains(const AValue: T): Boolean;
  1690. begin
  1691. Result := IndexOf(AValue) >= 0;
  1692. end;
  1693. function TList<T>.IndexOf(const AValue: T): SizeInt;
  1694. var
  1695. i: SizeInt;
  1696. begin
  1697. for i := 0 to Count - 1 do
  1698. if FComparer.Compare(AValue, FItems[i]) = 0 then
  1699. Exit(i);
  1700. Result := -1;
  1701. end;
  1702. function TList<T>.LastIndexOf(const AValue: T): SizeInt;
  1703. var
  1704. i: SizeInt;
  1705. begin
  1706. for i := Count - 1 downto 0 do
  1707. if FComparer.Compare(AValue, FItems[i]) = 0 then
  1708. Exit(i);
  1709. Result := -1;
  1710. end;
  1711. procedure TList<T>.Reverse;
  1712. var
  1713. a, b: SizeInt;
  1714. LTemp: T;
  1715. begin
  1716. a := 0;
  1717. b := Count - 1;
  1718. while a < b do
  1719. begin
  1720. LTemp := FItems[a];
  1721. FItems[a] := FItems[b];
  1722. FItems[b] := LTemp;
  1723. Inc(a);
  1724. Dec(b);
  1725. end;
  1726. end;
  1727. procedure TList<T>.Sort;
  1728. begin
  1729. TArrayHelperBugHack.Sort(FItems, FComparer, 0, Count);
  1730. end;
  1731. procedure TList<T>.Sort(const AComparer: IComparer<T>);
  1732. begin
  1733. TArrayHelperBugHack.Sort(FItems, AComparer, 0, Count);
  1734. end;
  1735. function TList<T>.BinarySearch(const AItem: T; out AIndex: SizeInt): Boolean;
  1736. begin
  1737. Result := TArrayHelperBugHack.BinarySearch(FItems, AItem, AIndex, FComparer, 0, Count);
  1738. end;
  1739. function TList<T>.BinarySearch(const AItem: T; out AIndex: SizeInt; const AComparer: IComparer<T>): Boolean;
  1740. begin
  1741. Result := TArrayHelperBugHack.BinarySearch(FItems, AItem, AIndex, AComparer, 0, Count);
  1742. end;
  1743. { TSortedList<T> }
  1744. procedure TSortedList<T>.InitializeList;
  1745. begin
  1746. FSortStyle := cssAuto;
  1747. end;
  1748. function TSortedList<T>.Add(const AValue: T): SizeInt;
  1749. var
  1750. LSearchResult: TBinarySearchResult;
  1751. begin
  1752. if SortStyle <> cssAuto then
  1753. Exit(inherited Add(AValue));
  1754. if TArrayHelperBugHack.BinarySearch(FItems, AValue, LSearchResult, FComparer, 0, Count) then
  1755. case FDuplicates of
  1756. dupAccept: Result := LSearchResult.FoundIndex;
  1757. dupIgnore: Exit(LSearchResult.FoundIndex);
  1758. dupError: raise EListError.Create(SCollectionDuplicate);
  1759. end
  1760. else
  1761. begin
  1762. if LSearchResult.CandidateIndex = -1 then
  1763. Result := 0
  1764. else
  1765. if LSearchResult.CompareResult > 0 then
  1766. Result := LSearchResult.CandidateIndex
  1767. else
  1768. Result := LSearchResult.CandidateIndex + 1;
  1769. end;
  1770. InternalInsert(Result, AValue);
  1771. end;
  1772. procedure TSortedList<T>.Insert(AIndex: SizeInt; const AValue: T);
  1773. begin
  1774. if FSortStyle = cssAuto then
  1775. raise EListError.Create(SSortedListError)
  1776. else
  1777. inherited;
  1778. end;
  1779. procedure TSortedList<T>.Exchange(AIndex1, AIndex2: SizeInt);
  1780. begin
  1781. if FSortStyle = cssAuto then
  1782. raise EListError.Create(SSortedListError)
  1783. else
  1784. inherited;
  1785. end;
  1786. procedure TSortedList<T>.Move(AIndex, ANewIndex: SizeInt);
  1787. begin
  1788. if FSortStyle = cssAuto then
  1789. raise EListError.Create(SSortedListError)
  1790. else
  1791. inherited;
  1792. end;
  1793. procedure TSortedList<T>.AddRange(const AValues: array of T);
  1794. var
  1795. i: T;
  1796. begin
  1797. for i in AValues do
  1798. Add(i);
  1799. end;
  1800. procedure TSortedList<T>.InsertRange(AIndex: SizeInt; const AValues: array of T);
  1801. var
  1802. LValue: T;
  1803. i: SizeInt;
  1804. begin
  1805. if (AIndex < 0) or (AIndex > Count) then
  1806. raise EArgumentOutOfRangeException.CreateRes(@SArgumentOutOfRange);
  1807. i := 0;
  1808. for LValue in AValues do
  1809. begin
  1810. InternalInsert(AIndex + i, LValue);
  1811. Inc(i);
  1812. end;
  1813. end;
  1814. function TSortedList<T>.GetSorted: boolean;
  1815. begin
  1816. Result := FSortStyle in [cssAuto, cssUser];
  1817. end;
  1818. procedure TSortedList<T>.SetSorted(AValue: boolean);
  1819. begin
  1820. if AValue then
  1821. SortStyle := cssAuto
  1822. else
  1823. SortStyle := cssNone;
  1824. end;
  1825. procedure TSortedList<T>.SetSortStyle(AValue: TCollectionSortStyle);
  1826. begin
  1827. if FSortStyle = AValue then
  1828. Exit;
  1829. if AValue = cssAuto then
  1830. Sort;
  1831. FSortStyle := AValue;
  1832. end;
  1833. function TSortedList<T>.ConsistencyCheck(ARaiseException: boolean = true): boolean;
  1834. var
  1835. i: Integer;
  1836. LCompare: SizeInt;
  1837. begin
  1838. if Sorted then
  1839. for i := 0 to Count-2 do
  1840. begin
  1841. LCompare := FComparer.Compare(FItems[i], FItems[i+1]);
  1842. if LCompare = 0 then
  1843. begin
  1844. if Duplicates <> dupAccept then
  1845. if ARaiseException then
  1846. raise EListError.Create(SCollectionDuplicate)
  1847. else
  1848. Exit(False)
  1849. end
  1850. else
  1851. if LCompare > 0 then
  1852. if ARaiseException then
  1853. raise EListError.Create(SCollectionInconsistency)
  1854. else
  1855. Exit(False)
  1856. end;
  1857. Result := True;
  1858. end;
  1859. { TThreadList<T> }
  1860. constructor TThreadList<T>.Create;
  1861. begin
  1862. inherited Create;
  1863. FDuplicates:=dupIgnore;
  1864. {$ifdef FPC_HAS_FEATURE_THREADING}
  1865. InitCriticalSection(FLock);
  1866. {$endif}
  1867. FList := TList<T>.Create;
  1868. end;
  1869. destructor TThreadList<T>.Destroy;
  1870. begin
  1871. LockList;
  1872. try
  1873. FList.Free;
  1874. inherited Destroy;
  1875. finally
  1876. UnlockList;
  1877. {$ifdef FPC_HAS_FEATURE_THREADING}
  1878. DoneCriticalSection(FLock);
  1879. {$endif}
  1880. end;
  1881. end;
  1882. procedure TThreadList<T>.Add(const AValue: T);
  1883. begin
  1884. LockList;
  1885. try
  1886. if (Duplicates = dupAccept) or (FList.IndexOf(AValue) = -1) then
  1887. FList.Add(AValue)
  1888. else if Duplicates = dupError then
  1889. raise EArgumentException.CreateRes(@SDuplicatesNotAllowed);
  1890. finally
  1891. UnlockList;
  1892. end;
  1893. end;
  1894. procedure TThreadList<T>.Remove(const AValue: T);
  1895. begin
  1896. LockList;
  1897. try
  1898. FList.Remove(AValue);
  1899. finally
  1900. UnlockList;
  1901. end;
  1902. end;
  1903. procedure TThreadList<T>.Clear;
  1904. begin
  1905. LockList;
  1906. try
  1907. FList.Clear;
  1908. finally
  1909. UnlockList;
  1910. end;
  1911. end;
  1912. function TThreadList<T>.LockList: TList<T>;
  1913. begin
  1914. Result:=FList;
  1915. {$ifdef FPC_HAS_FEATURE_THREADING}
  1916. System.EnterCriticalSection(FLock);
  1917. {$endif}
  1918. end;
  1919. procedure TThreadList<T>.UnlockList;
  1920. begin
  1921. {$ifdef FPC_HAS_FEATURE_THREADING}
  1922. System.LeaveCriticalSection(FLock);
  1923. {$endif}
  1924. end;
  1925. { TQueue<T>.TPointersEnumerator }
  1926. function TQueue<T>.TPointersEnumerator.DoMoveNext: boolean;
  1927. begin
  1928. Inc(FIndex);
  1929. Result := (FQueue.FLength <> 0) and (FIndex < FQueue.FLength)
  1930. end;
  1931. function TQueue<T>.TPointersEnumerator.DoGetCurrent: PT;
  1932. begin
  1933. Result := @FQueue.FItems[FIndex];
  1934. end;
  1935. constructor TQueue<T>.TPointersEnumerator.Create(AQueue: TQueue<T>);
  1936. begin
  1937. inherited Create;
  1938. FIndex := Pred(AQueue.FLow);
  1939. FQueue := AQueue;
  1940. end;
  1941. { TQueue<T>.TEnumerator }
  1942. constructor TQueue<T>.TEnumerator.Create(AQueue: TQueue<T>);
  1943. begin
  1944. inherited Create(AQueue);
  1945. FIndex := Pred(AQueue.FLow);
  1946. end;
  1947. { TQueue<T> }
  1948. function TQueue<T>.PrepareAddingItem: SizeInt;
  1949. begin
  1950. repeat
  1951. result := FLength;
  1952. if result <= High(FItems) then
  1953. begin
  1954. FLength := result + 1;
  1955. exit;
  1956. end;
  1957. if SizeUint(FLow) >= 4 + SizeUint(result) div 4 then
  1958. // If the empty space at the beginning is comparable to queue size, convert
  1959. //
  1960. // .......QQQQQQQQQ
  1961. // ↑FLow ↑FLength=length(FItems)
  1962. //
  1963. // to
  1964. //
  1965. // QQQQQQQQQ.......
  1966. // ↑FLow=0
  1967. //
  1968. // and retry the shortcut above.
  1969. MoveToFront
  1970. else
  1971. exit(inherited);
  1972. until false;
  1973. end;
  1974. function TQueue<T>.GetPtrEnumerator: TEnumerator<PT>;
  1975. begin
  1976. Result := TPointersenumerator.Create(Self);
  1977. end;
  1978. function TQueue<T>.GetEnumerator: TEnumerator;
  1979. begin
  1980. Result := TEnumerator.Create(Self);
  1981. end;
  1982. function TQueue<T>.DoGetEnumerator: {Generics.Collections.}TEnumerator<T>;
  1983. begin
  1984. Result := GetEnumerator;
  1985. end;
  1986. function TQueue<T>.DoRemove(AIndex: SizeInt; ACollectionNotification: TCollectionNotification): T;
  1987. begin
  1988. if Count = 0 then
  1989. raise EArgumentOutOfRangeException.CreateRes(@SArgumentOutOfRange);
  1990. Result := FItems[AIndex];
  1991. FItems[AIndex] := Default(T);
  1992. Inc(FLow);
  1993. if FLow = FLength then
  1994. begin
  1995. FLow := 0;
  1996. FLength := 0;
  1997. end;
  1998. Notify(Result, ACollectionNotification);
  1999. end;
  2000. procedure TQueue<T>.MoveToFront;
  2001. var
  2002. i: SizeInt;
  2003. begin
  2004. if FLength > FLow then
  2005. if IsManagedType(T) then
  2006. for i := 0 to FLength - FLow - 1 do
  2007. FItems[i] := FItems[FLow + i]
  2008. else
  2009. Move(FItems[FLow], FItems[0], (FLength - FLow) * SizeOf(T));
  2010. FLength := FLength - FLow;
  2011. FLow := 0;
  2012. end;
  2013. procedure TQueue<T>.SetCapacity(AValue: SizeInt);
  2014. begin
  2015. if AValue < Count then
  2016. raise EArgumentOutOfRangeException.CreateRes(@SArgumentOutOfRange);
  2017. if AValue = FLength then
  2018. Exit;
  2019. MoveToFront;
  2020. SetLength(FItems, AValue);
  2021. end;
  2022. function TQueue<T>.GetCount: SizeInt;
  2023. begin
  2024. Result := FLength - FLow;
  2025. end;
  2026. constructor TQueue<T>.Create(ACollection: TEnumerable<T>);
  2027. var
  2028. LItem: T;
  2029. begin
  2030. for LItem in ACollection do
  2031. Enqueue(LItem);
  2032. end;
  2033. {$IFDEF ENABLE_METHODS_WITH_TEnumerableWithPointers}
  2034. constructor TQueue<T>.Create(ACollection: TEnumerableWithPointers<T>);
  2035. var
  2036. LItem: PT;
  2037. begin
  2038. for LItem in ACollection.Ptr^ do
  2039. Enqueue(LItem^);
  2040. end;
  2041. {$ENDIF}
  2042. destructor TQueue<T>.Destroy;
  2043. begin
  2044. Clear;
  2045. end;
  2046. procedure TQueue<T>.Enqueue(const AValue: T);
  2047. var
  2048. LIndex: SizeInt;
  2049. begin
  2050. LIndex := PrepareAddingItem;
  2051. FItems[LIndex] := AValue;
  2052. Notify(AValue, cnAdded);
  2053. end;
  2054. function TQueue<T>.Dequeue: T;
  2055. begin
  2056. Result := DoRemove(FLow, cnRemoved);
  2057. end;
  2058. function TQueue<T>.Extract: T;
  2059. begin
  2060. Result := DoRemove(FLow, cnExtracted);
  2061. end;
  2062. function TQueue<T>.Peek: T;
  2063. begin
  2064. if (Count = 0) then
  2065. raise EArgumentOutOfRangeException.CreateRes(@SArgumentOutOfRange);
  2066. Result := FItems[FLow];
  2067. end;
  2068. procedure TQueue<T>.Clear;
  2069. begin
  2070. while Count <> 0 do
  2071. Dequeue;
  2072. FLow := 0;
  2073. FLength := 0;
  2074. end;
  2075. procedure TQueue<T>.TrimExcess;
  2076. begin
  2077. SetCapacity(Count);
  2078. end;
  2079. { TStack<T> }
  2080. function TStack<T>.GetEnumerator: TEnumerator;
  2081. begin
  2082. Result := TEnumerator.Create(Self);
  2083. end;
  2084. function TStack<T>.DoGetEnumerator: {Generics.Collections.}TEnumerator<T>;
  2085. begin
  2086. Result := GetEnumerator;
  2087. end;
  2088. constructor TStack<T>.Create(ACollection: TEnumerable<T>);
  2089. var
  2090. LItem: T;
  2091. begin
  2092. for LItem in ACollection do
  2093. Push(LItem);
  2094. end;
  2095. {$IFDEF ENABLE_METHODS_WITH_TEnumerableWithPointers}
  2096. constructor TStack<T>.Create(ACollection: TEnumerableWithPointers<T>);
  2097. var
  2098. LItem: PT;
  2099. begin
  2100. for LItem in ACollection.Ptr^ do
  2101. Push(LItem^);
  2102. end;
  2103. {$ENDIF}
  2104. function TStack<T>.DoRemove(AIndex: SizeInt; ACollectionNotification: TCollectionNotification): T;
  2105. begin
  2106. if (AIndex < 0) or (Count = 0) then
  2107. raise EArgumentOutOfRangeException.CreateRes(@SArgumentOutOfRange);
  2108. Result := FItems[AIndex];
  2109. FItems[AIndex] := Default(T);
  2110. Dec(FLength);
  2111. Notify(Result, ACollectionNotification);
  2112. end;
  2113. destructor TStack<T>.Destroy;
  2114. begin
  2115. Clear;
  2116. end;
  2117. procedure TStack<T>.Clear;
  2118. begin
  2119. while Count <> 0 do
  2120. Pop;
  2121. end;
  2122. procedure TStack<T>.SetCapacity(AValue: SizeInt);
  2123. begin
  2124. if AValue < Count then
  2125. AValue := Count;
  2126. SetLength(FItems, AValue);
  2127. end;
  2128. procedure TStack<T>.Push(const AValue: T);
  2129. var
  2130. LIndex: SizeInt;
  2131. begin
  2132. LIndex := PrepareAddingItem;
  2133. FItems[LIndex] := AValue;
  2134. Notify(AValue, cnAdded);
  2135. end;
  2136. function TStack<T>.Pop: T;
  2137. begin
  2138. Result := DoRemove(FLength - 1, cnRemoved);
  2139. end;
  2140. function TStack<T>.Peek: T;
  2141. begin
  2142. if (Count = 0) then
  2143. raise EArgumentOutOfRangeException.CreateRes(@SArgumentOutOfRange);
  2144. Result := FItems[FLength - 1];
  2145. end;
  2146. function TStack<T>.Extract: T;
  2147. begin
  2148. Result := DoRemove(FLength - 1, cnExtracted);
  2149. end;
  2150. procedure TStack<T>.TrimExcess;
  2151. begin
  2152. SetCapacity(Count);
  2153. end;
  2154. { TObjectList<T> }
  2155. procedure TObjectList<T>.Notify(const AValue: T; ACollectionNotification: TCollectionNotification);
  2156. begin
  2157. inherited Notify(AValue, ACollectionNotification);
  2158. if FObjectsOwner and (ACollectionNotification = cnRemoved) then
  2159. TObject(AValue).Free;
  2160. end;
  2161. constructor TObjectList<T>.Create(AOwnsObjects: Boolean);
  2162. begin
  2163. inherited Create;
  2164. FObjectsOwner := AOwnsObjects;
  2165. end;
  2166. constructor TObjectList<T>.Create(const AComparer: IComparer<T>; AOwnsObjects: Boolean);
  2167. begin
  2168. inherited Create(AComparer);
  2169. FObjectsOwner := AOwnsObjects;
  2170. end;
  2171. constructor TObjectList<T>.Create(ACollection: TEnumerable<T>; AOwnsObjects: Boolean);
  2172. begin
  2173. inherited Create(ACollection);
  2174. FObjectsOwner := AOwnsObjects;
  2175. end;
  2176. {$IFDEF ENABLE_METHODS_WITH_TEnumerableWithPointers}
  2177. constructor TObjectList<T>.Create(ACollection: TEnumerableWithPointers<T>; AOwnsObjects: Boolean);
  2178. begin
  2179. inherited Create(ACollection);
  2180. FObjectsOwner := AOwnsObjects;
  2181. end;
  2182. {$ENDIF}
  2183. { TObjectQueue<T> }
  2184. procedure TObjectQueue<T>.Notify(const AValue: T; ACollectionNotification: TCollectionNotification);
  2185. begin
  2186. inherited Notify(AValue, ACollectionNotification);
  2187. if FObjectsOwner and (ACollectionNotification = cnRemoved) then
  2188. TObject(AValue).Free;
  2189. end;
  2190. constructor TObjectQueue<T>.Create(AOwnsObjects: Boolean);
  2191. begin
  2192. inherited Create;
  2193. FObjectsOwner := AOwnsObjects;
  2194. end;
  2195. constructor TObjectQueue<T>.Create(ACollection: TEnumerable<T>; AOwnsObjects: Boolean);
  2196. begin
  2197. inherited Create(ACollection);
  2198. FObjectsOwner := AOwnsObjects;
  2199. end;
  2200. {$IFDEF ENABLE_METHODS_WITH_TEnumerableWithPointers}
  2201. constructor TObjectQueue<T>.Create(ACollection: TEnumerableWithPointers<T>; AOwnsObjects: Boolean);
  2202. begin
  2203. inherited Create(ACollection);
  2204. FObjectsOwner := AOwnsObjects;
  2205. end;
  2206. {$ENDIF}
  2207. procedure TObjectQueue<T>.Dequeue;
  2208. begin
  2209. inherited Dequeue;
  2210. end;
  2211. { TObjectStack<T> }
  2212. procedure TObjectStack<T>.Notify(const AValue: T; ACollectionNotification: TCollectionNotification);
  2213. begin
  2214. inherited Notify(AValue, ACollectionNotification);
  2215. if FObjectsOwner and (ACollectionNotification = cnRemoved) then
  2216. TObject(AValue).Free;
  2217. end;
  2218. constructor TObjectStack<T>.Create(AOwnsObjects: Boolean);
  2219. begin
  2220. inherited Create;
  2221. FObjectsOwner := AOwnsObjects;
  2222. end;
  2223. constructor TObjectStack<T>.Create(ACollection: TEnumerable<T>; AOwnsObjects: Boolean);
  2224. begin
  2225. inherited Create(ACollection);
  2226. FObjectsOwner := AOwnsObjects;
  2227. end;
  2228. {$IFDEF ENABLE_METHODS_WITH_TEnumerableWithPointers}
  2229. constructor TObjectStack<T>.Create(ACollection: TEnumerableWithPointers<T>; AOwnsObjects: Boolean);
  2230. begin
  2231. inherited Create(ACollection);
  2232. FObjectsOwner := AOwnsObjects;
  2233. end;
  2234. {$ENDIF}
  2235. function TObjectStack<T>.Pop: T;
  2236. begin
  2237. Result := inherited Pop;
  2238. end;
  2239. {$I inc\generics.dictionaries.inc}
  2240. { TCustomSet<T>.TCustomSetEnumerator }
  2241. function TCustomSet<T>.TCustomSetEnumerator.DoMoveNext: boolean;
  2242. begin
  2243. Result := FEnumerator.DoMoveNext;
  2244. end;
  2245. function TCustomSet<T>.TCustomSetEnumerator.DoGetCurrent: T;
  2246. begin
  2247. Result := FEnumerator.DoGetCurrent;
  2248. end;
  2249. destructor TCustomSet<T>.TCustomSetEnumerator.Destroy;
  2250. begin
  2251. FEnumerator.Free;
  2252. end;
  2253. { TCustomSet<T> }
  2254. function TCustomSet<T>.DoGetEnumerator: {$IFDEF FPC_DOTTEDUNITS}System.{$ENDIF}Generics.Collections.TEnumerator<T>;
  2255. begin
  2256. Result := GetEnumerator;
  2257. end;
  2258. constructor TCustomSet<T>.Create(ACollection: TEnumerable<T>);
  2259. var
  2260. i: T;
  2261. begin
  2262. Create;
  2263. for i in ACollection do
  2264. Add(i);
  2265. end;
  2266. {$IFDEF ENABLE_METHODS_WITH_TEnumerableWithPointers}
  2267. constructor TCustomSet<T>.Create(ACollection: TEnumerableWithPointers<T>);
  2268. var
  2269. i: PT;
  2270. begin
  2271. Create;
  2272. for i in ACollection.Ptr^ do
  2273. Add(i^);
  2274. end;
  2275. {$ENDIF}
  2276. function TCustomSet<T>.AddRange(const AValues: array of T): Boolean;
  2277. var
  2278. i: T;
  2279. begin
  2280. Result := True;
  2281. for i in AValues do
  2282. Result := Add(i) and Result;
  2283. end;
  2284. function TCustomSet<T>.AddRange(const AEnumerable: IEnumerable<T>): Boolean;
  2285. var
  2286. i: T;
  2287. begin
  2288. Result := True;
  2289. for i in AEnumerable do
  2290. Result := Add(i) and Result;
  2291. end;
  2292. function TCustomSet<T>.AddRange(AEnumerable: TEnumerable<T>): Boolean;
  2293. var
  2294. i: T;
  2295. begin
  2296. Result := True;
  2297. for i in AEnumerable do
  2298. Result := Add(i) and Result;
  2299. end;
  2300. {$IFDEF ENABLE_METHODS_WITH_TEnumerableWithPointers}
  2301. function TCustomSet<T>.AddRange(AEnumerable: TEnumerableWithPointers<T>): Boolean;
  2302. var
  2303. i: PT;
  2304. begin
  2305. Result := True;
  2306. for i in AEnumerable.Ptr^ do
  2307. Result := Add(i^) and Result;
  2308. end;
  2309. {$ENDIF}
  2310. procedure TCustomSet<T>.UnionWith(AHashSet: TCustomSet<T>);
  2311. var
  2312. i: PT;
  2313. begin
  2314. for i in AHashSet.Ptr^ do
  2315. Add(i^);
  2316. end;
  2317. procedure TCustomSet<T>.IntersectWith(AHashSet: TCustomSet<T>);
  2318. var
  2319. LList: TList<PT>;
  2320. i: PT;
  2321. begin
  2322. LList := TList<PT>.Create;
  2323. for i in Ptr^ do
  2324. if not AHashSet.Contains(i^) then
  2325. LList.Add(i);
  2326. for i in LList do
  2327. Remove(i^);
  2328. LList.Free;
  2329. end;
  2330. procedure TCustomSet<T>.ExceptWith(AHashSet: TCustomSet<T>);
  2331. var
  2332. i: PT;
  2333. begin
  2334. for i in AHashSet.Ptr^ do
  2335. Remove(i^);
  2336. end;
  2337. procedure TCustomSet<T>.SymmetricExceptWith(AHashSet: TCustomSet<T>);
  2338. var
  2339. LList: TList<PT>;
  2340. i: PT;
  2341. begin
  2342. LList := TList<PT>.Create;
  2343. for i in AHashSet.Ptr^ do
  2344. if Contains(i^) then
  2345. LList.Add(i)
  2346. else
  2347. Add(i^);
  2348. for i in LList do
  2349. Remove(i^);
  2350. LList.Free;
  2351. end;
  2352. { THashSet<T>.THashSetEnumerator }
  2353. function THashSet<T>.THashSetEnumerator.GetCurrent: T;
  2354. begin
  2355. Result := TDictionaryEnumerator(FEnumerator).GetCurrent;
  2356. end;
  2357. constructor THashSet<T>.THashSetEnumerator.Create(ASet: TCustomSet<T>);
  2358. begin
  2359. TDictionaryEnumerator(FEnumerator) := THashSet<T>(ASet).FInternalDictionary.Keys.DoGetEnumerator;
  2360. end;
  2361. { THashSet<T>.TPointersEnumerator }
  2362. function THashSet<T>.TPointersEnumerator.DoMoveNext: boolean;
  2363. begin
  2364. Result := FEnumerator.MoveNext;
  2365. end;
  2366. function THashSet<T>.TPointersEnumerator.DoGetCurrent: PT;
  2367. begin
  2368. Result := FEnumerator.Current;
  2369. end;
  2370. constructor THashSet<T>.TPointersEnumerator.Create(AHashSet: THashSet<T>);
  2371. begin
  2372. FEnumerator := AHashSet.FInternalDictionary.Keys.Ptr^.GetEnumerator;
  2373. end;
  2374. { THashSet<T> }
  2375. procedure THashSet<T>.InternalDictionaryNotify(ASender: TObject; const AItem: T; AAction: TCollectionNotification);
  2376. begin
  2377. FOnNotify(Self, AItem, AAction);
  2378. end;
  2379. function THashSet<T>.GetPtrEnumerator: TEnumerator<PT>;
  2380. begin
  2381. Result := TPointersEnumerator.Create(Self);
  2382. end;
  2383. function THashSet<T>.GetCount: SizeInt;
  2384. begin
  2385. Result := FInternalDictionary.Count;
  2386. end;
  2387. function THashSet<T>.GetCapacity: SizeInt;
  2388. begin
  2389. Result := FInternalDictionary.Capacity;
  2390. end;
  2391. procedure THashSet<T>.SetCapacity(AValue: SizeInt);
  2392. begin
  2393. FInternalDictionary.Capacity := AValue;
  2394. end;
  2395. function THashSet<T>.GetOnNotify: TCollectionNotifyEvent<T>;
  2396. begin
  2397. Result := FInternalDictionary.OnKeyNotify;
  2398. end;
  2399. procedure THashSet<T>.SetOnNotify(AValue: TCollectionNotifyEvent<T>);
  2400. begin
  2401. FOnNotify := AValue;
  2402. if Assigned(AValue) then
  2403. FInternalDictionary.OnKeyNotify := InternalDictionaryNotify
  2404. else
  2405. FInternalDictionary.OnKeyNotify := nil;
  2406. end;
  2407. function THashSet<T>.GetEnumerator: TCustomSetEnumerator;
  2408. begin
  2409. Result := THashSetEnumerator.Create(Self);
  2410. end;
  2411. constructor THashSet<T>.Create;
  2412. begin
  2413. FInternalDictionary := TOpenAddressingLP<T, TEmptyRecord>.Create;
  2414. end;
  2415. constructor THashSet<T>.Create(const AComparer: IEqualityComparer<T>);
  2416. begin
  2417. FInternalDictionary := TOpenAddressingLP<T, TEmptyRecord>.Create(AComparer);
  2418. end;
  2419. destructor THashSet<T>.Destroy;
  2420. begin
  2421. FInternalDictionary.Free;
  2422. end;
  2423. function THashSet<T>.Add(const AValue: T): Boolean;
  2424. begin
  2425. Result := not FInternalDictionary.ContainsKey(AValue);
  2426. if Result then
  2427. FInternalDictionary.Add(AValue, EmptyRecord);
  2428. end;
  2429. function THashSet<T>.Remove(const AValue: T): Boolean;
  2430. var
  2431. LIndex: SizeInt;
  2432. begin
  2433. LIndex := FInternalDictionary.FindBucketIndex(AValue);
  2434. Result := LIndex >= 0;
  2435. if Result then
  2436. FInternalDictionary.DoRemove(LIndex, cnRemoved);
  2437. end;
  2438. function THashSet<T>.Extract(const AValue: T): T;
  2439. var
  2440. LIndex: SizeInt;
  2441. begin
  2442. LIndex := FInternalDictionary.FindBucketIndex(AValue);
  2443. if LIndex < 0 then
  2444. Exit(Default(T));
  2445. Result := AValue;
  2446. FInternalDictionary.DoRemove(LIndex, cnExtracted);
  2447. end;
  2448. procedure THashSet<T>.Clear;
  2449. begin
  2450. FInternalDictionary.Clear;
  2451. end;
  2452. function THashSet<T>.Contains(const AValue: T): Boolean;
  2453. begin
  2454. Result := FInternalDictionary.ContainsKey(AValue);
  2455. end;
  2456. procedure THashSet<T>.TrimExcess;
  2457. begin
  2458. FInternalDictionary.TrimExcess;
  2459. end;
  2460. { TAVLTreeNode<TREE_CONSTRAINTS, TTree> }
  2461. function TAVLTreeNode<TREE_CONSTRAINTS, TTree>.Successor: PNode;
  2462. begin
  2463. Result:=Right;
  2464. if Result<>nil then begin
  2465. while (Result.Left<>nil) do Result:=Result.Left;
  2466. end else begin
  2467. Result:=@Self;
  2468. while (Result.Parent<>nil) and (Result.Parent.Right=Result) do
  2469. Result:=Result.Parent;
  2470. Result:=Result.Parent;
  2471. end;
  2472. end;
  2473. function TAVLTreeNode<TREE_CONSTRAINTS, TTree>.Precessor: PNode;
  2474. begin
  2475. Result:=Left;
  2476. if Result<>nil then begin
  2477. while (Result.Right<>nil) do Result:=Result.Right;
  2478. end else begin
  2479. Result:=@Self;
  2480. while (Result.Parent<>nil) and (Result.Parent.Left=Result) do
  2481. Result:=Result.Parent;
  2482. Result:=Result.Parent;
  2483. end;
  2484. end;
  2485. function TAVLTreeNode<TREE_CONSTRAINTS, TTree>.TreeDepth: integer;
  2486. // longest WAY down. e.g. only one node => 0 !
  2487. var LeftDepth, RightDepth: integer;
  2488. begin
  2489. if Left<>nil then
  2490. LeftDepth:=Left.TreeDepth+1
  2491. else
  2492. LeftDepth:=0;
  2493. if Right<>nil then
  2494. RightDepth:=Right.TreeDepth+1
  2495. else
  2496. RightDepth:=0;
  2497. if LeftDepth>RightDepth then
  2498. Result:=LeftDepth
  2499. else
  2500. Result:=RightDepth;
  2501. end;
  2502. procedure TAVLTreeNode<TREE_CONSTRAINTS, TTree>.ConsistencyCheck(ATree: TObject);
  2503. var
  2504. LTree: TTree absolute ATree;
  2505. LeftDepth: SizeInt;
  2506. RightDepth: SizeInt;
  2507. begin
  2508. // test left child
  2509. if Left<>nil then begin
  2510. if Left.Parent<>@Self then
  2511. raise EAVLTree.Create('Left.Parent<>Self');
  2512. if LTree.Compare(Left.Data.Key,Data.Key)>0 then
  2513. raise EAVLTree.Create('Compare(Left.Data,Data)>0');
  2514. Left.ConsistencyCheck(LTree);
  2515. end;
  2516. // test right child
  2517. if Right<>nil then begin
  2518. if Right.Parent<>@Self then
  2519. raise EAVLTree.Create('Right.Parent<>Self');
  2520. if LTree.Compare(Data.Key,Right.Data.Key)>0 then
  2521. raise EAVLTree.Create('Compare(Data,Right.Data)>0');
  2522. Right.ConsistencyCheck(LTree);
  2523. end;
  2524. // test balance
  2525. if Left<>nil then
  2526. LeftDepth:=Left.TreeDepth+1
  2527. else
  2528. LeftDepth:=0;
  2529. if Right<>nil then
  2530. RightDepth:=Right.TreeDepth+1
  2531. else
  2532. RightDepth:=0;
  2533. if Balance<>(LeftDepth-RightDepth) then
  2534. raise EAVLTree.CreateFmt('Balance[%d]<>(RightDepth[%d]-LeftDepth[%d])', [Balance, RightDepth, LeftDepth]);
  2535. end;
  2536. function TAVLTreeNode<TREE_CONSTRAINTS, TTree>.GetCount: SizeInt;
  2537. begin
  2538. Result:=1;
  2539. if Assigned(Left) then Inc(Result,Left.GetCount);
  2540. if Assigned(Right) then Inc(Result,Right.GetCount);
  2541. end;
  2542. { TCustomTreeEnumerator<T, PNode, TTree> }
  2543. function TCustomTreeEnumerator<T, PNode, TTree>.DoGetCurrent: T;
  2544. begin
  2545. Result := GetCurrent;
  2546. end;
  2547. constructor TCustomTreeEnumerator<T, PNode, TTree>.Create(ATree: TObject);
  2548. begin
  2549. TObject(FTree) := ATree;
  2550. end;
  2551. { TTreeEnumerable<TTreeEnumerator, TTreePointersEnumerator, T, PT, TREE_CONSTRAINTS> }
  2552. function TTreeEnumerable<TTreeEnumerator, TTreePointersEnumerator, T, PT, PNode, TTree>.GetCount: SizeInt;
  2553. begin
  2554. Result := FTree.Count;
  2555. end;
  2556. function TTreeEnumerable<TTreeEnumerator, TTreePointersEnumerator, T, PT, PNode, TTree>.GetPtrEnumerator: TEnumerator<PT>;
  2557. begin
  2558. Result := TTreePointersEnumerator.Create(FTree);
  2559. end;
  2560. constructor TTreeEnumerable<TTreeEnumerator, TTreePointersEnumerator, T, PT, PNode, TTree>.Create(
  2561. ATree: TTree);
  2562. begin
  2563. FTree := ATree;
  2564. end;
  2565. function TTreeEnumerable<TTreeEnumerator, TTreePointersEnumerator, T, PT, PNode, TTree>.
  2566. DoGetEnumerator: TTreeEnumerator;
  2567. begin
  2568. Result := TTreeEnumerator.Create(FTree);
  2569. end;
  2570. function TTreeEnumerable<TTreeEnumerator, TTreePointersEnumerator, T, PT, PNode, TTree>.ToArray: TArray<T>;
  2571. begin
  2572. Result := ToArrayImpl(FTree.Count);
  2573. end;
  2574. { TAVLTreeEnumerator<T, PNode, TTree> }
  2575. function TAVLTreeEnumerator<T, PNode, TTree>.DoMoveNext: Boolean;
  2576. begin
  2577. if FLowToHigh then begin
  2578. if FCurrent<>nil then
  2579. FCurrent:=FCurrent.Successor
  2580. else
  2581. FCurrent:=FTree.FindLowest;
  2582. end else begin
  2583. if FCurrent<>nil then
  2584. FCurrent:=FCurrent.Precessor
  2585. else
  2586. FCurrent:=FTree.FindHighest;
  2587. end;
  2588. Result:=FCurrent<>nil;
  2589. end;
  2590. constructor TAVLTreeEnumerator<T, PNode, TTree>.Create(ATree: TObject; ALowToHigh: boolean);
  2591. begin
  2592. inherited Create(ATree);
  2593. FLowToHigh:=aLowToHigh;
  2594. end;
  2595. { TCustomAVLTreeMap<TREE_CONSTRAINTS>.TPairEnumerator }
  2596. function TCustomAVLTreeMap<TREE_CONSTRAINTS>.TPairEnumerator.GetCurrent: TTreePair;
  2597. begin
  2598. Result := TTreePair((@FCurrent.Data)^);
  2599. end;
  2600. { TCustomAVLTreeMap<TREE_CONSTRAINTS>.TNodeEnumerator }
  2601. function TCustomAVLTreeMap<TREE_CONSTRAINTS>.TNodeEnumerator.GetCurrent: PNode;
  2602. begin
  2603. Result := FCurrent;
  2604. end;
  2605. { TCustomAVLTreeMap<TREE_CONSTRAINTS>.TKeyEnumerator }
  2606. function TCustomAVLTreeMap<TREE_CONSTRAINTS>.TKeyEnumerator.GetCurrent: TKey;
  2607. begin
  2608. Result := FCurrent.Key;
  2609. end;
  2610. { TCustomAVLTreeMap<TREE_CONSTRAINTS>.TPKeyEnumerator }
  2611. function TCustomAVLTreeMap<TREE_CONSTRAINTS>.TPKeyEnumerator.GetCurrent: PKey;
  2612. begin
  2613. Result := @FCurrent.Data.Key;
  2614. end;
  2615. { TCustomAVLTreeMap<TREE_CONSTRAINTS>.TValueEnumerator }
  2616. function TCustomAVLTreeMap<TREE_CONSTRAINTS>.TValueEnumerator.GetCurrent: TValue;
  2617. begin
  2618. Result := FCurrent.Value;
  2619. end;
  2620. { TCustomAVLTreeMap<TREE_CONSTRAINTS>.TValueEnumerator }
  2621. function TCustomAVLTreeMap<TREE_CONSTRAINTS>.TPValueEnumerator.GetCurrent: PValue;
  2622. begin
  2623. Result := @FCurrent.Data.Value;
  2624. end;
  2625. { TCustomAVLTreeMap<TREE_CONSTRAINTS> }
  2626. procedure TCustomAVLTreeMap<TREE_CONSTRAINTS>.NodeAdded(ANode: PNode);
  2627. begin
  2628. end;
  2629. procedure TCustomAVLTreeMap<TREE_CONSTRAINTS>.DeletingNode(ANode: PNode; AOrigin: boolean);
  2630. begin
  2631. end;
  2632. function TCustomAVLTreeMap<TREE_CONSTRAINTS>.DoRemove(ANode: PNode;
  2633. ACollectionNotification: TCollectionNotification; ADispose: boolean): TValue;
  2634. begin
  2635. if ANode=nil then
  2636. raise EArgumentNilException.CreateRes(@SArgumentNilNode);
  2637. if (ANode.Left = nil) or (ANode.Right = nil) then
  2638. DeletingNode(ANode, true);
  2639. InternalDelete(ANode);
  2640. Dec(FCount);
  2641. NodeNotify(ANode, ACollectionNotification, ADispose);
  2642. if ADispose then
  2643. Dispose(ANode);
  2644. end;
  2645. procedure TCustomAVLTreeMap<TREE_CONSTRAINTS>.DisposeAllNodes(ANode: PNode);
  2646. begin
  2647. if ANode.Left<>nil then
  2648. DisposeAllNodes(ANode.Left);
  2649. if ANode.Right<>nil then
  2650. DisposeAllNodes(ANode.Right);
  2651. NodeNotify(ANode, cnRemoved, true);
  2652. Dispose(ANode);
  2653. end;
  2654. function TCustomAVLTreeMap<TREE_CONSTRAINTS>.Compare(const ALeft, ARight: TKey): Integer; inline;
  2655. begin
  2656. Result := FComparer.Compare(ALeft, ARight);
  2657. end;
  2658. function TCustomAVLTreeMap<TREE_CONSTRAINTS>.FindPredecessor(ANode: PNode): PNode;
  2659. begin
  2660. if ANode <> nil then
  2661. begin
  2662. if ANode.Left <> nil then
  2663. begin
  2664. ANode := ANode.Left;
  2665. while ANode.Right <> nil do ANode := ANode.Right;
  2666. end
  2667. else
  2668. repeat
  2669. Result := ANode;
  2670. ANode := ANode.Parent;
  2671. until (ANode = nil) or (ANode.Right = Result);
  2672. end;
  2673. Result := ANode;
  2674. end;
  2675. function TCustomAVLTreeMap<TREE_CONSTRAINTS>.FindInsertNode(ANode: PNode; out AInsertNode: PNode): Integer;
  2676. begin
  2677. AInsertNode := FRoot;
  2678. if AInsertNode = nil then // first item in tree
  2679. Exit(0);
  2680. repeat
  2681. Result := Compare(ANode.Key,AInsertNode.Key);
  2682. if Result < 0 then
  2683. begin
  2684. Result:=-1;
  2685. if AInsertNode.Left = nil then
  2686. Exit;
  2687. AInsertNode := AInsertNode.Left;
  2688. end
  2689. else
  2690. begin
  2691. if Result > 0 then
  2692. Result:=1;
  2693. if AInsertNode.Right = nil then
  2694. Exit;
  2695. AInsertNode := AInsertNode.Right;
  2696. if Result = 0 then
  2697. Break;
  2698. end;
  2699. until false;
  2700. // for equal items (when item already exist) we need to keep 0 result
  2701. while true do
  2702. if Compare(ANode.Key,AInsertNode.Key) < 0 then
  2703. begin
  2704. if AInsertNode.Left = nil then
  2705. Exit;
  2706. AInsertNode := AInsertNode.Left;
  2707. end
  2708. else
  2709. begin
  2710. if AInsertNode.Right = nil then
  2711. Exit;
  2712. AInsertNode := AInsertNode.Right;
  2713. end;
  2714. end;
  2715. procedure TCustomAVLTreeMap<TREE_CONSTRAINTS>.RotateRightRight(ANode: PNode);
  2716. var
  2717. LNode, LParent: PNode;
  2718. begin
  2719. LNode := ANode.Right;
  2720. LParent := ANode.Parent;
  2721. ANode.Right := LNode.Left;
  2722. if ANode.Right <> nil then
  2723. ANode.Right.Parent := ANode;
  2724. LNode.Left := ANode;
  2725. LNode.Parent := LParent;
  2726. ANode.Parent := LNode;
  2727. if LParent <> nil then
  2728. begin
  2729. if LParent.Left = ANode then
  2730. LParent.Left := LNode
  2731. else
  2732. LParent.Right := LNode;
  2733. end
  2734. else
  2735. FRoot := LNode;
  2736. if LNode.Balance = -1 then
  2737. begin
  2738. ANode.Balance := 0;
  2739. LNode.Balance := 0;
  2740. end
  2741. else
  2742. begin
  2743. ANode.Balance := -1;
  2744. LNode.Balance := 1;
  2745. end
  2746. end;
  2747. procedure TCustomAVLTreeMap<TREE_CONSTRAINTS>.RotateLeftLeft(ANode: PNode);
  2748. var
  2749. LNode, LParent: PNode;
  2750. begin
  2751. LNode := ANode.Left;
  2752. LParent := ANode.Parent;
  2753. ANode.Left := LNode.Right;
  2754. if ANode.Left <> nil then
  2755. ANode.Left.Parent := ANode;
  2756. LNode.Right := ANode;
  2757. LNode.Parent := LParent;
  2758. ANode.Parent := LNode;
  2759. if LParent <> nil then
  2760. begin
  2761. if LParent.Left = ANode then
  2762. LParent.Left := LNode
  2763. else
  2764. LParent.Right := LNode;
  2765. end
  2766. else
  2767. FRoot := LNode;
  2768. if LNode.Balance = 1 then
  2769. begin
  2770. ANode.Balance := 0;
  2771. LNode.Balance := 0;
  2772. end
  2773. else
  2774. begin
  2775. ANode.Balance := 1;
  2776. LNode.Balance := -1;
  2777. end
  2778. end;
  2779. procedure TCustomAVLTreeMap<TREE_CONSTRAINTS>.RotateRightLeft(ANode: PNode);
  2780. var
  2781. LRight, LLeft, LParent: PNode;
  2782. begin
  2783. LRight := ANode.Right;
  2784. LLeft := LRight.Left;
  2785. LParent := ANode.Parent;
  2786. LRight.Left := LLeft.Right;
  2787. if LRight.Left <> nil then
  2788. LRight.Left.Parent := LRight;
  2789. ANode.Right := LLeft.Left;
  2790. if ANode.Right <> nil then
  2791. ANode.Right.Parent := ANode;
  2792. LLeft.Left := ANode;
  2793. LLeft.Right := LRight;
  2794. ANode.Parent := LLeft;
  2795. LRight.Parent := LLeft;
  2796. LLeft.Parent := LParent;
  2797. if LParent <> nil then
  2798. begin
  2799. if LParent.Left = ANode then
  2800. LParent.Left := LLeft
  2801. else
  2802. LParent.Right := LLeft;
  2803. end
  2804. else
  2805. FRoot := LLeft;
  2806. if LLeft.Balance = -1 then
  2807. ANode.Balance := 1
  2808. else
  2809. ANode.Balance := 0;
  2810. if LLeft.Balance = 1 then
  2811. LRight.Balance := -1
  2812. else
  2813. LRight.Balance := 0;
  2814. LLeft.Balance := 0;
  2815. end;
  2816. procedure TCustomAVLTreeMap<TREE_CONSTRAINTS>.RotateLeftRight(ANode: PNode);
  2817. var
  2818. LLeft, LRight, LParent: PNode;
  2819. begin
  2820. LLeft := ANode.Left;
  2821. LRight := LLeft.Right;
  2822. LParent := ANode.Parent;
  2823. LLeft.Right := LRight.Left;
  2824. if LLeft.Right <> nil then
  2825. LLeft.Right.Parent := LLeft;
  2826. ANode.Left := LRight.Right;
  2827. if ANode.Left <> nil then
  2828. ANode.Left.Parent := ANode;
  2829. LRight.Right := ANode;
  2830. LRight.Left := LLeft;
  2831. ANode.Parent := LRight;
  2832. LLeft.Parent := LRight;
  2833. LRight.Parent := LParent;
  2834. if LParent <> nil then
  2835. begin
  2836. if LParent.Left = ANode then
  2837. LParent.Left := LRight
  2838. else
  2839. LParent.Right := LRight;
  2840. end
  2841. else
  2842. FRoot := LRight;
  2843. if LRight.Balance = 1 then
  2844. ANode.Balance := -1
  2845. else
  2846. ANode.Balance := 0;
  2847. if LRight.Balance = -1 then
  2848. LLeft.Balance := 1
  2849. else
  2850. LLeft.Balance := 0;
  2851. LRight.Balance := 0;
  2852. end;
  2853. procedure TCustomAVLTreeMap<TREE_CONSTRAINTS>.KeyNotify(const AKey: TKey; ACollectionNotification: TCollectionNotification);
  2854. begin
  2855. if Assigned(FOnKeyNotify) then
  2856. FOnKeyNotify(Self, AKey, ACollectionNotification);
  2857. end;
  2858. procedure TCustomAVLTreeMap<TREE_CONSTRAINTS>.ValueNotify(const AValue: TValue; ACollectionNotification: TCollectionNotification);
  2859. begin
  2860. if Assigned(FOnValueNotify) then
  2861. FOnValueNotify(Self, AValue, ACollectionNotification);
  2862. end;
  2863. procedure TCustomAVLTreeMap<TREE_CONSTRAINTS>.NodeNotify(ANode: PNode; ACollectionNotification: TCollectionNotification; ADispose: boolean);
  2864. begin
  2865. if Assigned(FOnValueNotify) then
  2866. FOnNodeNotify(Self, ANode, ACollectionNotification, ADispose);
  2867. KeyNotify(ANode.Key, ACollectionNotification);
  2868. ValueNotify(ANode.Value, ACollectionNotification);
  2869. end;
  2870. procedure TCustomAVLTreeMap<TREE_CONSTRAINTS>.SetValue(var AValue: TValue; const ANewValue: TValue);
  2871. var
  2872. LOldValue: TValue;
  2873. begin
  2874. LOldValue := AValue;
  2875. AValue := ANewValue;
  2876. ValueNotify(LOldValue, cnRemoved);
  2877. ValueNotify(ANewValue, cnAdded);
  2878. end;
  2879. procedure TCustomAVLTreeMap<TREE_CONSTRAINTS>.WriteStr(AStream: TStream; const AText: string);
  2880. begin
  2881. if AText='' then exit;
  2882. AStream.Write(AText[1],Length(AText));
  2883. end;
  2884. function TCustomAVLTreeMap<TREE_CONSTRAINTS>.GetNodeCollection: TNodeCollection;
  2885. begin
  2886. if not Assigned(FNodes) then
  2887. FNodes := TNodeCollection.Create(TTree(Self));
  2888. Result := FNodes;
  2889. end;
  2890. procedure TCustomAVLTreeMap<TREE_CONSTRAINTS>.InternalAdd(ANode, AParent: PNode);
  2891. begin
  2892. Inc(FCount);
  2893. ANode.Parent := AParent;
  2894. NodeAdded(ANode);
  2895. if AParent=nil then
  2896. begin
  2897. FRoot := ANode;
  2898. Exit;
  2899. end;
  2900. // balance after insert
  2901. if AParent.Balance<>0 then
  2902. AParent.Balance := 0
  2903. else
  2904. begin
  2905. if AParent.Left = ANode then
  2906. AParent.Balance := 1
  2907. else
  2908. AParent.Balance := -1;
  2909. ANode := AParent.Parent;
  2910. while ANode <> nil do
  2911. begin
  2912. if ANode.Balance<>0 then
  2913. begin
  2914. if ANode.Balance = 1 then
  2915. begin
  2916. if ANode.Right = AParent then
  2917. ANode.Balance := 0
  2918. else if AParent.Balance = -1 then
  2919. RotateLeftRight(ANode)
  2920. else
  2921. RotateLeftLeft(ANode);
  2922. end
  2923. else
  2924. begin
  2925. if ANode.Left = AParent then
  2926. ANode.Balance := 0
  2927. else if AParent^.Balance = 1 then
  2928. RotateRightLeft(ANode)
  2929. else
  2930. RotateRightRight(ANode);
  2931. end;
  2932. Break;
  2933. end;
  2934. if ANode.Left = AParent then
  2935. ANode.Balance := 1
  2936. else
  2937. ANode.Balance := -1;
  2938. AParent := ANode;
  2939. ANode := ANode.Parent;
  2940. end;
  2941. end;
  2942. end;
  2943. function TCustomAVLTreeMap<TREE_CONSTRAINTS>.InternalAdd(ANode: PNode; ADispisable: boolean): PNode;
  2944. var
  2945. LParent: PNode;
  2946. begin
  2947. Result := ANode;
  2948. case FindInsertNode(ANode, LParent) of
  2949. -1: LParent.Left := ANode;
  2950. 0:
  2951. if Assigned(LParent) then
  2952. case FDuplicates of
  2953. dupAccept: LParent.Right := ANode;
  2954. dupIgnore:
  2955. begin
  2956. LParent.Right := nil;
  2957. if ADispisable then
  2958. Dispose(ANode);
  2959. Exit(LParent);
  2960. end;
  2961. dupError:
  2962. begin
  2963. LParent.Right := nil;
  2964. if ADispisable then
  2965. Dispose(ANode);
  2966. Result := nil;
  2967. raise EListError.Create(SCollectionDuplicate);
  2968. end;
  2969. end;
  2970. 1: LParent.Right := ANode;
  2971. end;
  2972. InternalAdd(ANode, LParent);
  2973. NodeNotify(ANode, cnAdded, false);
  2974. end;
  2975. procedure TCustomAVLTreeMap<TREE_CONSTRAINTS>.InternalDelete(ANode: PNode);
  2976. var
  2977. t, y, z: PNode;
  2978. LNest: boolean;
  2979. begin
  2980. if (ANode.Left <> nil) and (ANode.Right <> nil) then
  2981. begin
  2982. y := FindPredecessor(ANode);
  2983. y.Info := ANode.Info;
  2984. DeletingNode(y, false);
  2985. InternalDelete(y);
  2986. LNest := false;
  2987. end
  2988. else
  2989. begin
  2990. if ANode.Left <> nil then
  2991. begin
  2992. y := ANode.Left;
  2993. ANode.Left := nil;
  2994. end
  2995. else
  2996. begin
  2997. y := ANode.Right;
  2998. ANode.Right := nil;
  2999. end;
  3000. ANode.Balance := 0;
  3001. LNest := true;
  3002. end;
  3003. if y <> nil then
  3004. begin
  3005. y.Parent := ANode.Parent;
  3006. y.Left := ANode.Left;
  3007. if y.Left <> nil then
  3008. y.Left.Parent := y;
  3009. y.Right := ANode.Right;
  3010. if y.Right <> nil then
  3011. y.Right.Parent := y;
  3012. y.Balance := ANode.Balance;
  3013. end;
  3014. if ANode.Parent <> nil then
  3015. begin
  3016. if ANode.Parent.Left = ANode then
  3017. ANode.Parent.Left := y
  3018. else
  3019. ANode.Parent.Right := y;
  3020. end
  3021. else
  3022. FRoot := y;
  3023. if LNest then
  3024. begin
  3025. z := y;
  3026. y := ANode.Parent;
  3027. while y <> nil do
  3028. begin
  3029. if y.Balance = 0 then
  3030. begin
  3031. if y.Left = z then
  3032. y.Balance := -1
  3033. else
  3034. y.Balance := 1;
  3035. break;
  3036. end
  3037. else
  3038. begin
  3039. if ((y.Balance = 1) and (y.Left = z)) or ((y.Balance = -1) and (y.Right = z)) then
  3040. begin
  3041. y.Balance := 0;
  3042. z := y;
  3043. y := y.Parent;
  3044. end
  3045. else
  3046. begin
  3047. if y.Left = z then
  3048. t := y.Right
  3049. else
  3050. t := y.Left;
  3051. if t.Balance = 0 then
  3052. begin
  3053. if y.Balance = 1 then
  3054. RotateLeftLeft(y)
  3055. else
  3056. RotateRightRight(y);
  3057. break;
  3058. end
  3059. else if y.Balance = t.Balance then
  3060. begin
  3061. if y.Balance = 1 then
  3062. RotateLeftLeft(y)
  3063. else
  3064. RotateRightRight(y);
  3065. z := t;
  3066. y := t.Parent;
  3067. end
  3068. else
  3069. begin
  3070. if y.Balance = 1 then
  3071. RotateLeftRight(y)
  3072. else
  3073. RotateRightLeft(y);
  3074. z := y.Parent;
  3075. y := z.Parent;
  3076. end
  3077. end
  3078. end
  3079. end
  3080. end;
  3081. end;
  3082. function TCustomAVLTreeMap<TREE_CONSTRAINTS>.GetKeys: TKeyCollection;
  3083. begin
  3084. if not Assigned(FKeys) then
  3085. FKeys := TKeyCollection.Create(TTree(Self));
  3086. Result := TKeyCollection(FKeys);
  3087. end;
  3088. function TCustomAVLTreeMap<TREE_CONSTRAINTS>.GetValues: TValueCollection;
  3089. begin
  3090. if not Assigned(FValues) then
  3091. FValues := TValueCollection.Create(TTree(Self));
  3092. Result := TValueCollection(FValues);
  3093. end;
  3094. function TCustomAVLTreeMap<TREE_CONSTRAINTS>.GetItem(const AKey: TKey): TValue;
  3095. var
  3096. LNode: PNode;
  3097. // Need to differentiate with TValue template type...
  3098. D : {$IFDEF FPC_DOTTEDUNITS}System.{$ENDIF}Rtti.TValue;
  3099. K : TKey;
  3100. begin
  3101. LNode := Find(AKey);
  3102. if not Assigned(LNode) then
  3103. begin
  3104. K:=aKey;
  3105. {$IFDEF FPC_DOTTEDUNITS}System.{$ENDIF}Rtti.TValue.Make(@K,TypeInfo(TKey),D);
  3106. raise EAVLTree.CreateFmt(SDictionaryKeyNNNDoesNotExist,[D.ToString]);
  3107. end;
  3108. result := LNode.Value;
  3109. end;
  3110. procedure TCustomAVLTreeMap<TREE_CONSTRAINTS>.SetItem(const AKey: TKey; const AValue: TValue);
  3111. begin
  3112. Find(AKey).Value := AValue;
  3113. end;
  3114. constructor TCustomAVLTreeMap<TREE_CONSTRAINTS>.Create;
  3115. begin
  3116. FComparer := TComparer<TKey>.Default;
  3117. end;
  3118. constructor TCustomAVLTreeMap<TREE_CONSTRAINTS>.Create(const AComparer: IComparer<TKey>);
  3119. begin
  3120. FComparer := AComparer;
  3121. end;
  3122. function TCustomAVLTreeMap<TREE_CONSTRAINTS>.NewNode: PNode;
  3123. begin
  3124. Result := AllocMem(SizeOf(TNode));
  3125. Initialize(Result^);
  3126. end;
  3127. function TCustomAVLTreeMap<TREE_CONSTRAINTS>.NewNodeArray(ACount: SizeInt): PNode;
  3128. begin
  3129. Result := AllocMem(ACount * SizeOf(TNode));
  3130. Initialize(Result^, ACount);
  3131. end;
  3132. procedure TCustomAVLTreeMap<TREE_CONSTRAINTS>.NewNodeArray(out AArray: TArray<PNode>; ACount: SizeInt);
  3133. var
  3134. i: Integer;
  3135. begin
  3136. SetLength(AArray, ACount);
  3137. for i := 0 to ACount-1 do
  3138. AArray[i] := NewNode;
  3139. end;
  3140. procedure TCustomAVLTreeMap<TREE_CONSTRAINTS>.DisposeNode(ANode: PNode);
  3141. begin
  3142. Dispose(ANode);
  3143. end;
  3144. procedure TCustomAVLTreeMap<TREE_CONSTRAINTS>.DisposeNodeArray(ANode: PNode; ACount: SizeInt);
  3145. begin
  3146. Finalize(ANode^, ACount);
  3147. FreeMem(ANode);
  3148. end;
  3149. procedure TCustomAVLTreeMap<TREE_CONSTRAINTS>.DisposeNodeArray(var AArray: TArray<PNode>);
  3150. var
  3151. i: Integer;
  3152. begin
  3153. for i := 0 to High(AArray) do
  3154. Dispose(AArray[i]);
  3155. AArray := nil;
  3156. end;
  3157. destructor TCustomAVLTreeMap<TREE_CONSTRAINTS>.Destroy;
  3158. begin
  3159. FKeys.Free;
  3160. FValues.Free;
  3161. FNodes.Free;
  3162. Clear;
  3163. end;
  3164. function TCustomAVLTreeMap<TREE_CONSTRAINTS>.AddNode(ANode: PNode): boolean;
  3165. begin
  3166. Result := ANode=InternalAdd(ANode, false);
  3167. end;
  3168. function TCustomAVLTreeMap<TREE_CONSTRAINTS>.Add(const APair: TTreePair): PNode;
  3169. begin
  3170. Result := NewNode;
  3171. Result.Data.Key := APair.Key;
  3172. Result.Data.Value := APair.Value;
  3173. Result := InternalAdd(Result, true);
  3174. end;
  3175. function TCustomAVLTreeMap<TREE_CONSTRAINTS>.Add(const AKey: TKey; const AValue: TValue): PNode;
  3176. begin
  3177. Result := NewNode;
  3178. Result.Data.Key := AKey;
  3179. Result.Data.Value := AValue;
  3180. Result := InternalAdd(Result, true);
  3181. end;
  3182. function TCustomAVLTreeMap<TREE_CONSTRAINTS>.Remove(const AKey: TKey; ADisposeNode: boolean): boolean;
  3183. var
  3184. LNode: PNode;
  3185. begin
  3186. LNode:=Find(AKey);
  3187. if LNode<>nil then begin
  3188. Delete(LNode, ADisposeNode);
  3189. Result:=true;
  3190. end else
  3191. Result:=false;
  3192. end;
  3193. function TCustomAVLTreeMap<TREE_CONSTRAINTS>.ExtractPair(const AKey: TKey; ADisposeNode: boolean): TTreePair;
  3194. var
  3195. LNode: PNode;
  3196. begin
  3197. LNode:=Find(AKey);
  3198. if LNode<>nil then
  3199. begin
  3200. Result.Key := AKey;
  3201. Result.Value := DoRemove(LNode, cnExtracted, ADisposeNode);
  3202. end else
  3203. Result := Default(TTreePair);
  3204. end;
  3205. function TCustomAVLTreeMap<TREE_CONSTRAINTS>.ExtractPair(const ANode: PNode; ADispose: boolean = true): TTreePair;
  3206. begin
  3207. Result.Key := ANode.Key;
  3208. Result.Value := DoRemove(ANode, cnExtracted, ADispose);
  3209. end;
  3210. function TCustomAVLTreeMap<TREE_CONSTRAINTS>.Extract(const AKey: TKey; ADisposeNode: boolean): PNode;
  3211. begin
  3212. Result:=Find(AKey);
  3213. if Result<>nil then
  3214. begin
  3215. DoRemove(Result, cnExtracted, false);
  3216. if ADisposeNode then
  3217. Result := nil;
  3218. end;
  3219. end;
  3220. function TCustomAVLTreeMap<TREE_CONSTRAINTS>.ExtractNode(ANode: PNode; ADispose: boolean): PNode;
  3221. begin
  3222. DoRemove(ANode, cnExtracted, ADispose);
  3223. if ADispose then
  3224. Result := nil
  3225. else
  3226. Result := ANode;
  3227. end;
  3228. procedure TCustomAVLTreeMap<TREE_CONSTRAINTS>.Delete(ANode: PNode; ADispose: boolean);
  3229. begin
  3230. DoRemove(ANode, cnRemoved, ADispose);
  3231. end;
  3232. procedure TCustomAVLTreeMap<TREE_CONSTRAINTS>.Clear(ADisposeNodes: Boolean);
  3233. begin
  3234. if (FRoot<>nil) and ADisposeNodes then
  3235. DisposeAllNodes(FRoot);
  3236. fRoot:=nil;
  3237. FCount:=0;
  3238. end;
  3239. function TCustomAVLTreeMap<TREE_CONSTRAINTS>.GetEnumerator: TPairEnumerator;
  3240. begin
  3241. Result := TPairEnumerator.Create(Self, true);
  3242. end;
  3243. function TCustomAVLTreeMap<TREE_CONSTRAINTS>.FindLowest: PNode;
  3244. begin
  3245. Result:=FRoot;
  3246. if Result<>nil then
  3247. while Result.Left<>nil do Result:=Result.Left;
  3248. end;
  3249. function TCustomAVLTreeMap<TREE_CONSTRAINTS>.FindHighest: PNode;
  3250. begin
  3251. Result:=FRoot;
  3252. if Result<>nil then
  3253. while Result.Right<>nil do Result:=Result.Right;
  3254. end;
  3255. function TCustomAVLTreeMap<TREE_CONSTRAINTS>.Find(const AKey: TKey): PNode;
  3256. var
  3257. LComp: SizeInt;
  3258. begin
  3259. Result:=FRoot;
  3260. while (Result<>nil) do
  3261. begin
  3262. LComp:=Compare(AKey,Result.Key);
  3263. if LComp=0 then
  3264. Exit;
  3265. if LComp<0 then
  3266. Result:=Result.Left
  3267. else
  3268. Result:=Result.Right
  3269. end;
  3270. end;
  3271. function TCustomAVLTreeMap<TREE_CONSTRAINTS>.ContainsKey(const AKey: TKey; out ANode: PNode): boolean;
  3272. begin
  3273. ANode := Find(AKey);
  3274. Result := Assigned(ANode);
  3275. end;
  3276. function TCustomAVLTreeMap<TREE_CONSTRAINTS>.ContainsKey(const AKey: TKey): boolean; overload; inline;
  3277. begin
  3278. Result := Assigned(Find(AKey));
  3279. end;
  3280. procedure TCustomAVLTreeMap<TREE_CONSTRAINTS>.ConsistencyCheck;
  3281. var
  3282. RealCount: SizeInt;
  3283. begin
  3284. RealCount:=0;
  3285. if FRoot<>nil then begin
  3286. FRoot.ConsistencyCheck(Self);
  3287. RealCount:=FRoot.GetCount;
  3288. end;
  3289. if Count<>RealCount then
  3290. raise EAVLTree.Create('Count<>RealCount');
  3291. end;
  3292. procedure TCustomAVLTreeMap<TREE_CONSTRAINTS>.WriteTreeNode(AStream: TStream; ANode: PNode);
  3293. var
  3294. b: String;
  3295. IsLeft: boolean;
  3296. LParent: PNode;
  3297. WasLeft: Boolean;
  3298. begin
  3299. if ANode=nil then exit;
  3300. WriteTreeNode(AStream, ANode.Right);
  3301. LParent:=ANode;
  3302. WasLeft:=false;
  3303. b:='';
  3304. while LParent<>nil do begin
  3305. if LParent.Parent=nil then begin
  3306. if LParent=ANode then
  3307. b:='--'+b
  3308. else
  3309. b:=' '+b;
  3310. break;
  3311. end;
  3312. IsLeft:=LParent.Parent.Left=LParent;
  3313. if LParent=ANode then begin
  3314. if IsLeft then
  3315. b:='\-'
  3316. else
  3317. b:='/-';
  3318. end else begin
  3319. if WasLeft=IsLeft then
  3320. b:=' '+b
  3321. else
  3322. b:='| '+b;
  3323. end;
  3324. WasLeft:=IsLeft;
  3325. LParent:=LParent.Parent;
  3326. end;
  3327. b:=b+NodeToReportStr(ANode)+LineEnding;
  3328. WriteStr(AStream, b);
  3329. WriteTreeNode(AStream, ANode.Left);
  3330. end;
  3331. procedure TCustomAVLTreeMap<TREE_CONSTRAINTS>.WriteReportToStream(AStream: TStream);
  3332. begin
  3333. WriteStr(AStream, '-Start-of-AVL-Tree-------------------'+LineEnding);
  3334. WriteTreeNode(AStream, fRoot);
  3335. WriteStr(AStream, '-End-Of-AVL-Tree---------------------'+LineEnding);
  3336. end;
  3337. function TCustomAVLTreeMap<TREE_CONSTRAINTS>.NodeToReportStr(ANode: PNode): string;
  3338. begin
  3339. Result:=Format(' Self=%p Parent=%p Balance=%d', [ANode, ANode.Parent, ANode.Balance]);
  3340. end;
  3341. function TCustomAVLTreeMap<TREE_CONSTRAINTS>.ReportAsString: string;
  3342. var ms: TMemoryStream;
  3343. begin
  3344. Result:='';
  3345. ms:=TMemoryStream.Create;
  3346. try
  3347. WriteReportToStream(ms);
  3348. ms.Position:=0;
  3349. SetLength(Result,ms.Size);
  3350. if Result<>'' then
  3351. ms.Read(Result[1],length(Result));
  3352. finally
  3353. ms.Free;
  3354. end;
  3355. end;
  3356. { TIndexedAVLTreeMap<TKey, TValue> }
  3357. procedure TIndexedAVLTreeMap<TKey, TValue>.RotateRightRight(ANode: PNode);
  3358. var
  3359. LOldRight: PNode;
  3360. begin
  3361. LOldRight:=ANode.Right;
  3362. inherited;
  3363. Inc(LOldRight.Data.Info, (1 + ANode.Data.Info));
  3364. end;
  3365. procedure TIndexedAVLTreeMap<TKey, TValue>.RotateLeftLeft(ANode: PNode);
  3366. var
  3367. LOldLeft: PNode;
  3368. begin
  3369. LOldLeft:=ANode.Left;
  3370. inherited;
  3371. Dec(ANode.Data.Info, (1 + LOldLeft.Data.Info));
  3372. end;
  3373. procedure TIndexedAVLTreeMap<TKey, TValue>.RotateRightLeft(ANode: PNode);
  3374. var
  3375. LB, LC: PNode;
  3376. begin
  3377. LB := ANode.Right;
  3378. LC := LB.Left;
  3379. inherited;
  3380. Dec(LB.Data.Info, 1+LC.Info);
  3381. Inc(LC.Data.Info, 1+ANode.Info);
  3382. end;
  3383. procedure TIndexedAVLTreeMap<TKey, TValue>.RotateLeftRight(ANode: PNode);
  3384. var
  3385. LB, LC: PNode;
  3386. begin
  3387. LB := ANode.Left;
  3388. LC := LB.Right;
  3389. inherited;
  3390. Inc(LC.Data.Info, 1+LB.Info);
  3391. Dec(ANode.Data.Info, 1+LC.Info);
  3392. end;
  3393. procedure TIndexedAVLTreeMap<TKey, TValue>.NodeAdded(ANode: PNode);
  3394. var
  3395. LParent, LNode: PNode;
  3396. begin
  3397. FLastNode := nil;
  3398. LNode := ANode;
  3399. repeat
  3400. LParent:=LNode.Parent;
  3401. if (LParent=nil) then break;
  3402. if LParent.Left=LNode then
  3403. Inc(LParent.Data.Info);
  3404. LNode:=LParent;
  3405. until false;
  3406. end;
  3407. procedure TIndexedAVLTreeMap<TKey, TValue>.DeletingNode(ANode: PNode; AOrigin: boolean);
  3408. var
  3409. LParent: PNode;
  3410. begin
  3411. if not AOrigin then
  3412. Dec(ANode.Data.Info);
  3413. FLastNode := nil;
  3414. repeat
  3415. LParent:=ANode.Parent;
  3416. if (LParent=nil) then exit;
  3417. if LParent.Left=ANode then
  3418. Dec(LParent.Data.Info);
  3419. ANode:=LParent;
  3420. until false;
  3421. end;
  3422. function TIndexedAVLTreeMap<TKey, TValue>.GetNodeAtIndex(AIndex: SizeInt): PNode;
  3423. begin
  3424. if (AIndex<0) or (AIndex>=Count) then
  3425. raise EIndexedAVLTree.CreateFmt('TIndexedAVLTree: AIndex %d out of bounds 0..%d', [AIndex, Count]);
  3426. if FLastNode<>nil then begin
  3427. if AIndex=FLastIndex then
  3428. Exit(FLastNode)
  3429. else if AIndex=FLastIndex+1 then begin
  3430. FLastIndex:=AIndex;
  3431. FLastNode:=FLastNode.Successor;
  3432. Exit(FLastNode);
  3433. end else if AIndex=FLastIndex-1 then begin
  3434. FLastIndex:=AIndex;
  3435. FLastNode:=FLastNode.Precessor;
  3436. Exit(FLastNode);
  3437. end;
  3438. end;
  3439. FLastIndex:=AIndex;
  3440. Result:=FRoot;
  3441. repeat
  3442. if Result.Info>AIndex then
  3443. Result:=Result.Left
  3444. else if Result.Info=AIndex then begin
  3445. FLastNode:=Result;
  3446. Exit;
  3447. end
  3448. else begin
  3449. Dec(AIndex, Result.Info+1);
  3450. Result:=Result.Right;
  3451. end;
  3452. until false;
  3453. end;
  3454. function TIndexedAVLTreeMap<TKey, TValue>.NodeToIndex(ANode: PNode): SizeInt;
  3455. var
  3456. LNode: PNode;
  3457. LParent: PNode;
  3458. begin
  3459. if ANode=nil then
  3460. Exit(-1);
  3461. if FLastNode=ANode then
  3462. Exit(FLastIndex);
  3463. LNode:=ANode;
  3464. Result:=LNode.Info;
  3465. repeat
  3466. LParent:=LNode.Parent;
  3467. if LParent=nil then break;
  3468. if LParent.Right=LNode then
  3469. inc(Result,LParent.Info+1);
  3470. LNode:=LParent;
  3471. until false;
  3472. FLastNode:=ANode;
  3473. FLastIndex:=Result;
  3474. end;
  3475. procedure TIndexedAVLTreeMap<TKey, TValue>.ConsistencyCheck;
  3476. var
  3477. LNode: PNode;
  3478. i: SizeInt;
  3479. LeftCount: SizeInt = 0;
  3480. begin
  3481. inherited ConsistencyCheck;
  3482. i:=0;
  3483. for LNode in Self.Nodes do
  3484. begin
  3485. if LNode.Left<>nil then
  3486. LeftCount:=LNode.Left.GetCount
  3487. else
  3488. LeftCount:=0;
  3489. if LNode.Info<>LeftCount then
  3490. raise EIndexedAVLTree.CreateFmt('LNode.LeftCount=%d<>%d',[LNode.Info,LeftCount]);
  3491. if GetNodeAtIndex(i)<>LNode then
  3492. raise EIndexedAVLTree.CreateFmt('GetNodeAtIndex(%d)<>%P',[i,LNode]);
  3493. FLastNode:=nil;
  3494. if GetNodeAtIndex(i)<>LNode then
  3495. raise EIndexedAVLTree.CreateFmt('GetNodeAtIndex(%d)<>%P',[i,LNode]);
  3496. if NodeToIndex(LNode)<>i then
  3497. raise EIndexedAVLTree.CreateFmt('NodeToIndex(%P)<>%d',[LNode,i]);
  3498. FLastNode:=nil;
  3499. if NodeToIndex(LNode)<>i then
  3500. raise EIndexedAVLTree.CreateFmt('NodeToIndex(%P)<>%d',[LNode,i]);
  3501. inc(i);
  3502. end;
  3503. end;
  3504. function TIndexedAVLTreeMap<TKey, TValue>.NodeToReportStr(ANode: PNode): string;
  3505. begin
  3506. Result:=Format(' Self=%p Parent=%p Balance=%d Idx=%d Info=%d',
  3507. [ANode,ANode.Parent, ANode.Balance, NodeToIndex(ANode), ANode.Info]);
  3508. end;
  3509. { TAVLTree<T> }
  3510. function TAVLTree<T>.Add(const AValue: T): PNode;
  3511. begin
  3512. Result := inherited Add(AValue, EmptyRecord);
  3513. end;
  3514. function TAVLTree<T>.AddNode(ANode: PNode): boolean;
  3515. begin
  3516. Result := inherited AddNode(ANode);
  3517. end;
  3518. { TIndexedAVLTree<T> }
  3519. function TIndexedAVLTree<T>.Add(const AValue: T): PNode;
  3520. begin
  3521. Result := inherited Add(AValue, EmptyRecord);
  3522. end;
  3523. function TIndexedAVLTree<T>.AddNode(ANode: PNode): boolean;
  3524. begin
  3525. Result := inherited AddNode(ANode);
  3526. end;
  3527. { TSortedSet<T>.TSortedSetEnumerator }
  3528. function TSortedSet<T>.TSortedSetEnumerator.GetCurrent: T;
  3529. begin
  3530. Result := TTreeEnumerator(FEnumerator).GetCurrent;
  3531. end;
  3532. constructor TSortedSet<T>.TSortedSetEnumerator.Create(ASet: TCustomSet<T>);
  3533. begin
  3534. TTreeEnumerator(FEnumerator) := TSortedSet<T>(ASet).FInternalTree.Keys.DoGetEnumerator;
  3535. end;
  3536. { TSortedSet<T>.TPointersEnumerator }
  3537. function TSortedSet<T>.TPointersEnumerator.DoMoveNext: boolean;
  3538. begin
  3539. Result := FEnumerator.MoveNext;
  3540. end;
  3541. function TSortedSet<T>.TPointersEnumerator.DoGetCurrent: PT;
  3542. begin
  3543. Result := FEnumerator.Current;
  3544. end;
  3545. constructor TSortedSet<T>.TPointersEnumerator.Create(ASortedSet: TSortedSet<T>);
  3546. begin
  3547. FEnumerator := ASortedSet.FInternalTree.Keys.Ptr^.GetEnumerator;
  3548. end;
  3549. { TSortedSet<T> }
  3550. procedure TSortedSet<T>.InternalAVLTreeNotify(ASender: TObject; const AItem: T; AAction: TCollectionNotification);
  3551. begin
  3552. FOnNotify(Self, AItem, AAction);
  3553. end;
  3554. function TSortedSet<T>.GetPtrEnumerator: TEnumerator<PT>;
  3555. begin
  3556. Result := TPointersEnumerator.Create(Self);
  3557. end;
  3558. function TSortedSet<T>.GetCount: SizeInt;
  3559. begin
  3560. Result := FInternalTree.Count;
  3561. end;
  3562. function TSortedSet<T>.GetCapacity: SizeInt;
  3563. begin
  3564. Result := FInternalTree.Count;
  3565. end;
  3566. procedure TSortedSet<T>.SetCapacity(AValue: SizeInt);
  3567. begin
  3568. end;
  3569. function TSortedSet<T>.GetOnNotify: TCollectionNotifyEvent<T>;
  3570. begin
  3571. Result := FInternalTree.OnKeyNotify;
  3572. end;
  3573. procedure TSortedSet<T>.SetOnNotify(AValue: TCollectionNotifyEvent<T>);
  3574. begin
  3575. FOnNotify := AValue;
  3576. if Assigned(AValue) then
  3577. FInternalTree.OnKeyNotify := InternalAVLTreeNotify
  3578. else
  3579. FInternalTree.OnKeyNotify := nil;
  3580. end;
  3581. function TSortedSet<T>.GetEnumerator: TCustomSetEnumerator;
  3582. begin
  3583. Result := TSortedSetEnumerator.Create(Self);
  3584. end;
  3585. constructor TSortedSet<T>.Create;
  3586. begin
  3587. FInternalTree := TAVLTree<T>.Create;
  3588. end;
  3589. constructor TSortedSet<T>.Create(const AComparer: IComparer<T>);
  3590. begin
  3591. FInternalTree := TAVLTree<T>.Create(AComparer);
  3592. end;
  3593. destructor TSortedSet<T>.Destroy;
  3594. begin
  3595. FInternalTree.Free;
  3596. end;
  3597. function TSortedSet<T>.Add(const AValue: T): Boolean;
  3598. var
  3599. LNodePtr, LParent: TAVLTree<T>.PNode;
  3600. LNode: TAVLTree<T>.TNode;
  3601. LCompare: Integer;
  3602. begin
  3603. LNode.Data.Key := AValue;
  3604. LCompare := FInternalTree.FindInsertNode(@LNode, LParent);
  3605. Result := not((LCompare=0) and Assigned(LParent));
  3606. if not Result then
  3607. Exit;
  3608. LNodePtr := FInternalTree.NewNode;
  3609. LNodePtr^.Data.Key := AValue;
  3610. case LCompare of
  3611. -1: LParent.Left := LNodePtr;
  3612. 1: LParent.Right := LNodePtr;
  3613. end;
  3614. FInternalTree.InternalAdd(LNodePtr, LParent);
  3615. FInternalTree.NodeNotify(LNodePtr, cnAdded, false);
  3616. end;
  3617. function TSortedSet<T>.Remove(const AValue: T): Boolean;
  3618. var
  3619. LNode: TAVLTree<T>.PNode;
  3620. begin
  3621. LNode := FInternalTree.Find(AValue);
  3622. Result := Assigned(LNode);
  3623. if Result then
  3624. FInternalTree.Delete(LNode);
  3625. end;
  3626. function TSortedSet<T>.Extract(const AValue: T): T;
  3627. var
  3628. LNode: TAVLTree<T>.PNode;
  3629. begin
  3630. LNode := FInternalTree.Find(AValue);
  3631. if not Assigned(LNode) then
  3632. Exit(Default(T));
  3633. Result := FInternalTree.ExtractPair(LNode).Key;
  3634. end;
  3635. procedure TSortedSet<T>.Clear;
  3636. begin
  3637. FInternalTree.Clear;
  3638. end;
  3639. function TSortedSet<T>.Contains(const AValue: T): Boolean;
  3640. begin
  3641. Result := FInternalTree.ContainsKey(AValue);
  3642. end;
  3643. procedure TSortedSet<T>.TrimExcess;
  3644. begin
  3645. end;
  3646. { TSortedHashSet<T>.TSortedHashSetEqualityComparer }
  3647. function TSortedHashSet<T>.TSortedHashSetEqualityComparer.Equals(const ALeft, ARight: PT): Boolean;
  3648. begin
  3649. if Assigned(FComparer) then
  3650. Result := FComparer.Compare(ALeft^, ARight^) = 0
  3651. else
  3652. Result := FEqualityComparer.Equals(ALeft^, ARight^);
  3653. end;
  3654. function TSortedHashSet<T>.TSortedHashSetEqualityComparer.GetHashCode(const AValue: PT): UInt32;
  3655. begin
  3656. Result := FEqualityComparer.GetHashCode(AValue^);
  3657. end;
  3658. constructor TSortedHashSet<T>.TSortedHashSetEqualityComparer.Create(const AComparer: IComparer<T>);
  3659. begin
  3660. FComparer := AComparer;
  3661. FEqualityComparer := TEqualityComparer<T>.Default;
  3662. end;
  3663. constructor TSortedHashSet<T>.TSortedHashSetEqualityComparer.Create(const AEqualityComparer: IEqualityComparer<T>);
  3664. begin
  3665. FEqualityComparer := AEqualityComparer;
  3666. end;
  3667. constructor TSortedHashSet<T>.TSortedHashSetEqualityComparer.Create(const AComparer: IComparer<T>; const AEqualityComparer: IEqualityComparer<T>);
  3668. begin
  3669. FComparer := AComparer;
  3670. FEqualityComparer := AEqualityComparer;
  3671. end;
  3672. { TSortedHashSet<T>.TSortedHashSetEnumerator }
  3673. function TSortedHashSet<T>.TSortedHashSetEnumerator.GetCurrent: T;
  3674. begin
  3675. Result := TTreeEnumerator(FEnumerator).Current;
  3676. end;
  3677. constructor TSortedHashSet<T>.TSortedHashSetEnumerator.Create(ASet: TCustomSet<T>);
  3678. begin
  3679. FEnumerator := TSortedHashSet<T>(ASet).FInternalTree.Keys.GetEnumerator;
  3680. end;
  3681. { TSortedHashSet<T>.TPointersEnumerator }
  3682. function TSortedHashSet<T>.TPointersEnumerator.DoMoveNext: boolean;
  3683. begin
  3684. Result := FEnumerator.MoveNext;
  3685. end;
  3686. function TSortedHashSet<T>.TPointersEnumerator.DoGetCurrent: PT;
  3687. begin
  3688. Result := FEnumerator.Current;
  3689. end;
  3690. constructor TSortedHashSet<T>.TPointersEnumerator.Create(ASortedHashSet: TSortedHashSet<T>);
  3691. begin
  3692. FEnumerator := ASortedHashSet.FInternalTree.Keys.Ptr^.GetEnumerator;
  3693. end;
  3694. { TSortedHashSet<T> }
  3695. procedure TSortedHashSet<T>.InternalDictionaryNotify(ASender: TObject; const AItem: PT; AAction: TCollectionNotification);
  3696. begin
  3697. FOnNotify(Self, AItem^, AAction);
  3698. end;
  3699. function TSortedHashSet<T>.GetPtrEnumerator: TEnumerator<PT>;
  3700. begin
  3701. Result := TPointersEnumerator.Create(Self);
  3702. end;
  3703. function TSortedHashSet<T>.DoGetEnumerator: TEnumerator<T>;
  3704. begin
  3705. Result := GetEnumerator;
  3706. end;
  3707. function TSortedHashSet<T>.GetCount: SizeInt;
  3708. begin
  3709. Result := FInternalDictionary.Count;
  3710. end;
  3711. function TSortedHashSet<T>.GetCapacity: SizeInt;
  3712. begin
  3713. Result := FInternalDictionary.Capacity;
  3714. end;
  3715. procedure TSortedHashSet<T>.SetCapacity(AValue: SizeInt);
  3716. begin
  3717. FInternalDictionary.Capacity := AValue;
  3718. end;
  3719. function TSortedHashSet<T>.GetOnNotify: TCollectionNotifyEvent<T>;
  3720. begin
  3721. Result := FInternalTree.OnKeyNotify;
  3722. end;
  3723. procedure TSortedHashSet<T>.SetOnNotify(AValue: TCollectionNotifyEvent<T>);
  3724. begin
  3725. FOnNotify := AValue;
  3726. if Assigned(AValue) then
  3727. FInternalDictionary.OnKeyNotify := InternalDictionaryNotify
  3728. else
  3729. FInternalDictionary.OnKeyNotify := nil;
  3730. end;
  3731. function TSortedHashSet<T>.GetEnumerator: TCustomSetEnumerator;
  3732. begin
  3733. Result := TSortedHashSetEnumerator.Create(Self);
  3734. end;
  3735. function TSortedHashSet<T>.Add(const AValue: T): Boolean;
  3736. var
  3737. LNode: TAVLTree<T>.PNode;
  3738. begin
  3739. Result := not FInternalDictionary.ContainsKey(@AValue);
  3740. if Result then
  3741. begin
  3742. LNode := FInternalTree.Add(AValue);
  3743. FInternalDictionary.Add(@LNode.Data.Key, EmptyRecord);
  3744. end;
  3745. end;
  3746. function TSortedHashSet<T>.Remove(const AValue: T): Boolean;
  3747. var
  3748. LIndex: SizeInt;
  3749. begin
  3750. LIndex := FInternalDictionary.FindBucketIndex(@AValue);
  3751. Result := LIndex >= 0;
  3752. if Result then
  3753. begin
  3754. FInternalDictionary.DoRemove(LIndex, cnRemoved);
  3755. FInternalTree.Remove(AValue);
  3756. end;
  3757. end;
  3758. function TSortedHashSet<T>.Extract(const AValue: T): T;
  3759. var
  3760. LIndex: SizeInt;
  3761. begin
  3762. LIndex := FInternalDictionary.FindBucketIndex(@AValue);
  3763. if LIndex >= 0 then
  3764. begin
  3765. FInternalDictionary.DoRemove(LIndex, cnExtracted);
  3766. FInternalTree.Remove(AValue);
  3767. Result := AValue;
  3768. end else
  3769. Result := Default(T);
  3770. end;
  3771. procedure TSortedHashSet<T>.Clear;
  3772. begin
  3773. FInternalDictionary.Clear;
  3774. FInternalTree.Clear;
  3775. end;
  3776. function TSortedHashSet<T>.Contains(const AValue: T): Boolean;
  3777. begin
  3778. Result := FInternalDictionary.ContainsKey(@AValue);
  3779. end;
  3780. constructor TSortedHashSet<T>.Create;
  3781. begin
  3782. FInternalTree := TAVLTree<T>.Create;
  3783. FInternalDictionary := TOpenAddressingLP<PT, TEmptyRecord>.Create(TSortedHashSetEqualityComparer.Create(TEqualityComparer<T>.Default));
  3784. end;
  3785. constructor TSortedHashSet<T>.Create(const AComparer: IEqualityComparer<T>);
  3786. begin
  3787. Create(TComparer<T>.Default, AComparer);
  3788. end;
  3789. constructor TSortedHashSet<T>.Create(const AComparer: IComparer<T>);
  3790. begin
  3791. FInternalTree := TAVLTree<T>.Create(AComparer);
  3792. FInternalDictionary := TOpenAddressingLP<PT, TEmptyRecord>.Create(TSortedHashSetEqualityComparer.Create(AComparer));
  3793. end;
  3794. constructor TSortedHashSet<T>.Create(const AComparer: IComparer<T>; const AEqualityComparer: IEqualityComparer<T>);
  3795. begin
  3796. FInternalTree := TAVLTree<T>.Create(AComparer);
  3797. FInternalDictionary := TOpenAddressingLP<PT, TEmptyRecord>.Create(TSortedHashSetEqualityComparer.Create(AComparer,AEqualityComparer));
  3798. end;
  3799. destructor TSortedHashSet<T>.Destroy;
  3800. begin
  3801. FInternalDictionary.Free;
  3802. FInternalTree.Free;
  3803. inherited;
  3804. end;
  3805. procedure TSortedHashSet<T>.TrimExcess;
  3806. begin
  3807. FInternalDictionary.TrimExcess;
  3808. end;
  3809. end.