generics.defaults.pas 147 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512
  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.Defaults;
  20. {$ENDIF FPC_DOTTEDUNITS}
  21. {$MODE DELPHI}{$H+}
  22. {$POINTERMATH ON}
  23. {$MACRO ON}
  24. {$COPERATORS ON}
  25. {$HINTS OFF}
  26. {$WARNINGS OFF}
  27. {$NOTES OFF}
  28. {$OVERFLOWCHECKS OFF}
  29. {$RANGECHECKS OFF}
  30. interface
  31. {$IFDEF FPC_DOTTEDUNITS}
  32. uses
  33. System.Classes, System.SysUtils, System.Generics.Hashes, System.TypInfo, System.Variants, System.Math, System.Generics.Strings, System.Generics.Helpers;
  34. {$ELSE FPC_DOTTEDUNITS}
  35. uses
  36. Classes, SysUtils, Generics.Hashes, TypInfo, Variants, Math, Generics.Strings, Generics.Helpers;
  37. {$ENDIF FPC_DOTTEDUNITS}
  38. type
  39. IComparer<T> = interface
  40. function Compare(const Left, Right: T): Integer; overload;
  41. end;
  42. TOnComparison<T> = function(const Left, Right: T): Integer of object;
  43. TComparisonFunc<T> = function(const Left, Right: T): Integer;
  44. TComparison<T> = reference to function(const Left, Right: T): Integer;
  45. TComparer<T> = class(TInterfacedObject, IComparer<T>)
  46. public
  47. class function Default: IComparer<T>; static;
  48. function Compare(const ALeft, ARight: T): Integer; virtual; abstract; overload;
  49. class function Construct(const AComparison: TOnComparison<T>): IComparer<T>; overload;
  50. class function Construct(const AComparison: TComparisonFunc<T>): IComparer<T>; overload;
  51. class function Construct(const AComparison: TComparison<T>): IComparer<T>; overload;
  52. end;
  53. TDelegatedComparerEvents<T> = class(TComparer<T>)
  54. private
  55. FComparison: TOnComparison<T>;
  56. public
  57. function Compare(const ALeft, ARight: T): Integer; override;
  58. constructor Create(AComparison: TOnComparison<T>);
  59. end;
  60. TDelegatedComparerFunc<T> = class(TComparer<T>)
  61. private
  62. FComparison: TComparisonFunc<T>;
  63. public
  64. function Compare(const ALeft, ARight: T): Integer; override;
  65. constructor Create(AComparison: TComparisonFunc<T>);
  66. end;
  67. TDelegatedComparer<T> = class(TComparer<T>)
  68. private
  69. FCompareFunc: TComparison<T>;
  70. public
  71. constructor Create(const aCompare: TComparison<T>);
  72. function Compare(const aLeft, aRight: T): Integer; override;
  73. end;
  74. IEqualityComparer<T> = interface
  75. function Equals(const ALeft, ARight: T): Boolean;
  76. function GetHashCode(const AValue: T): UInt32;
  77. end;
  78. IExtendedEqualityComparer<T> = interface(IEqualityComparer<T>)
  79. procedure GetHashList(const AValue: T; AHashList: PUInt32); // for double hashing and more
  80. end;
  81. ShortString1 = string[1];
  82. ShortString2 = string[2];
  83. ShortString3 = string[3];
  84. { TAbstractInterface }
  85. TInterface = class
  86. public
  87. function QueryInterface(constref {%H-}IID: TGUID;{%H-} out Obj): HResult; {$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF}; virtual;
  88. function _AddRef: LongInt; {$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF}; virtual; abstract;
  89. function _Release: LongInt; {$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF}; virtual; abstract;
  90. end;
  91. { TRawInterface }
  92. TRawInterface = class(TInterface)
  93. public
  94. function _AddRef: LongInt; override;
  95. function _Release: LongInt; override;
  96. end;
  97. { TComTypeSizeInterface }
  98. // INTERNAL USE ONLY!
  99. TComTypeSizeInterface = class(TInterface)
  100. public
  101. // warning ! self as PSpoofInterfacedTypeSizeObject
  102. function _AddRef: LongInt; override;
  103. // warning ! self as PSpoofInterfacedTypeSizeObject
  104. function _Release: LongInt; override;
  105. end;
  106. { TSingletonImplementation }
  107. TSingletonImplementation = class(TRawInterface, IInterface)
  108. public
  109. function QueryInterface(constref IID: TGUID; out Obj): HResult; override;
  110. end;
  111. TCompare = class
  112. protected
  113. // warning ! self as PSpoofInterfacedTypeSizeObject
  114. class function _Binary(const ALeft, ARight): Integer;
  115. // warning ! self as PSpoofInterfacedTypeSizeObject
  116. class function _DynArray(const ALeft, ARight: Pointer): Integer;
  117. public
  118. class function Integer(const ALeft, ARight: Integer): Integer;
  119. class function Int8(const ALeft, ARight: Int8): Integer;
  120. class function Int16(const ALeft, ARight: Int16): Integer;
  121. class function Int32(const ALeft, ARight: Int32): Integer;
  122. class function Int64(const ALeft, ARight: Int64): Integer;
  123. class function UInt8(const ALeft, ARight: UInt8): Integer;
  124. class function UInt16(const ALeft, ARight: UInt16): Integer;
  125. class function UInt32(const ALeft, ARight: UInt32): Integer;
  126. class function UInt64(const ALeft, ARight: UInt64): Integer;
  127. class function Single(const ALeft, ARight: Single): Integer;
  128. class function Double(const ALeft, ARight: Double): Integer;
  129. class function Extended(const ALeft, ARight: Extended): Integer;
  130. class function Currency(const ALeft, ARight: Currency): Integer;
  131. class function Comp(const ALeft, ARight: Comp): Integer;
  132. class function Binary(const ALeft, ARight; const ASize: SizeInt): Integer;
  133. class function DynArray(const ALeft, ARight: Pointer; const AElementSize: SizeInt): Integer;
  134. class function ShortString1(const ALeft, ARight: ShortString1): Integer;
  135. class function ShortString2(const ALeft, ARight: ShortString2): Integer;
  136. class function ShortString3(const ALeft, ARight: ShortString3): Integer;
  137. class function &String(const ALeft, ARight: string): Integer;
  138. class function ShortString(const ALeft, ARight: ShortString): Integer;
  139. class function AnsiString(const ALeft, ARight: AnsiString): Integer;
  140. class function WideString(const ALeft, ARight: WideString): Integer;
  141. class function UnicodeString(const ALeft, ARight: UnicodeString): Integer;
  142. class function Method(const ALeft, ARight: TMethod): Integer;
  143. class function Variant(const ALeft, ARight: PVariant): Integer;
  144. class function Pointer(const ALeft, ARight: PtrUInt): Integer;
  145. end;
  146. { TEquals }
  147. TEquals = class
  148. protected
  149. // warning ! self as PSpoofInterfacedTypeSizeObject
  150. class function _Binary(const ALeft, ARight): Boolean;
  151. // warning ! self as PSpoofInterfacedTypeSizeObject
  152. class function _DynArray(const ALeft, ARight: Pointer): Boolean;
  153. public
  154. class function Integer(const ALeft, ARight: Integer): Boolean;
  155. class function Int8(const ALeft, ARight: Int8): Boolean;
  156. class function Int16(const ALeft, ARight: Int16): Boolean;
  157. class function Int32(const ALeft, ARight: Int32): Boolean;
  158. class function Int64(const ALeft, ARight: Int64): Boolean;
  159. class function UInt8(const ALeft, ARight: UInt8): Boolean;
  160. class function UInt16(const ALeft, ARight: UInt16): Boolean;
  161. class function UInt32(const ALeft, ARight: UInt32): Boolean;
  162. class function UInt64(const ALeft, ARight: UInt64): Boolean;
  163. class function Single(const ALeft, ARight: Single): Boolean;
  164. class function Double(const ALeft, ARight: Double): Boolean;
  165. class function Extended(const ALeft, ARight: Extended): Boolean;
  166. class function Currency(const ALeft, ARight: Currency): Boolean;
  167. class function Comp(const ALeft, ARight: Comp): Boolean;
  168. class function Binary(const ALeft, ARight; const ASize: SizeInt): Boolean;
  169. class function DynArray(const ALeft, ARight: Pointer; const AElementSize: SizeInt): Boolean;
  170. class function &Class(const ALeft, ARight: TObject): Boolean;
  171. class function ShortString1(const ALeft, ARight: ShortString1): Boolean;
  172. class function ShortString2(const ALeft, ARight: ShortString2): Boolean;
  173. class function ShortString3(const ALeft, ARight: ShortString3): Boolean;
  174. class function &String(const ALeft, ARight: String): Boolean;
  175. class function ShortString(const ALeft, ARight: ShortString): Boolean;
  176. class function AnsiString(const ALeft, ARight: AnsiString): Boolean;
  177. class function WideString(const ALeft, ARight: WideString): Boolean;
  178. class function UnicodeString(const ALeft, ARight: UnicodeString): Boolean;
  179. class function Method(const ALeft, ARight: TMethod): Boolean;
  180. class function Variant(const ALeft, ARight: PVariant): Boolean;
  181. class function Pointer(const ALeft, ARight: PtrUInt): Boolean;
  182. end;
  183. THashServiceClass = class of THashService;
  184. TExtendedHashServiceClass = class of TExtendedHashService;
  185. THashFactoryClass = class of THashFactory;
  186. TExtendedHashFactoryClass = class of TExtendedHashFactory;
  187. { TComparerService }
  188. {$DEFINE STD_RAW_INTERFACE_METHODS :=
  189. QueryInterface: @TRawInterface.QueryInterface;
  190. _AddRef : @TRawInterface._AddRef;
  191. _Release : @TRawInterface._Release
  192. }
  193. {$DEFINE STD_COM_TYPESIZE_INTERFACE_METHODS :=
  194. QueryInterface: @TComTypeSizeInterface.QueryInterface;
  195. _AddRef : @TComTypeSizeInterface._AddRef;
  196. _Release : @TComTypeSizeInterface._Release
  197. }
  198. TGetHashListOptions = set of (ghloHashListAsInitData);
  199. THashFactory = class
  200. private type
  201. PPEqualityComparerVMT = ^PEqualityComparerVMT;
  202. PEqualityComparerVMT = ^TEqualityComparerVMT;
  203. TEqualityComparerVMT = packed record
  204. QueryInterface: CodePointer;
  205. _AddRef: CodePointer;
  206. _Release: CodePointer;
  207. Equals: CodePointer;
  208. GetHashCode: CodePointer;
  209. __Reserved: CodePointer; // initially or TExtendedEqualityComparerVMT compatibility
  210. // (important when ExtendedEqualityComparer is calling Binary method)
  211. __ClassRef: THashFactoryClass; // hidden field in VMT. For class ref THashFactoryClass
  212. end;
  213. private
  214. (***********************************************************************************************************************
  215. Hashes
  216. (**********************************************************************************************************************)
  217. class function Int8 (const AValue: Int8 ): UInt32; overload;
  218. class function Int16 (const AValue: Int16 ): UInt32; overload;
  219. class function Int32 (const AValue: Int32 ): UInt32; overload;
  220. class function Int64 (const AValue: Int64 ): UInt32; overload;
  221. class function UInt8 (const AValue: UInt8 ): UInt32; overload;
  222. class function UInt16 (const AValue: UInt16 ): UInt32; overload;
  223. class function UInt32 (const AValue: UInt32 ): UInt32; overload;
  224. class function UInt64 (const AValue: UInt64 ): UInt32; overload;
  225. class function Single (const AValue: Single ): UInt32; overload;
  226. class function Double (const AValue: Double ): UInt32; overload;
  227. class function Extended (const AValue: Extended ): UInt32; overload;
  228. class function Currency (const AValue: Currency ): UInt32; overload;
  229. class function Comp (const AValue: Comp ): UInt32; overload;
  230. // warning ! self as PSpoofInterfacedTypeSizeObject
  231. class function Binary (const AValue ): UInt32; overload;
  232. // warning ! self as PSpoofInterfacedTypeSizeObject
  233. class function DynArray (const AValue: Pointer ): UInt32; overload;
  234. class function &Class (const AValue: TObject ): UInt32; overload;
  235. class function ShortString1 (const AValue: ShortString1 ): UInt32; overload;
  236. class function ShortString2 (const AValue: ShortString2 ): UInt32; overload;
  237. class function ShortString3 (const AValue: ShortString3 ): UInt32; overload;
  238. class function ShortString (const AValue: ShortString ): UInt32; overload;
  239. class function AnsiString (const AValue: AnsiString ): UInt32; overload;
  240. class function WideString (const AValue: WideString ): UInt32; overload;
  241. class function UnicodeString(const AValue: UnicodeString): UInt32; overload;
  242. class function Method (const AValue: TMethod ): UInt32; overload;
  243. class function Variant (const AValue: PVariant ): UInt32; overload;
  244. class function Pointer (const AValue: Pointer ): UInt32; overload;
  245. public
  246. const MAX_HASHLIST_COUNT = 1;
  247. const HASH_FUNCTIONS_COUNT = 1;
  248. const HASHLIST_COUNT_PER_FUNCTION: array[1..HASH_FUNCTIONS_COUNT] of Integer = (1);
  249. const HASH_FUNCTIONS_MASK_SIZE = 1;
  250. class function GetHashService: THashServiceClass; virtual; abstract;
  251. class function GetHashCode(AKey: Pointer; ASize: SizeInt; AInitVal: UInt32 = 0): UInt32; virtual; abstract; reintroduce;
  252. end;
  253. TExtendedHashFactory = class(THashFactory)
  254. private type
  255. PPExtendedEqualityComparerVMT = ^PExtendedEqualityComparerVMT;
  256. PExtendedEqualityComparerVMT = ^TExtendedEqualityComparerVMT;
  257. TExtendedEqualityComparerVMT = packed record
  258. QueryInterface: CodePointer;
  259. _AddRef: CodePointer;
  260. _Release: CodePointer;
  261. Equals: CodePointer;
  262. GetHashCode: CodePointer;
  263. GetHashList: CodePointer;
  264. __ClassRef: TExtendedHashFactoryClass; // hidden field in VMT. For class ref THashFactoryClass
  265. end;
  266. private
  267. (***********************************************************************************************************************
  268. Hashes 2
  269. (**********************************************************************************************************************)
  270. class procedure Int8 (const AValue: Int8 ; AHashList: PUInt32); overload;
  271. class procedure Int16 (const AValue: Int16 ; AHashList: PUInt32); overload;
  272. class procedure Int32 (const AValue: Int32 ; AHashList: PUInt32); overload;
  273. class procedure Int64 (const AValue: Int64 ; AHashList: PUInt32); overload;
  274. class procedure UInt8 (const AValue: UInt8 ; AHashList: PUInt32); overload;
  275. class procedure UInt16 (const AValue: UInt16 ; AHashList: PUInt32); overload;
  276. class procedure UInt32 (const AValue: UInt32 ; AHashList: PUInt32); overload;
  277. class procedure UInt64 (const AValue: UInt64 ; AHashList: PUInt32); overload;
  278. class procedure Single (const AValue: Single ; AHashList: PUInt32); overload;
  279. class procedure Double (const AValue: Double ; AHashList: PUInt32); overload;
  280. class procedure Extended (const AValue: Extended ; AHashList: PUInt32); overload;
  281. class procedure Currency (const AValue: Currency ; AHashList: PUInt32); overload;
  282. class procedure Comp (const AValue: Comp ; AHashList: PUInt32); overload;
  283. // warning ! self as PSpoofInterfacedTypeSizeObject
  284. class procedure Binary (const AValue ; AHashList: PUInt32); overload;
  285. // warning ! self as PSpoofInterfacedTypeSizeObject
  286. class procedure DynArray (const AValue: Pointer ; AHashList: PUInt32); overload;
  287. class procedure &Class (const AValue: TObject ; AHashList: PUInt32); overload;
  288. class procedure ShortString1 (const AValue: ShortString1 ; AHashList: PUInt32); overload;
  289. class procedure ShortString2 (const AValue: ShortString2 ; AHashList: PUInt32); overload;
  290. class procedure ShortString3 (const AValue: ShortString3 ; AHashList: PUInt32); overload;
  291. class procedure ShortString (const AValue: ShortString ; AHashList: PUInt32); overload;
  292. class procedure AnsiString (const AValue: AnsiString ; AHashList: PUInt32); overload;
  293. class procedure WideString (const AValue: WideString ; AHashList: PUInt32); overload;
  294. class procedure UnicodeString(const AValue: UnicodeString; AHashList: PUInt32); overload;
  295. class procedure Method (const AValue: TMethod ; AHashList: PUInt32); overload;
  296. class procedure Variant (const AValue: PVariant ; AHashList: PUInt32); overload;
  297. class procedure Pointer (const AValue: Pointer ; AHashList: PUInt32); overload;
  298. public
  299. class procedure GetHashList(AKey: Pointer; ASize: SizeInt; AHashList: PUInt32; AOptions: TGetHashListOptions = []); virtual; abstract;
  300. end;
  301. TComparerService = class abstract
  302. private type
  303. TSelectMethod = function(ATypeData: PTypeData; ASize: SizeInt): Pointer of object;
  304. private
  305. class function SelectIntegerEqualityComparer(ATypeData: PTypeData; ASize: SizeInt): Pointer; virtual; abstract;
  306. class function SelectFloatEqualityComparer(ATypeData: PTypeData; ASize: SizeInt): Pointer; virtual; abstract;
  307. class function SelectShortStringEqualityComparer(ATypeData: PTypeData; ASize: SizeInt): Pointer; virtual; abstract;
  308. class function SelectBinaryEqualityComparer(ATypeData: PTypeData; ASize: SizeInt): Pointer; virtual; abstract;
  309. class function SelectDynArrayEqualityComparer(ATypeData: PTypeData; ASize: SizeInt): Pointer; virtual; abstract;
  310. private type
  311. PSpoofInterfacedTypeSizeObject = ^TSpoofInterfacedTypeSizeObject;
  312. TSpoofInterfacedTypeSizeObject = record
  313. VMT: Pointer;
  314. RefCount: LongInt;
  315. Size: SizeInt;
  316. end;
  317. PInstance = ^TInstance;
  318. TInstance = record
  319. class function Create(ASelector: Boolean; AInstance: Pointer): TComparerService.TInstance; static;
  320. class function CreateSelector(ASelectorInstance: CodePointer): TComparerService.TInstance; static;
  321. case Selector: Boolean of
  322. false: (Instance: Pointer);
  323. true: (SelectorInstance: CodePointer);
  324. end;
  325. PComparerVMT = ^TComparerVMT;
  326. TComparerVMT = packed record
  327. QueryInterface: CodePointer;
  328. _AddRef: CodePointer;
  329. _Release: CodePointer;
  330. Compare: CodePointer;
  331. end;
  332. TSelectFunc = function(ATypeData: PTypeData; ASize: SizeInt): Pointer;
  333. private
  334. class function CreateInterface(AVMT: Pointer; ASize: SizeInt): PSpoofInterfacedTypeSizeObject; static;
  335. class function SelectIntegerComparer(ATypeData: PTypeData; ASize: SizeInt): Pointer; static;
  336. class function SelectInt64Comparer(ATypeData: PTypeData; ASize: SizeInt): Pointer; static;
  337. class function SelectFloatComparer(ATypeData: PTypeData; ASize: SizeInt): Pointer; static;
  338. class function SelectShortStringComparer(ATypeData: PTypeData; ASize: SizeInt): Pointer; static;
  339. class function SelectBinaryComparer(ATypeData: PTypeData; ASize: SizeInt): Pointer; static;
  340. class function SelectDynArrayComparer(ATypeData: PTypeData; ASize: SizeInt): Pointer; static;
  341. class function TypeNeedsBinaryMethods<T>: Boolean; static;
  342. private const
  343. UseBinaryMethods: set of TTypeKind = [tkUnknown, tkSet, tkFile, tkArray, tkRecord, tkObject];
  344. // IComparer VMT
  345. Comparer_Int8_VMT : TComparerVMT = (STD_RAW_INTERFACE_METHODS; Compare: @TCompare.Int8);
  346. Comparer_Int16_VMT : TComparerVMT = (STD_RAW_INTERFACE_METHODS; Compare: @TCompare.Int16 );
  347. Comparer_Int32_VMT : TComparerVMT = (STD_RAW_INTERFACE_METHODS; Compare: @TCompare.Int32 );
  348. Comparer_Int64_VMT : TComparerVMT = (STD_RAW_INTERFACE_METHODS; Compare: @TCompare.Int64 );
  349. Comparer_UInt8_VMT : TComparerVMT = (STD_RAW_INTERFACE_METHODS; Compare: @TCompare.UInt8 );
  350. Comparer_UInt16_VMT: TComparerVMT = (STD_RAW_INTERFACE_METHODS; Compare: @TCompare.UInt16);
  351. Comparer_UInt32_VMT: TComparerVMT = (STD_RAW_INTERFACE_METHODS; Compare: @TCompare.UInt32);
  352. Comparer_UInt64_VMT: TComparerVMT = (STD_RAW_INTERFACE_METHODS; Compare: @TCompare.UInt64);
  353. Comparer_Single_VMT : TComparerVMT = (STD_RAW_INTERFACE_METHODS; Compare: @TCompare.Single );
  354. Comparer_Double_VMT : TComparerVMT = (STD_RAW_INTERFACE_METHODS; Compare: @TCompare.Double );
  355. Comparer_Extended_VMT: TComparerVMT = (STD_RAW_INTERFACE_METHODS; Compare: @TCompare.Extended);
  356. Comparer_Currency_VMT: TComparerVMT = (STD_RAW_INTERFACE_METHODS; Compare: @TCompare.Currency);
  357. Comparer_Comp_VMT : TComparerVMT = (STD_RAW_INTERFACE_METHODS; Compare: @TCompare.Comp );
  358. Comparer_Binary_VMT : TComparerVMT = (STD_COM_TYPESIZE_INTERFACE_METHODS; Compare: @TCompare._Binary );
  359. Comparer_DynArray_VMT: TComparerVMT = (STD_COM_TYPESIZE_INTERFACE_METHODS; Compare: @TCompare._DynArray);
  360. Comparer_ShortString1_VMT : TComparerVMT = (STD_RAW_INTERFACE_METHODS; Compare: @TCompare.ShortString1 );
  361. Comparer_ShortString2_VMT : TComparerVMT = (STD_RAW_INTERFACE_METHODS; Compare: @TCompare.ShortString2 );
  362. Comparer_ShortString3_VMT : TComparerVMT = (STD_RAW_INTERFACE_METHODS; Compare: @TCompare.ShortString3 );
  363. Comparer_ShortString_VMT : TComparerVMT = (STD_RAW_INTERFACE_METHODS; Compare: @TCompare.ShortString );
  364. Comparer_AnsiString_VMT : TComparerVMT = (STD_RAW_INTERFACE_METHODS; Compare: @TCompare.AnsiString );
  365. Comparer_WideString_VMT : TComparerVMT = (STD_RAW_INTERFACE_METHODS; Compare: @TCompare.WideString );
  366. Comparer_UnicodeString_VMT: TComparerVMT = (STD_RAW_INTERFACE_METHODS; Compare: @TCompare.UnicodeString);
  367. Comparer_Method_VMT : TComparerVMT = (STD_RAW_INTERFACE_METHODS; Compare: @TCompare.Method );
  368. Comparer_Variant_VMT: TComparerVMT = (STD_RAW_INTERFACE_METHODS; Compare: @TCompare.Variant);
  369. Comparer_Pointer_VMT: TComparerVMT = (STD_RAW_INTERFACE_METHODS; Compare: @TCompare.Pointer);
  370. // Instances
  371. Comparer_Int8_Instance : Pointer = @Comparer_Int8_VMT ;
  372. Comparer_Int16_Instance : Pointer = @Comparer_Int16_VMT ;
  373. Comparer_Int32_Instance : Pointer = @Comparer_Int32_VMT ;
  374. Comparer_Int64_Instance : Pointer = @Comparer_Int64_VMT ;
  375. Comparer_UInt8_Instance : Pointer = @Comparer_UInt8_VMT ;
  376. Comparer_UInt16_Instance: Pointer = @Comparer_UInt16_VMT;
  377. Comparer_UInt32_Instance: Pointer = @Comparer_UInt32_VMT;
  378. Comparer_UInt64_Instance: Pointer = @Comparer_UInt64_VMT;
  379. Comparer_Single_Instance : Pointer = @Comparer_Single_VMT ;
  380. Comparer_Double_Instance : Pointer = @Comparer_Double_VMT ;
  381. Comparer_Extended_Instance: Pointer = @Comparer_Extended_VMT;
  382. Comparer_Currency_Instance: Pointer = @Comparer_Currency_VMT;
  383. Comparer_Comp_Instance : Pointer = @Comparer_Comp_VMT ;
  384. //Comparer_Binary_Instance : Pointer = @Comparer_Binary_VMT ; // dynamic instance
  385. //Comparer_DynArray_Instance: Pointer = @Comparer_DynArray_VMT; // dynamic instance
  386. Comparer_ShortString1_Instance : Pointer = @Comparer_ShortString1_VMT ;
  387. Comparer_ShortString2_Instance : Pointer = @Comparer_ShortString2_VMT ;
  388. Comparer_ShortString3_Instance : Pointer = @Comparer_ShortString3_VMT ;
  389. Comparer_ShortString_Instance : Pointer = @Comparer_ShortString_VMT ;
  390. Comparer_AnsiString_Instance : Pointer = @Comparer_AnsiString_VMT ;
  391. Comparer_WideString_Instance : Pointer = @Comparer_WideString_VMT ;
  392. Comparer_UnicodeString_Instance: Pointer = @Comparer_UnicodeString_VMT;
  393. Comparer_Method_Instance : Pointer = @Comparer_Method_VMT ;
  394. Comparer_Variant_Instance: Pointer = @Comparer_Variant_VMT;
  395. Comparer_Pointer_Instance: Pointer = @Comparer_Pointer_VMT;
  396. ComparerInstances: array[TTypeKind] of TInstance =
  397. (
  398. // tkUnknown
  399. (Selector: True; SelectorInstance: @TComparerService.SelectBinaryComparer),
  400. // tkInteger
  401. (Selector: True; SelectorInstance: @TComparerService.SelectIntegerComparer),
  402. // tkChar
  403. (Selector: False; Instance: @Comparer_UInt8_Instance),
  404. // tkEnumeration
  405. (Selector: True; SelectorInstance: @TComparerService.SelectIntegerComparer),
  406. // tkFloat
  407. (Selector: True; SelectorInstance: @TComparerService.SelectFloatComparer),
  408. // tkSet
  409. (Selector: True; SelectorInstance: @TComparerService.SelectBinaryComparer),
  410. // tkMethod
  411. (Selector: False; Instance: @Comparer_Method_Instance),
  412. // tkSString
  413. (Selector: True; SelectorInstance: @TComparerService.SelectShortStringComparer),
  414. // tkLString - only internal use / deprecated in compiler
  415. (Selector: False; Instance: @Comparer_AnsiString_Instance), // <- unsure
  416. // tkAString
  417. (Selector: False; Instance: @Comparer_AnsiString_Instance),
  418. // tkWString
  419. (Selector: False; Instance: @Comparer_WideString_Instance),
  420. // tkVariant
  421. (Selector: False; Instance: @Comparer_Variant_Instance),
  422. // tkArray
  423. (Selector: True; SelectorInstance: @TComparerService.SelectBinaryComparer),
  424. // tkRecord
  425. (Selector: True; SelectorInstance: @TComparerService.SelectBinaryComparer),
  426. // tkInterface
  427. (Selector: False; Instance: @Comparer_Pointer_Instance),
  428. // tkClass
  429. (Selector: False; Instance: @Comparer_Pointer_Instance),
  430. // tkObject
  431. (Selector: True; SelectorInstance: @TComparerService.SelectBinaryComparer),
  432. // tkWChar
  433. (Selector: False; Instance: @Comparer_UInt16_Instance),
  434. // tkBool
  435. (Selector: True; SelectorInstance: @TComparerService.SelectIntegerComparer),
  436. // tkInt64
  437. (Selector: False; Instance: @Comparer_Int64_Instance),
  438. // tkQWord
  439. (Selector: False; Instance: @Comparer_UInt64_Instance),
  440. // tkDynArray
  441. (Selector: True; SelectorInstance: @TComparerService.SelectDynArrayComparer),
  442. // tkInterfaceRaw
  443. (Selector: False; Instance: @Comparer_Pointer_Instance),
  444. // tkProcVar
  445. (Selector: False; Instance: @Comparer_Pointer_Instance),
  446. // tkUString
  447. (Selector: False; Instance: @Comparer_UnicodeString_Instance),
  448. // tkUChar - WTF? ... http://bugs.freepascal.org/view.php?id=24609
  449. (Selector: False; Instance: @Comparer_UInt16_Instance), // <- unsure maybe Comparer_UInt32_Instance
  450. // tkHelper
  451. (Selector: False; Instance: @Comparer_Pointer_Instance),
  452. // tkFile
  453. (Selector: True; SelectorInstance: @TComparerService.SelectBinaryComparer), // <- unsure what type?
  454. // tkClassRef
  455. (Selector: False; Instance: @Comparer_Pointer_Instance),
  456. // tkPointer
  457. (Selector: False; Instance: @Comparer_Pointer_Instance)
  458. );
  459. public
  460. class function LookupComparer(ATypeInfo: PTypeInfo; ASize: SizeInt): Pointer; static;
  461. end;
  462. THashService = class(TComparerService)
  463. public
  464. class function LookupEqualityComparer(ATypeInfo: PTypeInfo; ASize: SizeInt): Pointer; virtual; abstract;
  465. end;
  466. TExtendedHashService = class(THashService)
  467. public
  468. class function LookupEqualityComparer(ATypeInfo: PTypeInfo; ASize: SizeInt): Pointer; override;
  469. class function LookupExtendedEqualityComparer(ATypeInfo: PTypeInfo; ASize: SizeInt): Pointer; virtual; abstract;
  470. end;
  471. {$DEFINE HASH_FACTORY := PPEqualityComparerVMT(Self)^.__ClassRef}
  472. {$DEFINE EXTENDED_HASH_FACTORY := PPExtendedEqualityComparerVMT(Self)^.__ClassRef}
  473. { THashService }
  474. THashService<T: THashFactory> = class(THashService)
  475. private
  476. class function SelectIntegerEqualityComparer(ATypeData: PTypeData; ASize: SizeInt): Pointer; override;
  477. class function SelectFloatEqualityComparer(ATypeData: PTypeData; ASize: SizeInt): Pointer; override;
  478. class function SelectShortStringEqualityComparer(ATypeData: PTypeData; ASize: SizeInt): Pointer; override;
  479. class function SelectBinaryEqualityComparer(ATypeData: PTypeData; ASize: SizeInt): Pointer; override;
  480. class function SelectDynArrayEqualityComparer(ATypeData: PTypeData; ASize: SizeInt): Pointer; override;
  481. private const
  482. // IEqualityComparer VMT templates
  483. {$WARNINGS OFF}
  484. EqualityComparer_Int8_VMT : THashFactory.TEqualityComparerVMT = (STD_RAW_INTERFACE_METHODS; Equals: @TEquals.Int8 ; GetHashCode: @THashFactory.Int8 );
  485. EqualityComparer_Int16_VMT : THashFactory.TEqualityComparerVMT = (STD_RAW_INTERFACE_METHODS; Equals: @TEquals.Int16 ; GetHashCode: @THashFactory.Int16 );
  486. EqualityComparer_Int32_VMT : THashFactory.TEqualityComparerVMT = (STD_RAW_INTERFACE_METHODS; Equals: @TEquals.Int32 ; GetHashCode: @THashFactory.Int32 );
  487. EqualityComparer_Int64_VMT : THashFactory.TEqualityComparerVMT = (STD_RAW_INTERFACE_METHODS; Equals: @TEquals.Int64 ; GetHashCode: @THashFactory.Int64 );
  488. EqualityComparer_UInt8_VMT : THashFactory.TEqualityComparerVMT = (STD_RAW_INTERFACE_METHODS; Equals: @TEquals.UInt8 ; GetHashCode: @THashFactory.UInt8 );
  489. EqualityComparer_UInt16_VMT: THashFactory.TEqualityComparerVMT = (STD_RAW_INTERFACE_METHODS; Equals: @TEquals.UInt16; GetHashCode: @THashFactory.UInt16);
  490. EqualityComparer_UInt32_VMT: THashFactory.TEqualityComparerVMT = (STD_RAW_INTERFACE_METHODS; Equals: @TEquals.UInt32; GetHashCode: @THashFactory.UInt32);
  491. EqualityComparer_UInt64_VMT: THashFactory.TEqualityComparerVMT = (STD_RAW_INTERFACE_METHODS; Equals: @TEquals.UInt64; GetHashCode: @THashFactory.UInt64);
  492. EqualityComparer_Single_VMT : THashFactory.TEqualityComparerVMT = (STD_RAW_INTERFACE_METHODS; Equals: @TEquals.Single ; GetHashCode: @THashFactory.Single );
  493. EqualityComparer_Double_VMT : THashFactory.TEqualityComparerVMT = (STD_RAW_INTERFACE_METHODS; Equals: @TEquals.Double ; GetHashCode: @THashFactory.Double );
  494. EqualityComparer_Extended_VMT: THashFactory.TEqualityComparerVMT = (STD_RAW_INTERFACE_METHODS; Equals: @TEquals.Extended; GetHashCode: @THashFactory.Extended);
  495. EqualityComparer_Currency_VMT: THashFactory.TEqualityComparerVMT = (STD_RAW_INTERFACE_METHODS; Equals: @TEquals.Currency; GetHashCode: @THashFactory.Currency);
  496. EqualityComparer_Comp_VMT : THashFactory.TEqualityComparerVMT = (STD_RAW_INTERFACE_METHODS; Equals: @TEquals.Comp ; GetHashCode: @THashFactory.Comp );
  497. EqualityComparer_Binary_VMT : THashFactory.TEqualityComparerVMT = (STD_COM_TYPESIZE_INTERFACE_METHODS; Equals: @TEquals._Binary ; GetHashCode: @THashFactory.Binary );
  498. EqualityComparer_DynArray_VMT: THashFactory.TEqualityComparerVMT = (STD_COM_TYPESIZE_INTERFACE_METHODS; Equals: @TEquals._DynArray; GetHashCode: @THashFactory.DynArray);
  499. EqualityComparer_Class_VMT: THashFactory.TEqualityComparerVMT = (STD_RAW_INTERFACE_METHODS; Equals: @TEquals.&Class; GetHashCode: @THashFactory.&Class);
  500. EqualityComparer_ShortString1_VMT : THashFactory.TEqualityComparerVMT = (STD_RAW_INTERFACE_METHODS; Equals: @TEquals.ShortString1 ; GetHashCode: @THashFactory.ShortString1 );
  501. EqualityComparer_ShortString2_VMT : THashFactory.TEqualityComparerVMT = (STD_RAW_INTERFACE_METHODS; Equals: @TEquals.ShortString2 ; GetHashCode: @THashFactory.ShortString2 );
  502. EqualityComparer_ShortString3_VMT : THashFactory.TEqualityComparerVMT = (STD_RAW_INTERFACE_METHODS; Equals: @TEquals.ShortString3 ; GetHashCode: @THashFactory.ShortString3 );
  503. EqualityComparer_ShortString_VMT : THashFactory.TEqualityComparerVMT = (STD_RAW_INTERFACE_METHODS; Equals: @TEquals.ShortString ; GetHashCode: @THashFactory.ShortString );
  504. EqualityComparer_AnsiString_VMT : THashFactory.TEqualityComparerVMT = (STD_RAW_INTERFACE_METHODS; Equals: @TEquals.AnsiString ; GetHashCode: @THashFactory.AnsiString );
  505. EqualityComparer_WideString_VMT : THashFactory.TEqualityComparerVMT = (STD_RAW_INTERFACE_METHODS; Equals: @TEquals.WideString ; GetHashCode: @THashFactory.WideString );
  506. EqualityComparer_UnicodeString_VMT: THashFactory.TEqualityComparerVMT = (STD_RAW_INTERFACE_METHODS; Equals: @TEquals.UnicodeString; GetHashCode: @THashFactory.UnicodeString);
  507. EqualityComparer_Method_VMT : THashFactory.TEqualityComparerVMT = (STD_RAW_INTERFACE_METHODS; Equals: @TEquals.Method ; GetHashCode: @THashFactory.Method );
  508. EqualityComparer_Variant_VMT: THashFactory.TEqualityComparerVMT = (STD_RAW_INTERFACE_METHODS; Equals: @TEquals.Variant; GetHashCode: @THashFactory.Variant);
  509. EqualityComparer_Pointer_VMT: THashFactory.TEqualityComparerVMT = (STD_RAW_INTERFACE_METHODS; Equals: @TEquals.Pointer; GetHashCode: @THashFactory.Pointer);
  510. {.$WARNINGS ON} // do not enable warnings ever in this unit, or you will get many warnings about uninitialized TEqualityComparerVMT fields
  511. private class var
  512. // IEqualityComparer VMT
  513. FEqualityComparer_Int8_VMT : THashFactory.TEqualityComparerVMT;
  514. FEqualityComparer_Int16_VMT : THashFactory.TEqualityComparerVMT;
  515. FEqualityComparer_Int32_VMT : THashFactory.TEqualityComparerVMT;
  516. FEqualityComparer_Int64_VMT : THashFactory.TEqualityComparerVMT;
  517. FEqualityComparer_UInt8_VMT : THashFactory.TEqualityComparerVMT;
  518. FEqualityComparer_UInt16_VMT: THashFactory.TEqualityComparerVMT;
  519. FEqualityComparer_UInt32_VMT: THashFactory.TEqualityComparerVMT;
  520. FEqualityComparer_UInt64_VMT: THashFactory.TEqualityComparerVMT;
  521. FEqualityComparer_Single_VMT : THashFactory.TEqualityComparerVMT;
  522. FEqualityComparer_Double_VMT : THashFactory.TEqualityComparerVMT;
  523. FEqualityComparer_Extended_VMT: THashFactory.TEqualityComparerVMT;
  524. FEqualityComparer_Currency_VMT: THashFactory.TEqualityComparerVMT;
  525. FEqualityComparer_Comp_VMT : THashFactory.TEqualityComparerVMT;
  526. FEqualityComparer_Binary_VMT : THashFactory.TEqualityComparerVMT;
  527. FEqualityComparer_DynArray_VMT: THashFactory.TEqualityComparerVMT;
  528. FEqualityComparer_Class_VMT: THashFactory.TEqualityComparerVMT;
  529. FEqualityComparer_ShortString1_VMT : THashFactory.TEqualityComparerVMT;
  530. FEqualityComparer_ShortString2_VMT : THashFactory.TEqualityComparerVMT;
  531. FEqualityComparer_ShortString3_VMT : THashFactory.TEqualityComparerVMT;
  532. FEqualityComparer_ShortString_VMT : THashFactory.TEqualityComparerVMT;
  533. FEqualityComparer_AnsiString_VMT : THashFactory.TEqualityComparerVMT;
  534. FEqualityComparer_WideString_VMT : THashFactory.TEqualityComparerVMT;
  535. FEqualityComparer_UnicodeString_VMT: THashFactory.TEqualityComparerVMT;
  536. FEqualityComparer_Method_VMT : THashFactory.TEqualityComparerVMT;
  537. FEqualityComparer_Variant_VMT: THashFactory.TEqualityComparerVMT;
  538. FEqualityComparer_Pointer_VMT: THashFactory.TEqualityComparerVMT;
  539. FEqualityComparer_Int8_Instance : Pointer;
  540. FEqualityComparer_Int16_Instance : Pointer;
  541. FEqualityComparer_Int32_Instance : Pointer;
  542. FEqualityComparer_Int64_Instance : Pointer;
  543. FEqualityComparer_UInt8_Instance : Pointer;
  544. FEqualityComparer_UInt16_Instance : Pointer;
  545. FEqualityComparer_UInt32_Instance : Pointer;
  546. FEqualityComparer_UInt64_Instance : Pointer;
  547. FEqualityComparer_Single_Instance : Pointer;
  548. FEqualityComparer_Double_Instance : Pointer;
  549. FEqualityComparer_Extended_Instance : Pointer;
  550. FEqualityComparer_Currency_Instance : Pointer;
  551. FEqualityComparer_Comp_Instance : Pointer;
  552. //FEqualityComparer_Binary_Instance : Pointer; // dynamic instance
  553. //FEqualityComparer_DynArray_Instance : Pointer; // dynamic instance
  554. FEqualityComparer_ShortString1_Instance : Pointer;
  555. FEqualityComparer_ShortString2_Instance : Pointer;
  556. FEqualityComparer_ShortString3_Instance : Pointer;
  557. FEqualityComparer_ShortString_Instance : Pointer;
  558. FEqualityComparer_AnsiString_Instance : Pointer;
  559. FEqualityComparer_WideString_Instance : Pointer;
  560. FEqualityComparer_UnicodeString_Instance: Pointer;
  561. FEqualityComparer_Method_Instance : Pointer;
  562. FEqualityComparer_Variant_Instance : Pointer;
  563. FEqualityComparer_Pointer_Instance : Pointer;
  564. FEqualityComparerInstances: array[TTypeKind] of TInstance;
  565. TablesInitialized : Boolean;
  566. private
  567. class constructor Create;
  568. class procedure InitTables;
  569. public
  570. class function LookupEqualityComparer(ATypeInfo: PTypeInfo; ASize: SizeInt): Pointer; override;
  571. end;
  572. { TExtendedHashService }
  573. TExtendedHashService<T: TExtendedHashFactory> = class(TExtendedHashService)
  574. private
  575. class function SelectIntegerEqualityComparer(ATypeData: PTypeData; ASize: SizeInt): Pointer; override;
  576. class function SelectFloatEqualityComparer(ATypeData: PTypeData; ASize: SizeInt): Pointer; override;
  577. class function SelectShortStringEqualityComparer(ATypeData: PTypeData; ASize: SizeInt): Pointer; override;
  578. class function SelectBinaryEqualityComparer(ATypeData: PTypeData; ASize: SizeInt): Pointer; override;
  579. class function SelectDynArrayEqualityComparer(ATypeData: PTypeData; ASize: SizeInt): Pointer; override;
  580. private const
  581. // IExtendedEqualityComparer VMT templates
  582. {$WARNINGS OFF}
  583. ExtendedEqualityComparer_Int8_VMT : TExtendedHashFactory.TExtendedEqualityComparerVMT = (STD_RAW_INTERFACE_METHODS; Equals: @TEquals.Int8 ; GetHashCode: @THashFactory.Int8 ; GetHashList: @TExtendedHashFactory.Int8 );
  584. ExtendedEqualityComparer_Int16_VMT : TExtendedHashFactory.TExtendedEqualityComparerVMT = (STD_RAW_INTERFACE_METHODS; Equals: @TEquals.Int16 ; GetHashCode: @THashFactory.Int16 ; GetHashList: @TExtendedHashFactory.Int16 );
  585. ExtendedEqualityComparer_Int32_VMT : TExtendedHashFactory.TExtendedEqualityComparerVMT = (STD_RAW_INTERFACE_METHODS; Equals: @TEquals.Int32 ; GetHashCode: @THashFactory.Int32 ; GetHashList: @TExtendedHashFactory.Int32 );
  586. ExtendedEqualityComparer_Int64_VMT : TExtendedHashFactory.TExtendedEqualityComparerVMT = (STD_RAW_INTERFACE_METHODS; Equals: @TEquals.Int64 ; GetHashCode: @THashFactory.Int64 ; GetHashList: @TExtendedHashFactory.Int64 );
  587. ExtendedEqualityComparer_UInt8_VMT : TExtendedHashFactory.TExtendedEqualityComparerVMT = (STD_RAW_INTERFACE_METHODS; Equals: @TEquals.UInt8 ; GetHashCode: @THashFactory.UInt8 ; GetHashList: @TExtendedHashFactory.UInt8 );
  588. ExtendedEqualityComparer_UInt16_VMT: TExtendedHashFactory.TExtendedEqualityComparerVMT = (STD_RAW_INTERFACE_METHODS; Equals: @TEquals.UInt16; GetHashCode: @THashFactory.UInt16; GetHashList: @TExtendedHashFactory.UInt16);
  589. ExtendedEqualityComparer_UInt32_VMT: TExtendedHashFactory.TExtendedEqualityComparerVMT = (STD_RAW_INTERFACE_METHODS; Equals: @TEquals.UInt32; GetHashCode: @THashFactory.UInt32; GetHashList: @TExtendedHashFactory.UInt32);
  590. ExtendedEqualityComparer_UInt64_VMT: TExtendedHashFactory.TExtendedEqualityComparerVMT = (STD_RAW_INTERFACE_METHODS; Equals: @TEquals.UInt64; GetHashCode: @THashFactory.UInt64; GetHashList: @TExtendedHashFactory.UInt64);
  591. ExtendedEqualityComparer_Single_VMT : TExtendedHashFactory.TExtendedEqualityComparerVMT = (STD_RAW_INTERFACE_METHODS; Equals: @TEquals.Single ; GetHashCode: @THashFactory.Single ; GetHashList: @TExtendedHashFactory.Single );
  592. ExtendedEqualityComparer_Double_VMT : TExtendedHashFactory.TExtendedEqualityComparerVMT = (STD_RAW_INTERFACE_METHODS; Equals: @TEquals.Double ; GetHashCode: @THashFactory.Double ; GetHashList: @TExtendedHashFactory.Double );
  593. ExtendedEqualityComparer_Extended_VMT: TExtendedHashFactory.TExtendedEqualityComparerVMT = (STD_RAW_INTERFACE_METHODS; Equals: @TEquals.Extended; GetHashCode: @THashFactory.Extended; GetHashList: @TExtendedHashFactory.Extended);
  594. ExtendedEqualityComparer_Currency_VMT: TExtendedHashFactory.TExtendedEqualityComparerVMT = (STD_RAW_INTERFACE_METHODS; Equals: @TEquals.Currency; GetHashCode: @THashFactory.Currency; GetHashList: @TExtendedHashFactory.Currency);
  595. ExtendedEqualityComparer_Comp_VMT : TExtendedHashFactory.TExtendedEqualityComparerVMT = (STD_RAW_INTERFACE_METHODS; Equals: @TEquals.Comp ; GetHashCode: @THashFactory.Comp ; GetHashList: @TExtendedHashFactory.Comp );
  596. ExtendedEqualityComparer_Binary_VMT : TExtendedHashFactory.TExtendedEqualityComparerVMT = (STD_COM_TYPESIZE_INTERFACE_METHODS; Equals: @TEquals._Binary ; GetHashCode: @THashFactory.Binary ; GetHashList: @TExtendedHashFactory.Binary );
  597. ExtendedEqualityComparer_DynArray_VMT: TExtendedHashFactory.TExtendedEqualityComparerVMT = (STD_COM_TYPESIZE_INTERFACE_METHODS; Equals: @TEquals._DynArray; GetHashCode: @THashFactory.DynArray; GetHashList: @TExtendedHashFactory.DynArray);
  598. ExtendedEqualityComparer_Class_VMT: TExtendedHashFactory.TExtendedEqualityComparerVMT = (STD_RAW_INTERFACE_METHODS; Equals: @TEquals.&Class; GetHashCode: @THashFactory.&Class; GetHashList: @TExtendedHashFactory.&Class);
  599. ExtendedEqualityComparer_ShortString1_VMT : TExtendedHashFactory.TExtendedEqualityComparerVMT = (STD_RAW_INTERFACE_METHODS; Equals: @TEquals.ShortString1 ; GetHashCode: @THashFactory.ShortString1 ; GetHashList: @TExtendedHashFactory.ShortString1 );
  600. ExtendedEqualityComparer_ShortString2_VMT : TExtendedHashFactory.TExtendedEqualityComparerVMT = (STD_RAW_INTERFACE_METHODS; Equals: @TEquals.ShortString2 ; GetHashCode: @THashFactory.ShortString2 ; GetHashList: @TExtendedHashFactory.ShortString2 );
  601. ExtendedEqualityComparer_ShortString3_VMT : TExtendedHashFactory.TExtendedEqualityComparerVMT = (STD_RAW_INTERFACE_METHODS; Equals: @TEquals.ShortString3 ; GetHashCode: @THashFactory.ShortString3 ; GetHashList: @TExtendedHashFactory.ShortString3 );
  602. ExtendedEqualityComparer_ShortString_VMT : TExtendedHashFactory.TExtendedEqualityComparerVMT = (STD_RAW_INTERFACE_METHODS; Equals: @TEquals.ShortString ; GetHashCode: @THashFactory.ShortString ; GetHashList: @TExtendedHashFactory.ShortString );
  603. ExtendedEqualityComparer_AnsiString_VMT : TExtendedHashFactory.TExtendedEqualityComparerVMT = (STD_RAW_INTERFACE_METHODS; Equals: @TEquals.AnsiString ; GetHashCode: @THashFactory.AnsiString ; GetHashList: @TExtendedHashFactory.AnsiString );
  604. ExtendedEqualityComparer_WideString_VMT : TExtendedHashFactory.TExtendedEqualityComparerVMT = (STD_RAW_INTERFACE_METHODS; Equals: @TEquals.WideString ; GetHashCode: @THashFactory.WideString ; GetHashList: @TExtendedHashFactory.WideString );
  605. ExtendedEqualityComparer_UnicodeString_VMT: TExtendedHashFactory.TExtendedEqualityComparerVMT = (STD_RAW_INTERFACE_METHODS; Equals: @TEquals.UnicodeString; GetHashCode: @THashFactory.UnicodeString; GetHashList: @TExtendedHashFactory.UnicodeString);
  606. ExtendedEqualityComparer_Method_VMT : TExtendedHashFactory.TExtendedEqualityComparerVMT = (STD_RAW_INTERFACE_METHODS; Equals: @TEquals.Method ; GetHashCode: @THashFactory.Method ; GetHashList: @TExtendedHashFactory.Method );
  607. ExtendedEqualityComparer_Variant_VMT: TExtendedHashFactory.TExtendedEqualityComparerVMT = (STD_RAW_INTERFACE_METHODS; Equals: @TEquals.Variant; GetHashCode: @THashFactory.Variant; GetHashList: @TExtendedHashFactory.Variant);
  608. ExtendedEqualityComparer_Pointer_VMT: TExtendedHashFactory.TExtendedEqualityComparerVMT = (STD_RAW_INTERFACE_METHODS; Equals: @TEquals.Pointer; GetHashCode: @THashFactory.Pointer; GetHashList: @TExtendedHashFactory.Pointer);
  609. {.$WARNINGS ON} // do not enable warnings ever in this unit, or you will get many warnings about uninitialized TEqualityComparerVMT fields
  610. private class var
  611. // IExtendedEqualityComparer VMT
  612. FExtendedEqualityComparer_Int8_VMT : TExtendedHashFactory.TExtendedEqualityComparerVMT;
  613. FExtendedEqualityComparer_Int16_VMT : TExtendedHashFactory.TExtendedEqualityComparerVMT;
  614. FExtendedEqualityComparer_Int32_VMT : TExtendedHashFactory.TExtendedEqualityComparerVMT;
  615. FExtendedEqualityComparer_Int64_VMT : TExtendedHashFactory.TExtendedEqualityComparerVMT;
  616. FExtendedEqualityComparer_UInt8_VMT : TExtendedHashFactory.TExtendedEqualityComparerVMT;
  617. FExtendedEqualityComparer_UInt16_VMT: TExtendedHashFactory.TExtendedEqualityComparerVMT;
  618. FExtendedEqualityComparer_UInt32_VMT: TExtendedHashFactory.TExtendedEqualityComparerVMT;
  619. FExtendedEqualityComparer_UInt64_VMT: TExtendedHashFactory.TExtendedEqualityComparerVMT;
  620. FExtendedEqualityComparer_Single_VMT : TExtendedHashFactory.TExtendedEqualityComparerVMT;
  621. FExtendedEqualityComparer_Double_VMT : TExtendedHashFactory.TExtendedEqualityComparerVMT;
  622. FExtendedEqualityComparer_Extended_VMT: TExtendedHashFactory.TExtendedEqualityComparerVMT;
  623. FExtendedEqualityComparer_Currency_VMT: TExtendedHashFactory.TExtendedEqualityComparerVMT;
  624. FExtendedEqualityComparer_Comp_VMT : TExtendedHashFactory.TExtendedEqualityComparerVMT;
  625. FExtendedEqualityComparer_Binary_VMT : TExtendedHashFactory.TExtendedEqualityComparerVMT;
  626. FExtendedEqualityComparer_DynArray_VMT: TExtendedHashFactory.TExtendedEqualityComparerVMT;
  627. FExtendedEqualityComparer_Class_VMT: TExtendedHashFactory.TExtendedEqualityComparerVMT;
  628. FExtendedEqualityComparer_ShortString1_VMT : TExtendedHashFactory.TExtendedEqualityComparerVMT;
  629. FExtendedEqualityComparer_ShortString2_VMT : TExtendedHashFactory.TExtendedEqualityComparerVMT;
  630. FExtendedEqualityComparer_ShortString3_VMT : TExtendedHashFactory.TExtendedEqualityComparerVMT;
  631. FExtendedEqualityComparer_ShortString_VMT : TExtendedHashFactory.TExtendedEqualityComparerVMT;
  632. FExtendedEqualityComparer_AnsiString_VMT : TExtendedHashFactory.TExtendedEqualityComparerVMT;
  633. FExtendedEqualityComparer_WideString_VMT : TExtendedHashFactory.TExtendedEqualityComparerVMT;
  634. FExtendedEqualityComparer_UnicodeString_VMT: TExtendedHashFactory.TExtendedEqualityComparerVMT;
  635. FExtendedEqualityComparer_Method_VMT : TExtendedHashFactory.TExtendedEqualityComparerVMT;
  636. FExtendedEqualityComparer_Variant_VMT: TExtendedHashFactory.TExtendedEqualityComparerVMT;
  637. FExtendedEqualityComparer_Pointer_VMT: TExtendedHashFactory.TExtendedEqualityComparerVMT;
  638. FExtendedEqualityComparer_Int8_Instance : Pointer;
  639. FExtendedEqualityComparer_Int16_Instance : Pointer;
  640. FExtendedEqualityComparer_Int32_Instance : Pointer;
  641. FExtendedEqualityComparer_Int64_Instance : Pointer;
  642. FExtendedEqualityComparer_UInt8_Instance : Pointer;
  643. FExtendedEqualityComparer_UInt16_Instance : Pointer;
  644. FExtendedEqualityComparer_UInt32_Instance : Pointer;
  645. FExtendedEqualityComparer_UInt64_Instance : Pointer;
  646. FExtendedEqualityComparer_Single_Instance : Pointer;
  647. FExtendedEqualityComparer_Double_Instance : Pointer;
  648. FExtendedEqualityComparer_Extended_Instance : Pointer;
  649. FExtendedEqualityComparer_Currency_Instance : Pointer;
  650. FExtendedEqualityComparer_Comp_Instance : Pointer;
  651. //FExtendedEqualityComparer_Binary_Instance : Pointer; // dynamic instance
  652. //FExtendedEqualityComparer_DynArray_Instance : Pointer; // dynamic instance
  653. FExtendedEqualityComparer_ShortString1_Instance : Pointer;
  654. FExtendedEqualityComparer_ShortString2_Instance : Pointer;
  655. FExtendedEqualityComparer_ShortString3_Instance : Pointer;
  656. FExtendedEqualityComparer_ShortString_Instance : Pointer;
  657. FExtendedEqualityComparer_AnsiString_Instance : Pointer;
  658. FExtendedEqualityComparer_WideString_Instance : Pointer;
  659. FExtendedEqualityComparer_UnicodeString_Instance: Pointer;
  660. FExtendedEqualityComparer_Method_Instance : Pointer;
  661. FExtendedEqualityComparer_Variant_Instance : Pointer;
  662. FExtendedEqualityComparer_Pointer_Instance : Pointer;
  663. // all instances
  664. FExtendedEqualityComparerInstances: array[TTypeKind] of TInstance;
  665. TablesInitialized : Boolean;
  666. private
  667. class constructor Create;
  668. class procedure InitTables;
  669. public
  670. class function LookupExtendedEqualityComparer(ATypeInfo: PTypeInfo; ASize: SizeInt): Pointer; override;
  671. end;
  672. TOnEqualityComparison<T> = function(const ALeft, ARight: T): Boolean of object;
  673. TEqualityComparisonFunc<T> = function(const ALeft, ARight: T): Boolean;
  674. TOnHasher<T> = function(const AValue: T): UInt32 of object;
  675. TOnExtendedHasher<T> = procedure(const AValue: T; AHashList: PUInt32) of object;
  676. THasherFunc<T> = function(const AValue: T): UInt32;
  677. TExtendedHasherFunc<T> = procedure(const AValue: T; AHashList: PUInt32);
  678. TEqualityComparer<T> = class(TInterfacedObject, IEqualityComparer<T>)
  679. public
  680. class function Default: IEqualityComparer<T>; static; overload;
  681. class function Default(AHashFactoryClass: THashFactoryClass): IEqualityComparer<T>; static; overload;
  682. class function Construct(const AEqualityComparison: TOnEqualityComparison<T>;
  683. const AHasher: TOnHasher<T>): IEqualityComparer<T>; overload;
  684. class function Construct(const AEqualityComparison: TEqualityComparisonFunc<T>;
  685. const AHasher: THasherFunc<T>): IEqualityComparer<T>; overload;
  686. function Equals(const ALeft, ARight: T): Boolean; virtual; overload; abstract;
  687. function GetHashCode(const AValue: T): UInt32; virtual; overload; abstract;
  688. end;
  689. { TDelegatedEqualityComparerEvent }
  690. TDelegatedEqualityComparerEvents<T> = class(TEqualityComparer<T>)
  691. private
  692. FEqualityComparison: TOnEqualityComparison<T>;
  693. FHasher: TOnHasher<T>;
  694. public
  695. function Equals(const ALeft, ARight: T): Boolean; override;
  696. function GetHashCode(const AValue: T): UInt32; override;
  697. constructor Create(const AEqualityComparison: TOnEqualityComparison<T>;
  698. const AHasher: TOnHasher<T>);
  699. end;
  700. TDelegatedEqualityComparerFunc<T> = class(TEqualityComparer<T>)
  701. private
  702. FEqualityComparison: TEqualityComparisonFunc<T>;
  703. FHasher: THasherFunc<T>;
  704. public
  705. function Equals(const ALeft, ARight: T): Boolean; override;
  706. function GetHashCode(const AValue: T): UInt32; override;
  707. constructor Create(const AEqualityComparison: TEqualityComparisonFunc<T>;
  708. const AHasher: THasherFunc<T>);
  709. end;
  710. { TExtendedEqualityComparer }
  711. TExtendedEqualityComparer<T> = class(TEqualityComparer<T>, IExtendedEqualityComparer<T>)
  712. public
  713. class function Default: IExtendedEqualityComparer<T>; static; overload; reintroduce;
  714. class function Default(AExtenedHashFactoryClass: TExtendedHashFactoryClass): IExtendedEqualityComparer<T>; static; overload; reintroduce;
  715. class function Construct(const AEqualityComparison: TOnEqualityComparison<T>;
  716. const AHasher: TOnHasher<T>; const AExtendedHasher: TOnExtendedHasher<T>): IExtendedEqualityComparer<T>; overload; reintroduce;
  717. class function Construct(const AEqualityComparison: TEqualityComparisonFunc<T>;
  718. const AHasher: THasherFunc<T>; const AExtendedHasher: TExtendedHasherFunc<T>): IExtendedEqualityComparer<T>; overload; reintroduce;
  719. class function Construct(const AEqualityComparison: TOnEqualityComparison<T>;
  720. const AExtendedHasher: TOnExtendedHasher<T>): IExtendedEqualityComparer<T>; overload; reintroduce;
  721. class function Construct(const AEqualityComparison: TEqualityComparisonFunc<T>;
  722. const AExtendedHasher: TExtendedHasherFunc<T>): IExtendedEqualityComparer<T>; overload; reintroduce;
  723. procedure GetHashList(const AValue: T; AHashList: PUInt32); virtual; abstract;
  724. end;
  725. TDelegatedExtendedEqualityComparerEvents<T> = class(TExtendedEqualityComparer<T>)
  726. private
  727. FEqualityComparison: TOnEqualityComparison<T>;
  728. FHasher: TOnHasher<T>;
  729. FExtendedHasher: TOnExtendedHasher<T>;
  730. function GetHashCodeMethod(const AValue: T): UInt32;
  731. public
  732. function Equals(const ALeft, ARight: T): Boolean; override;
  733. function GetHashCode(const AValue: T): UInt32; override;
  734. procedure GetHashList(const AValue: T; AHashList: PUInt32); override;
  735. constructor Create(const AEqualityComparison: TOnEqualityComparison<T>;
  736. const AHasher: TOnHasher<T>; const AExtendedHasher: TOnExtendedHasher<T>); overload;
  737. constructor Create(const AEqualityComparison: TOnEqualityComparison<T>;
  738. const AExtendedHasher: TOnExtendedHasher<T>); overload;
  739. end;
  740. TDelegatedExtendedEqualityComparerFunc<T> = class(TExtendedEqualityComparer<T>)
  741. private
  742. FEqualityComparison: TEqualityComparisonFunc<T>;
  743. FHasher: THasherFunc<T>;
  744. FExtendedHasher: TExtendedHasherFunc<T>;
  745. public
  746. function Equals(const ALeft, ARight: T): Boolean; override;
  747. function GetHashCode(const AValue: T): UInt32; override;
  748. procedure GetHashList(const AValue: T; AHashList: PUInt32); override;
  749. constructor Create(const AEqualityComparison: TEqualityComparisonFunc<T>;
  750. const AHasher: THasherFunc<T>; const AExtendedHasher: TExtendedHasherFunc<T>); overload;
  751. constructor Create(const AEqualityComparison: TEqualityComparisonFunc<T>;
  752. const AExtendedHasher: TExtendedHasherFunc<T>); overload;
  753. end;
  754. TBinaryComparer<T> = class(TInterfacedObject, IComparer<T>)
  755. public
  756. function Compare(const ALeft, ARight: T): Integer;
  757. end;
  758. TBinaryEqualityComparer<T> = class(TInterfacedObject, IEqualityComparer<T>)
  759. private
  760. FHashFactory: THashFactoryClass;
  761. public
  762. constructor Create(AHashFactoryClass: THashFactoryClass);
  763. function Equals(const ALeft, ARight: T): Boolean; reintroduce;
  764. function GetHashCode(const AValue: T): UInt32; reintroduce;
  765. end;
  766. TBinaryExtendedEqualityComparer<T> = class(TBinaryEqualityComparer<T>, IExtendedEqualityComparer<T>)
  767. private
  768. FExtendedHashFactory: TExtendedHashFactoryClass;
  769. public
  770. constructor Create(AHashFactoryClass: TExtendedHashFactoryClass);
  771. procedure GetHashList(const AValue: T; AHashList: PUInt32);
  772. end;
  773. { TDelphiHashFactory }
  774. TDelphiHashFactory = class(THashFactory)
  775. public
  776. class function GetHashService: THashServiceClass; override;
  777. class function GetHashCode(AKey: Pointer; ASize: SizeInt; AInitVal: UInt32 = 0): UInt32; override;
  778. end;
  779. { TGenericsHashFactory }
  780. TGenericsHashFactory = class(THashFactory)
  781. public
  782. class function GetHashService: THashServiceClass; override;
  783. class function GetHashCode(AKey: Pointer; ASize: SizeInt; AInitVal: UInt32 = 0): UInt32; override;
  784. end;
  785. { TxxHash32HashFactory }
  786. TxxHash32HashFactory = class(THashFactory)
  787. public
  788. class function GetHashService: THashServiceClass; override;
  789. class function GetHashCode(AKey: Pointer; ASize: SizeInt; AInitVal: UInt32 = 0): UInt32; override;
  790. end;
  791. { TxxHash32PascalHashFactory }
  792. TxxHash32PascalHashFactory = class(THashFactory)
  793. public
  794. class function GetHashService: THashServiceClass; override;
  795. class function GetHashCode(AKey: Pointer; ASize: SizeInt; AInitVal: UInt32 = 0): UInt32; override;
  796. end;
  797. { TAdler32HashFactory }
  798. TAdler32HashFactory = class(THashFactory)
  799. public
  800. class function GetHashService: THashServiceClass; override;
  801. class function GetHashCode(AKey: Pointer; ASize: SizeInt; AInitVal: UInt32 = 0): UInt32; override;
  802. end;
  803. { TSdbmHashFactory }
  804. TSdbmHashFactory = class(THashFactory)
  805. public
  806. class function GetHashService: THashServiceClass; override;
  807. class function GetHashCode(AKey: Pointer; ASize: SizeInt; AInitVal: UInt32 = 0): UInt32; override;
  808. end;
  809. { TSdbmHashFactory }
  810. TSimpleChecksumFactory = class(THashFactory)
  811. public
  812. class function GetHashService: THashServiceClass; override;
  813. class function GetHashCode(AKey: Pointer; ASize: SizeInt; AInitVal: UInt32 = 0): UInt32; override;
  814. end;
  815. { TDelphiDoubleHashFactory }
  816. TDelphiDoubleHashFactory = class(TExtendedHashFactory)
  817. public
  818. const MAX_HASHLIST_COUNT = 2;
  819. const HASH_FUNCTIONS_COUNT = 1;
  820. const HASHLIST_COUNT_PER_FUNCTION: array[1..HASH_FUNCTIONS_COUNT] of Integer = (2);
  821. const HASH_FUNCTIONS_MASK_SIZE = 1;
  822. const HASH_FUNCTIONS_MASK = 1; // 00000001b
  823. class function GetHashService: THashServiceClass; override;
  824. class function GetHashCode(AKey: Pointer; ASize: SizeInt; AInitVal: UInt32 = 0): UInt32; override;
  825. class procedure GetHashList(AKey: Pointer; ASize: SizeInt; AHashList: PUInt32; AOptions: TGetHashListOptions = []); override;
  826. end;
  827. TDelphiQuadrupleHashFactory = class(TExtendedHashFactory)
  828. public
  829. const MAX_HASHLIST_COUNT = 4;
  830. const HASH_FUNCTIONS_COUNT = 2;
  831. const HASHLIST_COUNT_PER_FUNCTION: array[1..HASH_FUNCTIONS_COUNT] of Integer = (2, 2);
  832. const HASH_FUNCTIONS_MASK_SIZE = 2;
  833. const HASH_FUNCTIONS_MASK = 3; // 00000011b
  834. class function GetHashService: THashServiceClass; override;
  835. class function GetHashCode(AKey: Pointer; ASize: SizeInt; AInitVal: UInt32 = 0): UInt32; override;
  836. class procedure GetHashList(AKey: Pointer; ASize: SizeInt; AHashList: PUInt32; AOptions: TGetHashListOptions = []); override;
  837. end;
  838. TDelphiSixfoldHashFactory = class(TExtendedHashFactory)
  839. public
  840. const MAX_HASHLIST_COUNT = 6;
  841. const HASH_FUNCTIONS_COUNT = 3;
  842. const HASHLIST_COUNT_PER_FUNCTION: array[1..HASH_FUNCTIONS_COUNT] of Integer = (2, 2, 2);
  843. const HASH_FUNCTIONS_MASK_SIZE = 3;
  844. const HASH_FUNCTIONS_MASK = 7; // 00000111b
  845. class function GetHashService: THashServiceClass; override;
  846. class function GetHashCode(AKey: Pointer; ASize: SizeInt; AInitVal: UInt32 = 0): UInt32; override;
  847. class procedure GetHashList(AKey: Pointer; ASize: SizeInt; AHashList: PUInt32; AOptions: TGetHashListOptions = []); override;
  848. end;
  849. TDefaultHashFactory = TGenericsHashFactory;
  850. TDefaultGenericInterface = (giComparer, giEqualityComparer, giExtendedEqualityComparer);
  851. TCustomComparer<T> = class(TSingletonImplementation, IComparer<T>, IEqualityComparer<T>, IExtendedEqualityComparer<T>)
  852. protected
  853. function Compare(const Left, Right: T): Integer; virtual; abstract;
  854. function Equals(const Left, Right: T): Boolean; reintroduce; overload; virtual; abstract;
  855. function GetHashCode(const Value: T): UInt32; reintroduce; overload; virtual; abstract;
  856. procedure GetHashList(const Value: T; AHashList: PUInt32); virtual; abstract;
  857. end;
  858. TOrdinalComparer<T, THashFactory> = class(TCustomComparer<T>)
  859. protected class var
  860. FComparer: IComparer<T>;
  861. FEqualityComparer: IEqualityComparer<T>;
  862. FExtendedEqualityComparer: IExtendedEqualityComparer<T>;
  863. class constructor Create;
  864. public
  865. class function Ordinal: TCustomComparer<T>; virtual; abstract;
  866. end;
  867. // TGStringComparer will be renamed to TStringComparer -> bug #26030
  868. // anyway class var can't be used safely -> bug #24848
  869. TGStringComparer<T, THashFactory> = class(TOrdinalComparer<T, THashFactory>)
  870. private class var
  871. FOrdinal: TCustomComparer<T>;
  872. class destructor Destroy;
  873. public
  874. class function Ordinal: TCustomComparer<T>; override;
  875. end;
  876. TGStringComparer<T> = class(TGStringComparer<T, TDelphiQuadrupleHashFactory>);
  877. TStringComparer = class(TGStringComparer<string>);
  878. TAnsiStringComparer = class(TGStringComparer<AnsiString>);
  879. TUnicodeStringComparer = class(TGStringComparer<UnicodeString>);
  880. { TGOrdinalStringComparer }
  881. // TGOrdinalStringComparer will be renamed to TOrdinalStringComparer -> bug #26030
  882. // anyway class var can't be used safely -> bug #24848
  883. TGOrdinalStringComparer<T, THashFactory> = class(TGStringComparer<T, THashFactory>)
  884. public
  885. function Compare(const ALeft, ARight: T): Integer; override;
  886. function Equals(const ALeft, ARight: T): Boolean; overload; override;
  887. function GetHashCode(const AValue: T): UInt32; overload; override;
  888. procedure GetHashList(const AValue: T; AHashList: PUInt32); override;
  889. end;
  890. TGOrdinalStringComparer<T> = class(TGOrdinalStringComparer<T, TDelphiQuadrupleHashFactory>);
  891. TOrdinalStringComparer = class(TGOrdinalStringComparer<string>);
  892. TGIStringComparer<T, THashFactory> = class(TOrdinalComparer<T, THashFactory>)
  893. private class var
  894. FOrdinal: TCustomComparer<T>;
  895. class destructor Destroy;
  896. public
  897. class function Ordinal: TCustomComparer<T>; override;
  898. end;
  899. TGIStringComparer<T> = class(TGIStringComparer<T, TDelphiQuadrupleHashFactory>);
  900. TIStringComparer = class(TGIStringComparer<string>);
  901. TIAnsiStringComparer = class(TGIStringComparer<AnsiString>);
  902. TIUnicodeStringComparer = class(TGIStringComparer<UnicodeString>);
  903. TGOrdinalIStringComparer<T, THashFactory> = class(TGIStringComparer<T, THashFactory>)
  904. public
  905. function Compare(const ALeft, ARight: T): Integer; override;
  906. function Equals(const ALeft, ARight: T): Boolean; overload; override;
  907. function GetHashCode(const AValue: T): UInt32; overload; override;
  908. procedure GetHashList(const AValue: T; AHashList: PUInt32); override;
  909. end;
  910. TGOrdinalIStringComparer<T> = class(TGOrdinalIStringComparer<T, TDelphiQuadrupleHashFactory>);
  911. TOrdinalIStringComparer = class(TGOrdinalIStringComparer<string>);
  912. // Delphi version of Bob Jenkins Hash
  913. function BobJenkinsHash(const AData; ALength, AInitData: Integer): Integer; // same result as HashLittle_Delphi, just different interface
  914. function BinaryCompare(const ALeft, ARight: Pointer; ASize: PtrUInt): Integer; inline;
  915. function _LookupVtableInfo(AGInterface: TDefaultGenericInterface; ATypeInfo: PTypeInfo; ASize: SizeInt): Pointer; inline;
  916. function _LookupVtableInfoEx(AGInterface: TDefaultGenericInterface; ATypeInfo: PTypeInfo; ASize: SizeInt;
  917. AFactory: THashFactoryClass): Pointer;
  918. Type
  919. TCollectionItemComparer = IComparer<TCollectionItem>;
  920. TCollectionHelper = Class helper for TCollection
  921. Procedure sort(const AComparer: TCollectionItemComparer); overload;
  922. end;
  923. implementation
  924. { TComparer<T> }
  925. class function TComparer<T>.Default: IComparer<T>;
  926. begin
  927. if TComparerService.TypeNeedsBinaryMethods<T> then begin
  928. Result := TBinaryComparer<T>.Create
  929. end else
  930. Result := _LookupVtableInfo(giComparer, TypeInfo(T), SizeOf(T));
  931. end;
  932. class function TComparer<T>.Construct(const AComparison: TOnComparison<T>): IComparer<T>;
  933. begin
  934. Result := TDelegatedComparerEvents<T>.Create(AComparison);
  935. end;
  936. class function TComparer<T>.Construct(const AComparison: TComparison<T>): IComparer<T>;
  937. begin
  938. Result := TDelegatedComparer<T>.Create(AComparison);
  939. end;
  940. class function TComparer<T>.Construct(const AComparison: TComparisonFunc<T>): IComparer<T>;
  941. begin
  942. Result := TDelegatedComparerFunc<T>.Create(AComparison);
  943. end;
  944. function TDelegatedComparerEvents<T>.Compare(const ALeft, ARight: T): Integer;
  945. begin
  946. Result := FComparison(ALeft, ARight);
  947. end;
  948. constructor TDelegatedComparerEvents<T>.Create(AComparison: TOnComparison<T>);
  949. begin
  950. FComparison := AComparison;
  951. end;
  952. function TDelegatedComparerFunc<T>.Compare(const ALeft, ARight: T): Integer;
  953. begin
  954. Result := FComparison(ALeft, ARight);
  955. end;
  956. constructor TDelegatedComparerFunc<T>.Create(AComparison: TComparisonFunc<T>);
  957. begin
  958. FComparison := AComparison;
  959. end;
  960. constructor TDelegatedComparer<T>.Create(const aCompare: TComparison<T>);
  961. begin
  962. FCompareFunc:=aCompare;
  963. end;
  964. function TDelegatedComparer<T>.Compare(const aLeft, aRight: T): Integer;
  965. begin
  966. Result:=FCompareFunc(aLeft, aRight);
  967. end;
  968. { TInterface }
  969. function TInterface.QueryInterface(constref IID: TGUID; out Obj): HResult;
  970. begin
  971. Result := E_NOINTERFACE;
  972. end;
  973. { TRawInterface }
  974. function TRawInterface._AddRef: LongInt;
  975. begin
  976. Result := -1;
  977. end;
  978. function TRawInterface._Release: LongInt;
  979. begin
  980. Result := -1;
  981. end;
  982. { TComTypeSizeInterface }
  983. function TComTypeSizeInterface._AddRef: LongInt;
  984. var
  985. _self: TComparerService.PSpoofInterfacedTypeSizeObject absolute Self;
  986. begin
  987. Result := InterLockedIncrement(_self.RefCount);
  988. end;
  989. function TComTypeSizeInterface._Release: LongInt;
  990. var
  991. _self: TComparerService.PSpoofInterfacedTypeSizeObject absolute Self;
  992. begin
  993. Result := InterLockedDecrement(_self.RefCount);
  994. if _self.RefCount = 0 then
  995. Dispose(_self);
  996. end;
  997. { TSingletonImplementation }
  998. function TSingletonImplementation.QueryInterface(constref IID: TGUID; out Obj): HResult;
  999. begin
  1000. if GetInterface(IID, Obj) then
  1001. Result := S_OK
  1002. else
  1003. Result := E_NOINTERFACE;
  1004. end;
  1005. { TCompare }
  1006. (***********************************************************************************************************************
  1007. Comparers
  1008. (**********************************************************************************************************************)
  1009. {-----------------------------------------------------------------------------------------------------------------------
  1010. Comparers Int8 - Int32 and UInt8 - UInt32
  1011. {----------------------------------------------------------------------------------------------------------------------}
  1012. class function TCompare.Integer(const ALeft, ARight: Integer): Integer;
  1013. begin
  1014. Result := {$IFDEF FPC_DOTTEDUNITS}System.{$ENDIF}Math.CompareValue(ALeft, ARight);
  1015. end;
  1016. class function TCompare.Int8(const ALeft, ARight: Int8): Integer;
  1017. begin
  1018. Result := ALeft - ARight;
  1019. end;
  1020. class function TCompare.Int16(const ALeft, ARight: Int16): Integer;
  1021. begin
  1022. Result := ALeft - ARight;
  1023. end;
  1024. class function TCompare.Int32(const ALeft, ARight: Int32): Integer;
  1025. begin
  1026. if ALeft > ARight then
  1027. Exit(1)
  1028. else if ALeft < ARight then
  1029. Exit(-1)
  1030. else
  1031. Exit(0);
  1032. end;
  1033. class function TCompare.Int64(const ALeft, ARight: Int64): Integer;
  1034. begin
  1035. if ALeft > ARight then
  1036. Exit(1)
  1037. else if ALeft < ARight then
  1038. Exit(-1)
  1039. else
  1040. Exit(0);
  1041. end;
  1042. class function TCompare.UInt8(const ALeft, ARight: UInt8): Integer;
  1043. begin
  1044. Result := System.Integer(ALeft) - System.Integer(ARight);
  1045. end;
  1046. class function TCompare.UInt16(const ALeft, ARight: UInt16): Integer;
  1047. begin
  1048. Result := System.Integer(ALeft) - System.Integer(ARight);
  1049. end;
  1050. class function TCompare.UInt32(const ALeft, ARight: UInt32): Integer;
  1051. begin
  1052. if ALeft > ARight then
  1053. Exit(1)
  1054. else if ALeft < ARight then
  1055. Exit(-1)
  1056. else
  1057. Exit(0);
  1058. end;
  1059. class function TCompare.UInt64(const ALeft, ARight: UInt64): Integer;
  1060. begin
  1061. if ALeft > ARight then
  1062. Exit(1)
  1063. else if ALeft < ARight then
  1064. Exit(-1)
  1065. else
  1066. Exit(0);
  1067. end;
  1068. {-----------------------------------------------------------------------------------------------------------------------
  1069. Comparers for Float types
  1070. {----------------------------------------------------------------------------------------------------------------------}
  1071. class function TCompare.Single(const ALeft, ARight: Single): Integer;
  1072. begin
  1073. if ALeft > ARight then
  1074. Exit(1)
  1075. else if ALeft < ARight then
  1076. Exit(-1)
  1077. else
  1078. Exit(0);
  1079. end;
  1080. class function TCompare.Double(const ALeft, ARight: Double): Integer;
  1081. begin
  1082. if ALeft > ARight then
  1083. Exit(1)
  1084. else if ALeft < ARight then
  1085. Exit(-1)
  1086. else
  1087. Exit(0);
  1088. end;
  1089. class function TCompare.Extended(const ALeft, ARight: Extended): Integer;
  1090. begin
  1091. if ALeft > ARight then
  1092. Exit(1)
  1093. else if ALeft < ARight then
  1094. Exit(-1)
  1095. else
  1096. Exit(0);
  1097. end;
  1098. {-----------------------------------------------------------------------------------------------------------------------
  1099. Comparers for other number types
  1100. {----------------------------------------------------------------------------------------------------------------------}
  1101. class function TCompare.Currency(const ALeft, ARight: Currency): Integer;
  1102. begin
  1103. if ALeft > ARight then
  1104. Exit(1)
  1105. else if ALeft < ARight then
  1106. Exit(-1)
  1107. else
  1108. Exit(0);
  1109. end;
  1110. class function TCompare.Comp(const ALeft, ARight: Comp): Integer;
  1111. begin
  1112. if ALeft > ARight then
  1113. Exit(1)
  1114. else if ALeft < ARight then
  1115. Exit(-1)
  1116. else
  1117. Exit(0);
  1118. end;
  1119. {-----------------------------------------------------------------------------------------------------------------------
  1120. Comparers for binary data (records etc) and dynamics arrays
  1121. {----------------------------------------------------------------------------------------------------------------------}
  1122. class function TCompare._Binary(const ALeft, ARight): Integer;
  1123. var
  1124. _self: TComparerService.PSpoofInterfacedTypeSizeObject absolute Self;
  1125. begin
  1126. Result := CompareMemRange(@ALeft, @ARight, _self.Size)
  1127. end;
  1128. class function TCompare._DynArray(const ALeft, ARight: Pointer): Integer;
  1129. var
  1130. _self: TComparerService.PSpoofInterfacedTypeSizeObject absolute Self;
  1131. LLength, LLeftLength, LRightLength: Integer;
  1132. begin
  1133. LLeftLength := DynArraySize(ALeft);
  1134. LRightLength := DynArraySize(ARight);
  1135. if LLeftLength > LRightLength then
  1136. LLength := LRightLength
  1137. else
  1138. LLength := LLeftLength;
  1139. Result := CompareMemRange(ALeft, ARight, LLength * _self.Size);
  1140. if Result = 0 then
  1141. Result := LLeftLength - LRightLength;
  1142. end;
  1143. class function TCompare.Binary(const ALeft, ARight; const ASize: SizeInt): Integer;
  1144. begin
  1145. Result := CompareMemRange(@ALeft, @ARight, ASize);
  1146. end;
  1147. class function TCompare.DynArray(const ALeft, ARight: Pointer; const AElementSize: SizeInt): Integer;
  1148. var
  1149. LLength, LLeftLength, LRightLength: Integer;
  1150. begin
  1151. LLeftLength := DynArraySize(ALeft);
  1152. LRightLength := DynArraySize(ARight);
  1153. if LLeftLength > LRightLength then
  1154. LLength := LRightLength
  1155. else
  1156. LLength := LLeftLength;
  1157. Result := CompareMemRange(ALeft, ARight, LLength * AElementSize);
  1158. if Result = 0 then
  1159. Result := LLeftLength - LRightLength;
  1160. end;
  1161. {-----------------------------------------------------------------------------------------------------------------------
  1162. Comparers for string types
  1163. {----------------------------------------------------------------------------------------------------------------------}
  1164. class function TCompare.ShortString1(const ALeft, ARight: ShortString1): Integer;
  1165. begin
  1166. if ALeft > ARight then
  1167. Exit(1)
  1168. else if ALeft < ARight then
  1169. Exit(-1)
  1170. else
  1171. Exit(0);
  1172. end;
  1173. class function TCompare.ShortString2(const ALeft, ARight: ShortString2): Integer;
  1174. begin
  1175. if ALeft > ARight then
  1176. Exit(1)
  1177. else if ALeft < ARight then
  1178. Exit(-1)
  1179. else
  1180. Exit(0);
  1181. end;
  1182. class function TCompare.ShortString3(const ALeft, ARight: ShortString3): Integer;
  1183. begin
  1184. if ALeft > ARight then
  1185. Exit(1)
  1186. else if ALeft < ARight then
  1187. Exit(-1)
  1188. else
  1189. Exit(0);
  1190. end;
  1191. class function TCompare.ShortString(const ALeft, ARight: ShortString): Integer;
  1192. begin
  1193. if ALeft > ARight then
  1194. Exit(1)
  1195. else if ALeft < ARight then
  1196. Exit(-1)
  1197. else
  1198. Exit(0);
  1199. end;
  1200. class function TCompare.&String(const ALeft, ARight: String): Integer;
  1201. begin
  1202. Result := CompareStr(ALeft, ARight);
  1203. end;
  1204. class function TCompare.AnsiString(const ALeft, ARight: AnsiString): Integer;
  1205. begin
  1206. Result := AnsiCompareStr(ALeft, ARight);
  1207. end;
  1208. class function TCompare.WideString(const ALeft, ARight: WideString): Integer;
  1209. begin
  1210. Result := WideCompareStr(ALeft, ARight);
  1211. end;
  1212. class function TCompare.UnicodeString(const ALeft, ARight: UnicodeString): Integer;
  1213. begin
  1214. Result := UnicodeCompareStr(ALeft, ARight);
  1215. end;
  1216. {-----------------------------------------------------------------------------------------------------------------------
  1217. Comparers for Delegates
  1218. {----------------------------------------------------------------------------------------------------------------------}
  1219. class function TCompare.Method(const ALeft, ARight: TMethod): Integer;
  1220. begin
  1221. Result := CompareMemRange(@ALeft, @ARight, SizeOf(System.TMethod));
  1222. end;
  1223. {-----------------------------------------------------------------------------------------------------------------------
  1224. Comparers for Variant
  1225. {----------------------------------------------------------------------------------------------------------------------}
  1226. class function TCompare.Variant(const ALeft, ARight: PVariant): Integer;
  1227. var
  1228. LLeftString, LRightString: string;
  1229. begin
  1230. try
  1231. case VarCompareValue(ALeft^, ARight^) of
  1232. vrGreaterThan:
  1233. Exit(1);
  1234. vrLessThan:
  1235. Exit(-1);
  1236. vrEqual:
  1237. Exit(0);
  1238. vrNotEqual:
  1239. if VarIsEmpty(ALeft^) or VarIsNull(ALeft^) then
  1240. Exit(1)
  1241. else
  1242. Exit(-1);
  1243. end;
  1244. except
  1245. try
  1246. LLeftString := ALeft^;
  1247. LRightString := ARight^;
  1248. Result := CompareStr(LLeftString, LRightString);
  1249. except
  1250. Result := CompareMemRange(ALeft, ARight, SizeOf(System.Variant));
  1251. end;
  1252. end;
  1253. end;
  1254. {-----------------------------------------------------------------------------------------------------------------------
  1255. Comparers for Pointer
  1256. {----------------------------------------------------------------------------------------------------------------------}
  1257. class function TCompare.Pointer(const ALeft, ARight: PtrUInt): Integer;
  1258. begin
  1259. if ALeft > ARight then
  1260. Exit(1)
  1261. else if ALeft < ARight then
  1262. Exit(-1)
  1263. else
  1264. Exit(0);
  1265. end;
  1266. { TEquals }
  1267. (***********************************************************************************************************************
  1268. Equality Comparers
  1269. (**********************************************************************************************************************)
  1270. {-----------------------------------------------------------------------------------------------------------------------
  1271. Equality Comparers Int8 - Int32 and UInt8 - UInt32
  1272. {----------------------------------------------------------------------------------------------------------------------}
  1273. class function TEquals.Integer(const ALeft, ARight: Integer): Boolean;
  1274. begin
  1275. Result := ALeft = ARight;
  1276. end;
  1277. class function TEquals.Int8(const ALeft, ARight: Int8): Boolean;
  1278. begin
  1279. Result := ALeft = ARight;
  1280. end;
  1281. class function TEquals.Int16(const ALeft, ARight: Int16): Boolean;
  1282. begin
  1283. Result := ALeft = ARight;
  1284. end;
  1285. class function TEquals.Int32(const ALeft, ARight: Int32): Boolean;
  1286. begin
  1287. Result := ALeft = ARight;
  1288. end;
  1289. class function TEquals.Int64(const ALeft, ARight: Int64): Boolean;
  1290. begin
  1291. Result := ALeft = ARight;
  1292. end;
  1293. class function TEquals.UInt8(const ALeft, ARight: UInt8): Boolean;
  1294. begin
  1295. Result := ALeft = ARight;
  1296. end;
  1297. class function TEquals.UInt16(const ALeft, ARight: UInt16): Boolean;
  1298. begin
  1299. Result := ALeft = ARight;
  1300. end;
  1301. class function TEquals.UInt32(const ALeft, ARight: UInt32): Boolean;
  1302. begin
  1303. Result := ALeft = ARight;
  1304. end;
  1305. class function TEquals.UInt64(const ALeft, ARight: UInt64): Boolean;
  1306. begin
  1307. Result := ALeft = ARight;
  1308. end;
  1309. {-----------------------------------------------------------------------------------------------------------------------
  1310. Equality Comparers for Float types
  1311. {----------------------------------------------------------------------------------------------------------------------}
  1312. class function TEquals.Single(const ALeft, ARight: Single): Boolean;
  1313. begin
  1314. Result := ALeft = ARight;
  1315. end;
  1316. class function TEquals.Double(const ALeft, ARight: Double): Boolean;
  1317. begin
  1318. Result := ALeft = ARight;
  1319. end;
  1320. class function TEquals.Extended(const ALeft, ARight: Extended): Boolean;
  1321. begin
  1322. Result := ALeft = ARight;
  1323. end;
  1324. {-----------------------------------------------------------------------------------------------------------------------
  1325. Equality Comparers for other number types
  1326. {----------------------------------------------------------------------------------------------------------------------}
  1327. class function TEquals.Currency(const ALeft, ARight: Currency): Boolean;
  1328. begin
  1329. Result := ALeft = ARight;
  1330. end;
  1331. class function TEquals.Comp(const ALeft, ARight: Comp): Boolean;
  1332. begin
  1333. Result := ALeft = ARight;
  1334. end;
  1335. {-----------------------------------------------------------------------------------------------------------------------
  1336. Equality Comparers for binary data (records etc) and dynamics arrays
  1337. {----------------------------------------------------------------------------------------------------------------------}
  1338. class function TEquals._Binary(const ALeft, ARight): Boolean;
  1339. var
  1340. _self: TComparerService.PSpoofInterfacedTypeSizeObject absolute Self;
  1341. begin
  1342. Result := CompareMem(@ALeft, @ARight, _self.Size)
  1343. end;
  1344. class function TEquals._DynArray(const ALeft, ARight: Pointer): Boolean;
  1345. var
  1346. _self: TComparerService.PSpoofInterfacedTypeSizeObject absolute Self;
  1347. LLength: Integer;
  1348. begin
  1349. LLength := DynArraySize(ALeft);
  1350. if LLength <> DynArraySize(ARight) then
  1351. Exit(False);
  1352. Result := CompareMem(ALeft, ARight, LLength * _self.Size);
  1353. end;
  1354. class function TEquals.Binary(const ALeft, ARight; const ASize: SizeInt): Boolean;
  1355. begin
  1356. Result := CompareMem(@ALeft, @ARight, ASize);
  1357. end;
  1358. class function TEquals.DynArray(const ALeft, ARight: Pointer; const AElementSize: SizeInt): Boolean;
  1359. var
  1360. LLength: Integer;
  1361. begin
  1362. LLength := DynArraySize(ALeft);
  1363. if LLength <> DynArraySize(ARight) then
  1364. Exit(False);
  1365. Result := CompareMem(ALeft, ARight, LLength * AElementSize);
  1366. end;
  1367. {-----------------------------------------------------------------------------------------------------------------------
  1368. Equality Comparers for classes
  1369. {----------------------------------------------------------------------------------------------------------------------}
  1370. class function TEquals.&class(const ALeft, ARight: TObject): Boolean;
  1371. begin
  1372. if ALeft <> nil then
  1373. Exit(ALeft.Equals(ARight))
  1374. else
  1375. Exit(ARight = nil);
  1376. end;
  1377. {-----------------------------------------------------------------------------------------------------------------------
  1378. Equality Comparers for string types
  1379. {----------------------------------------------------------------------------------------------------------------------}
  1380. class function TEquals.ShortString1(const ALeft, ARight: ShortString1): Boolean;
  1381. begin
  1382. Result := ALeft = ARight;
  1383. end;
  1384. class function TEquals.ShortString2(const ALeft, ARight: ShortString2): Boolean;
  1385. begin
  1386. Result := ALeft = ARight;
  1387. end;
  1388. class function TEquals.ShortString3(const ALeft, ARight: ShortString3): Boolean;
  1389. begin
  1390. Result := ALeft = ARight;
  1391. end;
  1392. class function TEquals.&String(const ALeft, ARight: String): Boolean;
  1393. begin
  1394. Result := ALeft = ARight;
  1395. end;
  1396. class function TEquals.ShortString(const ALeft, ARight: ShortString): Boolean;
  1397. begin
  1398. Result := ALeft = ARight;
  1399. end;
  1400. class function TEquals.AnsiString(const ALeft, ARight: AnsiString): Boolean;
  1401. begin
  1402. Result := ALeft = ARight;
  1403. end;
  1404. class function TEquals.WideString(const ALeft, ARight: WideString): Boolean;
  1405. begin
  1406. Result := ALeft = ARight;
  1407. end;
  1408. class function TEquals.UnicodeString(const ALeft, ARight: UnicodeString): Boolean;
  1409. begin
  1410. Result := ALeft = ARight;
  1411. end;
  1412. {-----------------------------------------------------------------------------------------------------------------------
  1413. Equality Comparers for Delegates
  1414. {----------------------------------------------------------------------------------------------------------------------}
  1415. class function TEquals.Method(const ALeft, ARight: TMethod): Boolean;
  1416. begin
  1417. Result := (ALeft.Code = ARight.Code) and (ALeft.Data = ARight.Data);
  1418. end;
  1419. {-----------------------------------------------------------------------------------------------------------------------
  1420. Equality Comparers for Variant
  1421. {----------------------------------------------------------------------------------------------------------------------}
  1422. class function TEquals.Variant(const ALeft, ARight: PVariant): Boolean;
  1423. begin
  1424. Result := VarCompareValue(ALeft^, ARight^) = vrEqual;
  1425. end;
  1426. {-----------------------------------------------------------------------------------------------------------------------
  1427. Equality Comparers for Pointer
  1428. {----------------------------------------------------------------------------------------------------------------------}
  1429. class function TEquals.Pointer(const ALeft, ARight: PtrUInt): Boolean;
  1430. begin
  1431. Result := ALeft = ARight;
  1432. end;
  1433. (***********************************************************************************************************************
  1434. Hashes
  1435. (**********************************************************************************************************************)
  1436. {-----------------------------------------------------------------------------------------------------------------------
  1437. GetHashCode Int8 - Int32 and UInt8 - UInt32
  1438. {----------------------------------------------------------------------------------------------------------------------}
  1439. class function THashFactory.Int8(const AValue: Int8): UInt32;
  1440. begin
  1441. Result := HASH_FACTORY.GetHashCode(@AValue, SizeOf(System.Int8), 0);
  1442. end;
  1443. class function THashFactory.Int16(const AValue: Int16): UInt32;
  1444. begin
  1445. Result := HASH_FACTORY.GetHashCode(@AValue, SizeOf(System.Int16), 0);
  1446. end;
  1447. class function THashFactory.Int32(const AValue: Int32): UInt32;
  1448. begin
  1449. Result := HASH_FACTORY.GetHashCode(@AValue, SizeOf(System.Int32), 0);
  1450. end;
  1451. class function THashFactory.Int64(const AValue: Int64): UInt32;
  1452. begin
  1453. Result := HASH_FACTORY.GetHashCode(@AValue, SizeOf(System.Int64), 0);
  1454. end;
  1455. class function THashFactory.UInt8(const AValue: UInt8): UInt32;
  1456. begin
  1457. Result := HASH_FACTORY.GetHashCode(@AValue, SizeOf(System.UInt8), 0);
  1458. end;
  1459. class function THashFactory.UInt16(const AValue: UInt16): UInt32;
  1460. begin
  1461. Result := HASH_FACTORY.GetHashCode(@AValue, SizeOf(System.UInt16), 0);
  1462. end;
  1463. class function THashFactory.UInt32(const AValue: UInt32): UInt32;
  1464. begin
  1465. Result := HASH_FACTORY.GetHashCode(@AValue, SizeOf(System.UInt32), 0);
  1466. end;
  1467. class function THashFactory.UInt64(const AValue: UInt64): UInt32;
  1468. begin
  1469. Result := HASH_FACTORY.GetHashCode(@AValue, SizeOf(System.UInt64), 0);
  1470. end;
  1471. {-----------------------------------------------------------------------------------------------------------------------
  1472. GetHashCode for Float types
  1473. {----------------------------------------------------------------------------------------------------------------------}
  1474. class function THashFactory.Single(const AValue: Single): UInt32;
  1475. var
  1476. LMantissa: Float;
  1477. LExponent: Integer;
  1478. begin
  1479. Frexp(AValue, LMantissa, LExponent);
  1480. if LMantissa = 0 then
  1481. LMantissa := Abs(LMantissa);
  1482. Result := HASH_FACTORY.GetHashCode(@LMantissa, SizeOf({$IFDEF FPC_DOTTEDUNITS}System.{$ENDIF}Math.Float), 0);
  1483. Result := HASH_FACTORY.GetHashCode(@LExponent, SizeOf(System.Integer), Result);
  1484. end;
  1485. class function THashFactory.Double(const AValue: Double): UInt32;
  1486. var
  1487. LMantissa: Float;
  1488. LExponent: Integer;
  1489. begin
  1490. Frexp(AValue, LMantissa, LExponent);
  1491. if LMantissa = 0 then
  1492. LMantissa := Abs(LMantissa);
  1493. Result := HASH_FACTORY.GetHashCode(@LMantissa, SizeOf({$IFDEF FPC_DOTTEDUNITS}System.{$ENDIF}Math.Float), 0);
  1494. Result := HASH_FACTORY.GetHashCode(@LExponent, SizeOf(System.Integer), Result);
  1495. end;
  1496. class function THashFactory.Extended(const AValue: Extended): UInt32;
  1497. var
  1498. LMantissa: Float;
  1499. LExponent: Integer;
  1500. begin
  1501. Frexp(AValue, LMantissa, LExponent);
  1502. if LMantissa = 0 then
  1503. LMantissa := Abs(LMantissa);
  1504. Result := HASH_FACTORY.GetHashCode(@LMantissa, SizeOf({$IFDEF FPC_DOTTEDUNITS}System.{$ENDIF}Math.Float), 0);
  1505. Result := HASH_FACTORY.GetHashCode(@LExponent, SizeOf(System.Integer), Result);
  1506. end;
  1507. {-----------------------------------------------------------------------------------------------------------------------
  1508. GetHashCode for other number types
  1509. {----------------------------------------------------------------------------------------------------------------------}
  1510. class function THashFactory.Currency(const AValue: Currency): UInt32;
  1511. begin
  1512. Result := HASH_FACTORY.GetHashCode(@AValue, SizeOf(System.Int64), 0);
  1513. end;
  1514. class function THashFactory.Comp(const AValue: Comp): UInt32;
  1515. begin
  1516. Result := HASH_FACTORY.GetHashCode(@AValue, SizeOf(System.Int64), 0);
  1517. end;
  1518. {-----------------------------------------------------------------------------------------------------------------------
  1519. GetHashCode for binary data (records etc) and dynamics arrays
  1520. {----------------------------------------------------------------------------------------------------------------------}
  1521. class function THashFactory.Binary(const AValue): UInt32;
  1522. var
  1523. _self: TComparerService.PSpoofInterfacedTypeSizeObject absolute Self;
  1524. begin
  1525. Result := HASH_FACTORY.GetHashCode(@AValue, _self.Size, 0);
  1526. end;
  1527. class function THashFactory.DynArray(const AValue: Pointer): UInt32;
  1528. var
  1529. _self: TComparerService.PSpoofInterfacedTypeSizeObject absolute Self;
  1530. begin
  1531. Result := HASH_FACTORY.GetHashCode(AValue, DynArraySize(AValue) * _self.Size, 0);
  1532. end;
  1533. {-----------------------------------------------------------------------------------------------------------------------
  1534. GetHashCode for classes
  1535. {----------------------------------------------------------------------------------------------------------------------}
  1536. class function THashFactory.&Class(const AValue: TObject): UInt32;
  1537. begin
  1538. if AValue = nil then
  1539. Exit($2A);
  1540. Result := AValue.GetHashCode;
  1541. end;
  1542. {-----------------------------------------------------------------------------------------------------------------------
  1543. GetHashCode for string types
  1544. {----------------------------------------------------------------------------------------------------------------------}
  1545. class function THashFactory.ShortString1(const AValue: ShortString1): UInt32;
  1546. begin
  1547. Result := HASH_FACTORY.GetHashCode(@AValue[1], Length(AValue), 0);
  1548. end;
  1549. class function THashFactory.ShortString2(const AValue: ShortString2): UInt32;
  1550. begin
  1551. Result := HASH_FACTORY.GetHashCode(@AValue[1], Length(AValue), 0);
  1552. end;
  1553. class function THashFactory.ShortString3(const AValue: ShortString3): UInt32;
  1554. begin
  1555. Result := HASH_FACTORY.GetHashCode(@AValue[1], Length(AValue), 0);
  1556. end;
  1557. class function THashFactory.ShortString(const AValue: ShortString): UInt32;
  1558. begin
  1559. Result := HASH_FACTORY.GetHashCode(@AValue[1], Length(AValue), 0);
  1560. end;
  1561. class function THashFactory.AnsiString(const AValue: AnsiString): UInt32;
  1562. begin
  1563. Result := HASH_FACTORY.GetHashCode(@AValue[1], Length(AValue) * SizeOf(System.AnsiChar), 0);
  1564. end;
  1565. class function THashFactory.WideString(const AValue: WideString): UInt32;
  1566. begin
  1567. Result := HASH_FACTORY.GetHashCode(@AValue[1], Length(AValue) * SizeOf(System.WideChar), 0);
  1568. end;
  1569. class function THashFactory.UnicodeString(const AValue: UnicodeString): UInt32;
  1570. begin
  1571. Result := HASH_FACTORY.GetHashCode(@AValue[1], Length(AValue) * SizeOf(System.UnicodeChar), 0);
  1572. end;
  1573. {-----------------------------------------------------------------------------------------------------------------------
  1574. GetHashCode for Delegates
  1575. {----------------------------------------------------------------------------------------------------------------------}
  1576. class function THashFactory.Method(const AValue: TMethod): UInt32;
  1577. begin
  1578. Result := HASH_FACTORY.GetHashCode(@AValue, SizeOf(System.TMethod), 0);
  1579. end;
  1580. {-----------------------------------------------------------------------------------------------------------------------
  1581. GetHashCode for Variant
  1582. {----------------------------------------------------------------------------------------------------------------------}
  1583. class function THashFactory.Variant(const AValue: PVariant): UInt32;
  1584. begin
  1585. try
  1586. Result := HASH_FACTORY.UnicodeString(AValue^);
  1587. except
  1588. Result := HASH_FACTORY.GetHashCode(AValue, SizeOf(System.Variant), 0);
  1589. end;
  1590. end;
  1591. {-----------------------------------------------------------------------------------------------------------------------
  1592. GetHashCode for Pointer
  1593. {----------------------------------------------------------------------------------------------------------------------}
  1594. class function THashFactory.Pointer(const AValue: Pointer): UInt32;
  1595. begin
  1596. Result := HASH_FACTORY.GetHashCode(@AValue, SizeOf(System.Pointer), 0);
  1597. end;
  1598. { TExtendedHashFactory }
  1599. (***********************************************************************************************************************
  1600. Hashes 2
  1601. (**********************************************************************************************************************)
  1602. {-----------------------------------------------------------------------------------------------------------------------
  1603. GetHashCode Int8 - Int32 and UInt8 - UInt32
  1604. {----------------------------------------------------------------------------------------------------------------------}
  1605. class procedure TExtendedHashFactory.Int8(const AValue: Int8; AHashList: PUInt32);
  1606. begin
  1607. EXTENDED_HASH_FACTORY.GetHashList(@AValue, SizeOf(System.Int8), AHashList, []);
  1608. end;
  1609. class procedure TExtendedHashFactory.Int16(const AValue: Int16; AHashList: PUInt32);
  1610. begin
  1611. EXTENDED_HASH_FACTORY.GetHashList(@AValue, SizeOf(System.Int16), AHashList, []);
  1612. end;
  1613. class procedure TExtendedHashFactory.Int32(const AValue: Int32; AHashList: PUInt32);
  1614. begin
  1615. EXTENDED_HASH_FACTORY.GetHashList(@AValue, SizeOf(System.Int32), AHashList, []);
  1616. end;
  1617. class procedure TExtendedHashFactory.Int64(const AValue: Int64; AHashList: PUInt32);
  1618. begin
  1619. EXTENDED_HASH_FACTORY.GetHashList(@AValue, SizeOf(System.Int64), AHashList, []);
  1620. end;
  1621. class procedure TExtendedHashFactory.UInt8(const AValue: UInt8; AHashList: PUInt32);
  1622. begin
  1623. EXTENDED_HASH_FACTORY.GetHashList(@AValue, SizeOf(System.UInt8), AHashList, []);
  1624. end;
  1625. class procedure TExtendedHashFactory.UInt16(const AValue: UInt16; AHashList: PUInt32);
  1626. begin
  1627. EXTENDED_HASH_FACTORY.GetHashList(@AValue, SizeOf(System.UInt16), AHashList, []);
  1628. end;
  1629. class procedure TExtendedHashFactory.UInt32(const AValue: UInt32; AHashList: PUInt32);
  1630. begin
  1631. EXTENDED_HASH_FACTORY.GetHashList(@AValue, SizeOf(System.UInt32), AHashList, []);
  1632. end;
  1633. class procedure TExtendedHashFactory.UInt64(const AValue: UInt64; AHashList: PUInt32);
  1634. begin
  1635. EXTENDED_HASH_FACTORY.GetHashList(@AValue, SizeOf(System.UInt64), AHashList, []);
  1636. end;
  1637. {-----------------------------------------------------------------------------------------------------------------------
  1638. GetHashCode for Float types
  1639. {----------------------------------------------------------------------------------------------------------------------}
  1640. class procedure TExtendedHashFactory.Single(const AValue: Single; AHashList: PUInt32);
  1641. var
  1642. LMantissa: Float;
  1643. LExponent: Integer;
  1644. begin
  1645. Frexp(AValue, LMantissa, LExponent);
  1646. if LMantissa = 0 then
  1647. LMantissa := Abs(LMantissa);
  1648. EXTENDED_HASH_FACTORY.GetHashList(@LMantissa, SizeOf({$IFDEF FPC_DOTTEDUNITS}System.{$ENDIF}Math.Float), AHashList, []);
  1649. EXTENDED_HASH_FACTORY.GetHashList(@LExponent, SizeOf(System.Integer), AHashList, [ghloHashListAsInitData]);
  1650. end;
  1651. class procedure TExtendedHashFactory.Double(const AValue: Double; AHashList: PUInt32);
  1652. var
  1653. LMantissa: Float;
  1654. LExponent: Integer;
  1655. begin
  1656. Frexp(AValue, LMantissa, LExponent);
  1657. if LMantissa = 0 then
  1658. LMantissa := Abs(LMantissa);
  1659. EXTENDED_HASH_FACTORY.GetHashList(@LMantissa, SizeOf({$IFDEF FPC_DOTTEDUNITS}System.{$ENDIF}Math.Float), AHashList, []);
  1660. EXTENDED_HASH_FACTORY.GetHashList(@LExponent, SizeOf(System.Integer), AHashList, [ghloHashListAsInitData]);
  1661. end;
  1662. class procedure TExtendedHashFactory.Extended(const AValue: Extended; AHashList: PUInt32);
  1663. var
  1664. LMantissa: Float;
  1665. LExponent: Integer;
  1666. begin
  1667. Frexp(AValue, LMantissa, LExponent);
  1668. if LMantissa = 0 then
  1669. LMantissa := Abs(LMantissa);
  1670. EXTENDED_HASH_FACTORY.GetHashList(@LMantissa, SizeOf({$IFDEF FPC_DOTTEDUNITS}System.{$ENDIF}Math.Float), AHashList, []);
  1671. EXTENDED_HASH_FACTORY.GetHashList(@LExponent, SizeOf(System.Integer), AHashList, [ghloHashListAsInitData]);
  1672. end;
  1673. {-----------------------------------------------------------------------------------------------------------------------
  1674. GetHashCode for other number types
  1675. {----------------------------------------------------------------------------------------------------------------------}
  1676. class procedure TExtendedHashFactory.Currency(const AValue: Currency; AHashList: PUInt32);
  1677. begin
  1678. EXTENDED_HASH_FACTORY.GetHashList(@AValue, SizeOf(System.Int64), AHashList, []);
  1679. end;
  1680. class procedure TExtendedHashFactory.Comp(const AValue: Comp; AHashList: PUInt32);
  1681. begin
  1682. EXTENDED_HASH_FACTORY.GetHashList(@AValue, SizeOf(System.Int64), AHashList, []);
  1683. end;
  1684. {-----------------------------------------------------------------------------------------------------------------------
  1685. GetHashCode for binary data (records etc) and dynamics arrays
  1686. {----------------------------------------------------------------------------------------------------------------------}
  1687. class procedure TExtendedHashFactory.Binary(const AValue; AHashList: PUInt32);
  1688. var
  1689. _self: TComparerService.PSpoofInterfacedTypeSizeObject absolute Self;
  1690. begin
  1691. EXTENDED_HASH_FACTORY.GetHashList(@AValue, _self.Size, AHashList, []);
  1692. end;
  1693. class procedure TExtendedHashFactory.DynArray(const AValue: Pointer; AHashList: PUInt32);
  1694. var
  1695. _self: TComparerService.PSpoofInterfacedTypeSizeObject absolute Self;
  1696. begin
  1697. EXTENDED_HASH_FACTORY.GetHashList(AValue, DynArraySize(AValue) * _self.Size, AHashList, []);
  1698. end;
  1699. {-----------------------------------------------------------------------------------------------------------------------
  1700. GetHashCode for classes
  1701. {----------------------------------------------------------------------------------------------------------------------}
  1702. class procedure TExtendedHashFactory.&Class(const AValue: TObject; AHashList: PUInt32);
  1703. var
  1704. LValue: PtrInt;
  1705. begin
  1706. if AValue = nil then
  1707. begin
  1708. LValue := $2A;
  1709. EXTENDED_HASH_FACTORY.GetHashList(@LValue, SizeOf(LValue), AHashList, []);
  1710. Exit;
  1711. end;
  1712. LValue := AValue.GetHashCode;
  1713. EXTENDED_HASH_FACTORY.GetHashList(@LValue, SizeOf(LValue), AHashList, []);
  1714. end;
  1715. {-----------------------------------------------------------------------------------------------------------------------
  1716. GetHashCode for string types
  1717. {----------------------------------------------------------------------------------------------------------------------}
  1718. class procedure TExtendedHashFactory.ShortString1(const AValue: ShortString1; AHashList: PUInt32);
  1719. begin
  1720. EXTENDED_HASH_FACTORY.GetHashList(@AValue[1], Length(AValue), AHashList, []);
  1721. end;
  1722. class procedure TExtendedHashFactory.ShortString2(const AValue: ShortString2; AHashList: PUInt32);
  1723. begin
  1724. EXTENDED_HASH_FACTORY.GetHashList(@AValue[1], Length(AValue), AHashList, []);
  1725. end;
  1726. class procedure TExtendedHashFactory.ShortString3(const AValue: ShortString3; AHashList: PUInt32);
  1727. begin
  1728. EXTENDED_HASH_FACTORY.GetHashList(@AValue[1], Length(AValue), AHashList, []);
  1729. end;
  1730. class procedure TExtendedHashFactory.ShortString(const AValue: ShortString; AHashList: PUInt32);
  1731. begin
  1732. EXTENDED_HASH_FACTORY.GetHashList(@AValue[1], Length(AValue), AHashList, []);
  1733. end;
  1734. class procedure TExtendedHashFactory.AnsiString(const AValue: AnsiString; AHashList: PUInt32);
  1735. begin
  1736. EXTENDED_HASH_FACTORY.GetHashList(@AValue[1], Length(AValue) * SizeOf(System.AnsiChar), AHashList, []);
  1737. end;
  1738. class procedure TExtendedHashFactory.WideString(const AValue: WideString; AHashList: PUInt32);
  1739. begin
  1740. EXTENDED_HASH_FACTORY.GetHashList(@AValue[1], Length(AValue) * SizeOf(System.WideChar), AHashList, []);
  1741. end;
  1742. class procedure TExtendedHashFactory.UnicodeString(const AValue: UnicodeString; AHashList: PUInt32);
  1743. begin
  1744. EXTENDED_HASH_FACTORY.GetHashList(@AValue[1], Length(AValue) * SizeOf(System.UnicodeChar), AHashList, []);
  1745. end;
  1746. {-----------------------------------------------------------------------------------------------------------------------
  1747. GetHashCode for Delegates
  1748. {----------------------------------------------------------------------------------------------------------------------}
  1749. class procedure TExtendedHashFactory.Method(const AValue: TMethod; AHashList: PUInt32);
  1750. begin
  1751. EXTENDED_HASH_FACTORY.GetHashList(@AValue, SizeOf(System.TMethod), AHashList, []);
  1752. end;
  1753. {-----------------------------------------------------------------------------------------------------------------------
  1754. GetHashCode for Variant
  1755. {----------------------------------------------------------------------------------------------------------------------}
  1756. class procedure TExtendedHashFactory.Variant(const AValue: PVariant; AHashList: PUInt32);
  1757. begin
  1758. try
  1759. EXTENDED_HASH_FACTORY.UnicodeString(AValue^, AHashList);
  1760. except
  1761. EXTENDED_HASH_FACTORY.GetHashList(AValue, SizeOf(System.Variant), AHashList, []);
  1762. end;
  1763. end;
  1764. {-----------------------------------------------------------------------------------------------------------------------
  1765. GetHashCode for Pointer
  1766. {----------------------------------------------------------------------------------------------------------------------}
  1767. class procedure TExtendedHashFactory.Pointer(const AValue: Pointer; AHashList: PUInt32);
  1768. begin
  1769. EXTENDED_HASH_FACTORY.GetHashList(@AValue, SizeOf(System.Pointer), AHashList, []);
  1770. end;
  1771. { TComparerService }
  1772. class function TComparerService.CreateInterface(AVMT: Pointer; ASize: SizeInt): PSpoofInterfacedTypeSizeObject;
  1773. begin
  1774. Result := New(PSpoofInterfacedTypeSizeObject);
  1775. Result.VMT := AVMT;
  1776. Result.RefCount := 0;
  1777. Result.Size := ASize;
  1778. end;
  1779. class function TComparerService.SelectIntegerComparer(ATypeData: PTypeData; ASize: SizeInt): Pointer;
  1780. begin
  1781. case ATypeData.OrdType of
  1782. otSByte:
  1783. Exit(@Comparer_Int8_Instance);
  1784. otUByte:
  1785. Exit(@Comparer_UInt8_Instance);
  1786. otSWord:
  1787. Exit(@Comparer_Int16_Instance);
  1788. otUWord:
  1789. Exit(@Comparer_UInt16_Instance);
  1790. otSLong:
  1791. Exit(@Comparer_Int32_Instance);
  1792. otULong:
  1793. Exit(@Comparer_UInt32_Instance);
  1794. else
  1795. System.Error(reRangeError);
  1796. Exit(nil);
  1797. end;
  1798. end;
  1799. class function TComparerService.SelectInt64Comparer(ATypeData: PTypeData; ASize: SizeInt): Pointer;
  1800. begin
  1801. if ATypeData.MaxInt64Value > ATypeData.MinInt64Value then
  1802. Exit(@Comparer_Int64_Instance)
  1803. else
  1804. Exit(@Comparer_UInt64_Instance);
  1805. end;
  1806. class function TComparerService.SelectFloatComparer(ATypeData: PTypeData;
  1807. ASize: SizeInt): Pointer;
  1808. begin
  1809. case ATypeData.FloatType of
  1810. ftSingle:
  1811. Exit(@Comparer_Single_Instance);
  1812. ftDouble:
  1813. Exit(@Comparer_Double_Instance);
  1814. ftExtended:
  1815. Exit(@Comparer_Extended_Instance);
  1816. ftComp:
  1817. Exit(@Comparer_Comp_Instance);
  1818. ftCurr:
  1819. Exit(@Comparer_Currency_Instance);
  1820. else
  1821. System.Error(reRangeError);
  1822. Exit(nil);
  1823. end;
  1824. end;
  1825. class function TComparerService.SelectShortStringComparer(ATypeData: PTypeData;
  1826. ASize: SizeInt): Pointer;
  1827. begin
  1828. case ASize of
  1829. 2: Exit(@Comparer_ShortString1_Instance);
  1830. 3: Exit(@Comparer_ShortString2_Instance);
  1831. 4: Exit(@Comparer_ShortString3_Instance);
  1832. else
  1833. Exit(@Comparer_ShortString_Instance);
  1834. end;
  1835. end;
  1836. class function TComparerService.SelectBinaryComparer(ATypeData: PTypeData;
  1837. ASize: SizeInt): Pointer;
  1838. begin
  1839. Result := CreateInterface(@Comparer_Binary_VMT, ASize);
  1840. end;
  1841. class function TComparerService.SelectDynArrayComparer(ATypeData: PTypeData; ASize: SizeInt): Pointer;
  1842. begin
  1843. Result := CreateInterface(@Comparer_DynArray_VMT, ATypeData.elSize);
  1844. end;
  1845. class function TComparerService.TypeNeedsBinaryMethods<T>: Boolean;
  1846. begin
  1847. Result := (GetTypeKind(T) in TComparerService.UseBinaryMethods) or
  1848. ((GetTypeKind(T) = tkEnumeration) and not Assigned(TypeInfo(T)));
  1849. end;
  1850. class function TComparerService.LookupComparer(ATypeInfo: PTypeInfo; ASize: SizeInt): Pointer;
  1851. var
  1852. LInstance: PInstance;
  1853. begin
  1854. if ATypeInfo = nil then
  1855. Exit(SelectBinaryComparer(Nil, ASize))
  1856. else
  1857. begin
  1858. LInstance := @ComparerInstances[ATypeInfo.Kind];
  1859. if LInstance.Selector then
  1860. Result := TSelectFunc(LInstance.SelectorInstance)(GetTypeData(ATypeInfo), ASize)
  1861. else
  1862. Result := LInstance.Instance;
  1863. end;
  1864. end;
  1865. { TComparerService.TInstance }
  1866. class function TComparerService.TInstance.Create(ASelector: Boolean;
  1867. AInstance: Pointer): TComparerService.TInstance;
  1868. begin
  1869. Result.Selector := ASelector;
  1870. Result.Instance := AInstance;
  1871. end;
  1872. class function TComparerService.TInstance.CreateSelector(ASelectorInstance: CodePointer): TComparerService.TInstance;
  1873. begin
  1874. Result.Selector := True;
  1875. Result.SelectorInstance := ASelectorInstance;
  1876. end;
  1877. { TExtendedHashService }
  1878. class function TExtendedHashService.LookupEqualityComparer(ATypeInfo: PTypeInfo; ASize: SizeInt): Pointer;
  1879. begin
  1880. Result := LookupExtendedEqualityComparer(ATypeInfo, ASize);
  1881. end;
  1882. { THashService }
  1883. class function THashService<T>.SelectIntegerEqualityComparer(ATypeData: PTypeData; ASize: SizeInt): Pointer;
  1884. begin
  1885. case ATypeData.OrdType of
  1886. otSByte:
  1887. Exit(@FEqualityComparer_Int8_Instance);
  1888. otUByte:
  1889. Exit(@FEqualityComparer_UInt8_Instance);
  1890. otSWord:
  1891. Exit(@FEqualityComparer_Int16_Instance);
  1892. otUWord:
  1893. Exit(@FEqualityComparer_UInt16_Instance);
  1894. otSLong:
  1895. Exit(@FEqualityComparer_Int32_Instance);
  1896. otULong:
  1897. Exit(@FEqualityComparer_UInt32_Instance);
  1898. else
  1899. System.Error(reRangeError);
  1900. Exit(nil);
  1901. end;
  1902. end;
  1903. class function THashService<T>.SelectFloatEqualityComparer(ATypeData: PTypeData;
  1904. ASize: SizeInt): Pointer;
  1905. begin
  1906. case ATypeData.FloatType of
  1907. ftSingle:
  1908. Exit(@FEqualityComparer_Single_Instance);
  1909. ftDouble:
  1910. Exit(@FEqualityComparer_Double_Instance);
  1911. ftExtended:
  1912. Exit(@FEqualityComparer_Extended_Instance);
  1913. ftComp:
  1914. Exit(@FEqualityComparer_Comp_Instance);
  1915. ftCurr:
  1916. Exit(@FEqualityComparer_Currency_Instance);
  1917. else
  1918. System.Error(reRangeError);
  1919. Exit(nil);
  1920. end;
  1921. end;
  1922. class function THashService<T>.SelectShortStringEqualityComparer(
  1923. ATypeData: PTypeData; ASize: SizeInt): Pointer;
  1924. begin
  1925. case ASize of
  1926. 2: Exit(@FEqualityComparer_ShortString1_Instance);
  1927. 3: Exit(@FEqualityComparer_ShortString2_Instance);
  1928. 4: Exit(@FEqualityComparer_ShortString3_Instance);
  1929. else
  1930. Exit(@FEqualityComparer_ShortString_Instance);
  1931. end
  1932. end;
  1933. class function THashService<T>.SelectBinaryEqualityComparer(ATypeData: PTypeData;
  1934. ASize: SizeInt): Pointer;
  1935. begin
  1936. Result := CreateInterface(@FEqualityComparer_Binary_VMT, ASize);
  1937. end;
  1938. class function THashService<T>.SelectDynArrayEqualityComparer(
  1939. ATypeData: PTypeData; ASize: SizeInt): Pointer;
  1940. begin
  1941. Result := CreateInterface(@FEqualityComparer_DynArray_VMT, ATypeData.elSize);
  1942. end;
  1943. class function THashService<T>.LookupEqualityComparer(ATypeInfo: PTypeInfo;
  1944. ASize: SizeInt): Pointer;
  1945. var
  1946. LInstance: PInstance;
  1947. LSelectMethod: TSelectMethod;
  1948. begin
  1949. if ATypeInfo = nil then
  1950. Exit(SelectBinaryEqualityComparer(Nil, ASize))
  1951. else
  1952. begin
  1953. If not TablesInitialized then
  1954. InitTables;
  1955. LInstance := @FEqualityComparerInstances[ATypeInfo.Kind];
  1956. Result := LInstance.Instance;
  1957. if LInstance.Selector then
  1958. begin
  1959. TMethod(LSelectMethod).Code := LInstance.SelectorInstance;
  1960. TMethod(LSelectMethod).Data := Self;
  1961. Result := LSelectMethod(GetTypeData(ATypeInfo), ASize);
  1962. end;
  1963. end;
  1964. end;
  1965. class constructor THashService<T>.Create;
  1966. begin
  1967. if not TablesInitialized then
  1968. InitTables
  1969. end;
  1970. class Procedure THashService<T>.InitTables;
  1971. begin
  1972. if TablesInitialized then
  1973. exit;
  1974. TablesInitialized:=true;
  1975. FEqualityComparer_Int8_VMT := EqualityComparer_Int8_VMT ;
  1976. FEqualityComparer_Int16_VMT := EqualityComparer_Int16_VMT ;
  1977. FEqualityComparer_Int32_VMT := EqualityComparer_Int32_VMT ;
  1978. FEqualityComparer_Int64_VMT := EqualityComparer_Int64_VMT ;
  1979. FEqualityComparer_UInt8_VMT := EqualityComparer_UInt8_VMT ;
  1980. FEqualityComparer_UInt16_VMT := EqualityComparer_UInt16_VMT ;
  1981. FEqualityComparer_UInt32_VMT := EqualityComparer_UInt32_VMT ;
  1982. FEqualityComparer_UInt64_VMT := EqualityComparer_UInt64_VMT ;
  1983. FEqualityComparer_Single_VMT := EqualityComparer_Single_VMT ;
  1984. FEqualityComparer_Double_VMT := EqualityComparer_Double_VMT ;
  1985. FEqualityComparer_Extended_VMT := EqualityComparer_Extended_VMT ;
  1986. FEqualityComparer_Currency_VMT := EqualityComparer_Currency_VMT ;
  1987. FEqualityComparer_Comp_VMT := EqualityComparer_Comp_VMT ;
  1988. FEqualityComparer_Binary_VMT := EqualityComparer_Binary_VMT ;
  1989. FEqualityComparer_DynArray_VMT := EqualityComparer_DynArray_VMT ;
  1990. FEqualityComparer_Class_VMT := EqualityComparer_Class_VMT ;
  1991. FEqualityComparer_ShortString1_VMT := EqualityComparer_ShortString1_VMT ;
  1992. FEqualityComparer_ShortString2_VMT := EqualityComparer_ShortString2_VMT ;
  1993. FEqualityComparer_ShortString3_VMT := EqualityComparer_ShortString3_VMT ;
  1994. FEqualityComparer_ShortString_VMT := EqualityComparer_ShortString_VMT ;
  1995. FEqualityComparer_AnsiString_VMT := EqualityComparer_AnsiString_VMT ;
  1996. FEqualityComparer_WideString_VMT := EqualityComparer_WideString_VMT ;
  1997. FEqualityComparer_UnicodeString_VMT := EqualityComparer_UnicodeString_VMT;
  1998. FEqualityComparer_Method_VMT := EqualityComparer_Method_VMT ;
  1999. FEqualityComparer_Variant_VMT := EqualityComparer_Variant_VMT ;
  2000. FEqualityComparer_Pointer_VMT := EqualityComparer_Pointer_VMT ;
  2001. /////
  2002. FEqualityComparer_Int8_VMT.__ClassRef := THashFactoryClass(T.ClassType);
  2003. FEqualityComparer_Int16_VMT.__ClassRef := THashFactoryClass(T.ClassType);
  2004. FEqualityComparer_Int32_VMT.__ClassRef := THashFactoryClass(T.ClassType);
  2005. FEqualityComparer_Int64_VMT.__ClassRef := THashFactoryClass(T.ClassType);
  2006. FEqualityComparer_UInt8_VMT.__ClassRef := THashFactoryClass(T.ClassType);
  2007. FEqualityComparer_UInt16_VMT.__ClassRef := THashFactoryClass(T.ClassType);
  2008. FEqualityComparer_UInt32_VMT.__ClassRef := THashFactoryClass(T.ClassType);
  2009. FEqualityComparer_UInt64_VMT.__ClassRef := THashFactoryClass(T.ClassType);
  2010. FEqualityComparer_Single_VMT.__ClassRef := THashFactoryClass(T.ClassType);
  2011. FEqualityComparer_Double_VMT.__ClassRef := THashFactoryClass(T.ClassType);
  2012. FEqualityComparer_Extended_VMT.__ClassRef := THashFactoryClass(T.ClassType);
  2013. FEqualityComparer_Currency_VMT.__ClassRef := THashFactoryClass(T.ClassType);
  2014. FEqualityComparer_Comp_VMT.__ClassRef := THashFactoryClass(T.ClassType);
  2015. FEqualityComparer_Binary_VMT.__ClassRef := THashFactoryClass(T.ClassType);
  2016. FEqualityComparer_DynArray_VMT.__ClassRef := THashFactoryClass(T.ClassType);
  2017. FEqualityComparer_Class_VMT.__ClassRef := THashFactoryClass(T.ClassType);
  2018. FEqualityComparer_ShortString1_VMT.__ClassRef := THashFactoryClass(T.ClassType);
  2019. FEqualityComparer_ShortString2_VMT.__ClassRef := THashFactoryClass(T.ClassType);
  2020. FEqualityComparer_ShortString3_VMT.__ClassRef := THashFactoryClass(T.ClassType);
  2021. FEqualityComparer_ShortString_VMT.__ClassRef := THashFactoryClass(T.ClassType);
  2022. FEqualityComparer_AnsiString_VMT.__ClassRef := THashFactoryClass(T.ClassType);
  2023. FEqualityComparer_WideString_VMT.__ClassRef := THashFactoryClass(T.ClassType);
  2024. FEqualityComparer_UnicodeString_VMT.__ClassRef := THashFactoryClass(T.ClassType);
  2025. FEqualityComparer_Method_VMT.__ClassRef := THashFactoryClass(T.ClassType);
  2026. FEqualityComparer_Variant_VMT.__ClassRef := THashFactoryClass(T.ClassType);
  2027. FEqualityComparer_Pointer_VMT.__ClassRef := THashFactoryClass(T.ClassType);
  2028. ///////
  2029. FEqualityComparer_Int8_Instance := @FEqualityComparer_Int8_VMT ;
  2030. FEqualityComparer_Int16_Instance := @FEqualityComparer_Int16_VMT ;
  2031. FEqualityComparer_Int32_Instance := @FEqualityComparer_Int32_VMT ;
  2032. FEqualityComparer_Int64_Instance := @FEqualityComparer_Int64_VMT ;
  2033. FEqualityComparer_UInt8_Instance := @FEqualityComparer_UInt8_VMT ;
  2034. FEqualityComparer_UInt16_Instance := @FEqualityComparer_UInt16_VMT ;
  2035. FEqualityComparer_UInt32_Instance := @FEqualityComparer_UInt32_VMT ;
  2036. FEqualityComparer_UInt64_Instance := @FEqualityComparer_UInt64_VMT ;
  2037. FEqualityComparer_Single_Instance := @FEqualityComparer_Single_VMT ;
  2038. FEqualityComparer_Double_Instance := @FEqualityComparer_Double_VMT ;
  2039. FEqualityComparer_Extended_Instance := @FEqualityComparer_Extended_VMT ;
  2040. FEqualityComparer_Currency_Instance := @FEqualityComparer_Currency_VMT ;
  2041. FEqualityComparer_Comp_Instance := @FEqualityComparer_Comp_VMT ;
  2042. //FEqualityComparer_Binary_Instance := @FEqualityComparer_Binary_VMT ; // dynamic instance
  2043. //FEqualityComparer_DynArray_Instance := @FEqualityComparer_DynArray_VMT ; // dynamic instance
  2044. FEqualityComparer_ShortString1_Instance := @FEqualityComparer_ShortString1_VMT ;
  2045. FEqualityComparer_ShortString2_Instance := @FEqualityComparer_ShortString2_VMT ;
  2046. FEqualityComparer_ShortString3_Instance := @FEqualityComparer_ShortString3_VMT ;
  2047. FEqualityComparer_ShortString_Instance := @FEqualityComparer_ShortString_VMT ;
  2048. FEqualityComparer_AnsiString_Instance := @FEqualityComparer_AnsiString_VMT ;
  2049. FEqualityComparer_WideString_Instance := @FEqualityComparer_WideString_VMT ;
  2050. FEqualityComparer_UnicodeString_Instance := @FEqualityComparer_UnicodeString_VMT;
  2051. FEqualityComparer_Method_Instance := @FEqualityComparer_Method_VMT ;
  2052. FEqualityComparer_Variant_Instance := @FEqualityComparer_Variant_VMT ;
  2053. FEqualityComparer_Pointer_Instance := @FEqualityComparer_Pointer_VMT ;
  2054. //////
  2055. FEqualityComparerInstances[tkUnknown] := TInstance.CreateSelector(TMethod(TSelectMethod(THashService<T>.SelectBinaryEqualityComparer)).Code);
  2056. FEqualityComparerInstances[tkInteger] := TInstance.CreateSelector(TMethod(TSelectMethod(THashService<T>.SelectIntegerEqualityComparer)).Code);
  2057. FEqualityComparerInstances[tkChar] := TInstance.Create(False, @FEqualityComparer_UInt8_Instance);
  2058. FEqualityComparerInstances[tkEnumeration] := TInstance.CreateSelector(TMethod(TSelectMethod(THashService<T>.SelectIntegerEqualityComparer)).Code);
  2059. FEqualityComparerInstances[tkFloat] := TInstance.CreateSelector(TMethod(TSelectMethod(THashService<T>.SelectFloatEqualityComparer)).Code);
  2060. FEqualityComparerInstances[tkSet] := TInstance.CreateSelector(TMethod(TSelectMethod(THashService<T>.SelectBinaryEqualityComparer)).Code);
  2061. FEqualityComparerInstances[tkMethod] := TInstance.Create(False, @FEqualityComparer_Method_Instance);
  2062. FEqualityComparerInstances[tkSString] := TInstance.CreateSelector(TMethod(TSelectMethod(THashService<T>.SelectShortStringEqualityComparer)).Code);
  2063. FEqualityComparerInstances[tkLString] := TInstance.Create(False, @FEqualityComparer_AnsiString_Instance);
  2064. FEqualityComparerInstances[tkAString] := TInstance.Create(False, @FEqualityComparer_AnsiString_Instance);
  2065. FEqualityComparerInstances[tkWString] := TInstance.Create(False, @FEqualityComparer_WideString_Instance);
  2066. FEqualityComparerInstances[tkVariant] := TInstance.Create(False, @FEqualityComparer_Variant_Instance);
  2067. FEqualityComparerInstances[tkArray] := TInstance.CreateSelector(TMethod(TSelectMethod(THashService<T>.SelectBinaryEqualityComparer)).Code);
  2068. FEqualityComparerInstances[tkRecord] := TInstance.CreateSelector(TMethod(TSelectMethod(THashService<T>.SelectBinaryEqualityComparer)).Code);
  2069. FEqualityComparerInstances[tkInterface] := TInstance.Create(False, @FEqualityComparer_Pointer_Instance);
  2070. FEqualityComparerInstances[tkClass] := TInstance.Create(False, @FEqualityComparer_Pointer_Instance);
  2071. FEqualityComparerInstances[tkObject] := TInstance.CreateSelector(TMethod(TSelectMethod(THashService<T>.SelectBinaryEqualityComparer)).Code);
  2072. FEqualityComparerInstances[tkWChar] := TInstance.Create(False, @FEqualityComparer_UInt16_Instance);
  2073. FEqualityComparerInstances[tkBool] := TInstance.CreateSelector(TMethod(TSelectMethod(THashService<T>.SelectIntegerEqualityComparer)).Code);
  2074. FEqualityComparerInstances[tkInt64] := TInstance.Create(False, @FEqualityComparer_Int64_Instance);
  2075. FEqualityComparerInstances[tkQWord] := TInstance.Create(False, @FEqualityComparer_UInt64_Instance);
  2076. FEqualityComparerInstances[tkDynArray] := TInstance.CreateSelector(TMethod(TSelectMethod(THashService<T>.SelectDynArrayEqualityComparer)).Code);
  2077. FEqualityComparerInstances[tkInterfaceRaw] := TInstance.Create(False, @FEqualityComparer_Pointer_Instance);
  2078. FEqualityComparerInstances[tkProcVar] := TInstance.Create(False, @FEqualityComparer_Pointer_Instance);
  2079. FEqualityComparerInstances[tkUString] := TInstance.Create(False, @FEqualityComparer_UnicodeString_Instance);
  2080. FEqualityComparerInstances[tkUChar] := TInstance.Create(False, @FEqualityComparer_UInt16_Instance);
  2081. FEqualityComparerInstances[tkHelper] := TInstance.Create(False, @FEqualityComparer_Pointer_Instance);
  2082. FEqualityComparerInstances[tkFile] := TInstance.CreateSelector(TMethod(TSelectMethod(THashService<T>.SelectBinaryEqualityComparer)).Code);
  2083. FEqualityComparerInstances[tkClassRef] := TInstance.Create(False, @FEqualityComparer_Pointer_Instance);
  2084. FEqualityComparerInstances[tkPointer] := TInstance.Create(False, @FEqualityComparer_Pointer_Instance)
  2085. end;
  2086. { TExtendedHashService }
  2087. class function TExtendedHashService<T>.SelectIntegerEqualityComparer(ATypeData: PTypeData; ASize: SizeInt): Pointer;
  2088. begin
  2089. case ATypeData.OrdType of
  2090. otSByte:
  2091. Exit(@FExtendedEqualityComparer_Int8_Instance);
  2092. otUByte:
  2093. Exit(@FExtendedEqualityComparer_UInt8_Instance);
  2094. otSWord:
  2095. Exit(@FExtendedEqualityComparer_Int16_Instance);
  2096. otUWord:
  2097. Exit(@FExtendedEqualityComparer_UInt16_Instance);
  2098. otSLong:
  2099. Exit(@FExtendedEqualityComparer_Int32_Instance);
  2100. otULong:
  2101. Exit(@FExtendedEqualityComparer_UInt32_Instance);
  2102. else
  2103. System.Error(reRangeError);
  2104. Exit(nil);
  2105. end;
  2106. end;
  2107. class function TExtendedHashService<T>.SelectFloatEqualityComparer(ATypeData: PTypeData; ASize: SizeInt): Pointer;
  2108. begin
  2109. case ATypeData.FloatType of
  2110. ftSingle:
  2111. Exit(@FExtendedEqualityComparer_Single_Instance);
  2112. ftDouble:
  2113. Exit(@FExtendedEqualityComparer_Double_Instance);
  2114. ftExtended:
  2115. Exit(@FExtendedEqualityComparer_Extended_Instance);
  2116. ftComp:
  2117. Exit(@FExtendedEqualityComparer_Comp_Instance);
  2118. ftCurr:
  2119. Exit(@FExtendedEqualityComparer_Currency_Instance);
  2120. else
  2121. System.Error(reRangeError);
  2122. Exit(nil);
  2123. end;
  2124. end;
  2125. class function TExtendedHashService<T>.SelectShortStringEqualityComparer(ATypeData: PTypeData;
  2126. ASize: SizeInt): Pointer;
  2127. begin
  2128. case ASize of
  2129. 2: Exit(@FExtendedEqualityComparer_ShortString1_Instance);
  2130. 3: Exit(@FExtendedEqualityComparer_ShortString2_Instance);
  2131. 4: Exit(@FExtendedEqualityComparer_ShortString3_Instance);
  2132. else
  2133. Exit(@FExtendedEqualityComparer_ShortString_Instance);
  2134. end
  2135. end;
  2136. class function TExtendedHashService<T>.SelectBinaryEqualityComparer(ATypeData: PTypeData;
  2137. ASize: SizeInt): Pointer;
  2138. begin
  2139. Result := CreateInterface(@FExtendedEqualityComparer_Binary_VMT, ASize);
  2140. end;
  2141. class function TExtendedHashService<T>.SelectDynArrayEqualityComparer(
  2142. ATypeData: PTypeData; ASize: SizeInt): Pointer;
  2143. begin
  2144. Result := CreateInterface(@FExtendedEqualityComparer_DynArray_VMT, ATypeData.elSize);
  2145. end;
  2146. class function TExtendedHashService<T>.LookupExtendedEqualityComparer(
  2147. ATypeInfo: PTypeInfo; ASize: SizeInt): Pointer;
  2148. var
  2149. LInstance: PInstance;
  2150. LSelectMethod: TSelectMethod;
  2151. begin
  2152. if ATypeInfo = nil then
  2153. Exit(SelectBinaryEqualityComparer(Nil, ASize))
  2154. else
  2155. begin
  2156. if not TablesInitialized then
  2157. InitTables;
  2158. LInstance := @FExtendedEqualityComparerInstances[ATypeInfo.Kind];
  2159. Result := LInstance.Instance;
  2160. if LInstance.Selector then
  2161. begin
  2162. TMethod(LSelectMethod).Code := LInstance.SelectorInstance;
  2163. TMethod(LSelectMethod).Data := Self;
  2164. Result := LSelectMethod(GetTypeData(ATypeInfo), ASize);
  2165. end;
  2166. end;
  2167. end;
  2168. class constructor TExtendedHashService<T>.Create;
  2169. begin
  2170. // The InitTables can have been called before from the class constructors of other classes.
  2171. if not TablesInitialized then
  2172. InitTables
  2173. end;
  2174. class procedure TExtendedHashService<T>.InitTables;
  2175. begin
  2176. if TablesInitialized then exit;
  2177. TablesInitialized:=True;
  2178. FExtendedEqualityComparer_Int8_VMT := ExtendedEqualityComparer_Int8_VMT ;
  2179. FExtendedEqualityComparer_Int16_VMT := ExtendedEqualityComparer_Int16_VMT ;
  2180. FExtendedEqualityComparer_Int32_VMT := ExtendedEqualityComparer_Int32_VMT ;
  2181. FExtendedEqualityComparer_Int64_VMT := ExtendedEqualityComparer_Int64_VMT ;
  2182. FExtendedEqualityComparer_UInt8_VMT := ExtendedEqualityComparer_UInt8_VMT ;
  2183. FExtendedEqualityComparer_UInt16_VMT := ExtendedEqualityComparer_UInt16_VMT ;
  2184. FExtendedEqualityComparer_UInt32_VMT := ExtendedEqualityComparer_UInt32_VMT ;
  2185. FExtendedEqualityComparer_UInt64_VMT := ExtendedEqualityComparer_UInt64_VMT ;
  2186. FExtendedEqualityComparer_Single_VMT := ExtendedEqualityComparer_Single_VMT ;
  2187. FExtendedEqualityComparer_Double_VMT := ExtendedEqualityComparer_Double_VMT ;
  2188. FExtendedEqualityComparer_Extended_VMT := ExtendedEqualityComparer_Extended_VMT ;
  2189. FExtendedEqualityComparer_Currency_VMT := ExtendedEqualityComparer_Currency_VMT ;
  2190. FExtendedEqualityComparer_Comp_VMT := ExtendedEqualityComparer_Comp_VMT ;
  2191. FExtendedEqualityComparer_Binary_VMT := ExtendedEqualityComparer_Binary_VMT ;
  2192. FExtendedEqualityComparer_DynArray_VMT := ExtendedEqualityComparer_DynArray_VMT ;
  2193. FExtendedEqualityComparer_Class_VMT := ExtendedEqualityComparer_Class_VMT ;
  2194. FExtendedEqualityComparer_ShortString1_VMT := ExtendedEqualityComparer_ShortString1_VMT ;
  2195. FExtendedEqualityComparer_ShortString2_VMT := ExtendedEqualityComparer_ShortString2_VMT ;
  2196. FExtendedEqualityComparer_ShortString3_VMT := ExtendedEqualityComparer_ShortString3_VMT ;
  2197. FExtendedEqualityComparer_ShortString_VMT := ExtendedEqualityComparer_ShortString_VMT ;
  2198. FExtendedEqualityComparer_AnsiString_VMT := ExtendedEqualityComparer_AnsiString_VMT ;
  2199. FExtendedEqualityComparer_WideString_VMT := ExtendedEqualityComparer_WideString_VMT ;
  2200. FExtendedEqualityComparer_UnicodeString_VMT := ExtendedEqualityComparer_UnicodeString_VMT;
  2201. FExtendedEqualityComparer_Method_VMT := ExtendedEqualityComparer_Method_VMT ;
  2202. FExtendedEqualityComparer_Variant_VMT := ExtendedEqualityComparer_Variant_VMT ;
  2203. FExtendedEqualityComparer_Pointer_VMT := ExtendedEqualityComparer_Pointer_VMT ;
  2204. /////
  2205. FExtendedEqualityComparer_Int8_VMT.__ClassRef := TExtendedHashFactoryClass(T.ClassType);
  2206. FExtendedEqualityComparer_Int16_VMT.__ClassRef := TExtendedHashFactoryClass(T.ClassType);
  2207. FExtendedEqualityComparer_Int32_VMT.__ClassRef := TExtendedHashFactoryClass(T.ClassType);
  2208. FExtendedEqualityComparer_Int64_VMT.__ClassRef := TExtendedHashFactoryClass(T.ClassType);
  2209. FExtendedEqualityComparer_UInt8_VMT.__ClassRef := TExtendedHashFactoryClass(T.ClassType);
  2210. FExtendedEqualityComparer_UInt16_VMT.__ClassRef := TExtendedHashFactoryClass(T.ClassType);
  2211. FExtendedEqualityComparer_UInt32_VMT.__ClassRef := TExtendedHashFactoryClass(T.ClassType);
  2212. FExtendedEqualityComparer_UInt64_VMT.__ClassRef := TExtendedHashFactoryClass(T.ClassType);
  2213. FExtendedEqualityComparer_Single_VMT.__ClassRef := TExtendedHashFactoryClass(T.ClassType);
  2214. FExtendedEqualityComparer_Double_VMT.__ClassRef := TExtendedHashFactoryClass(T.ClassType);
  2215. FExtendedEqualityComparer_Extended_VMT.__ClassRef := TExtendedHashFactoryClass(T.ClassType);
  2216. FExtendedEqualityComparer_Currency_VMT.__ClassRef := TExtendedHashFactoryClass(T.ClassType);
  2217. FExtendedEqualityComparer_Comp_VMT.__ClassRef := TExtendedHashFactoryClass(T.ClassType);
  2218. FExtendedEqualityComparer_Binary_VMT.__ClassRef := TExtendedHashFactoryClass(T.ClassType);
  2219. FExtendedEqualityComparer_DynArray_VMT.__ClassRef := TExtendedHashFactoryClass(T.ClassType);
  2220. FExtendedEqualityComparer_Class_VMT.__ClassRef := TExtendedHashFactoryClass(T.ClassType);
  2221. FExtendedEqualityComparer_ShortString1_VMT.__ClassRef := TExtendedHashFactoryClass(T.ClassType);
  2222. FExtendedEqualityComparer_ShortString2_VMT.__ClassRef := TExtendedHashFactoryClass(T.ClassType);
  2223. FExtendedEqualityComparer_ShortString3_VMT.__ClassRef := TExtendedHashFactoryClass(T.ClassType);
  2224. FExtendedEqualityComparer_ShortString_VMT.__ClassRef := TExtendedHashFactoryClass(T.ClassType);
  2225. FExtendedEqualityComparer_AnsiString_VMT.__ClassRef := TExtendedHashFactoryClass(T.ClassType);
  2226. FExtendedEqualityComparer_WideString_VMT.__ClassRef := TExtendedHashFactoryClass(T.ClassType);
  2227. FExtendedEqualityComparer_UnicodeString_VMT.__ClassRef := TExtendedHashFactoryClass(T.ClassType);
  2228. FExtendedEqualityComparer_Method_VMT.__ClassRef := TExtendedHashFactoryClass(T.ClassType);
  2229. FExtendedEqualityComparer_Variant_VMT.__ClassRef := TExtendedHashFactoryClass(T.ClassType);
  2230. FExtendedEqualityComparer_Pointer_VMT.__ClassRef := TExtendedHashFactoryClass(T.ClassType);
  2231. ///////
  2232. FExtendedEqualityComparer_Int8_Instance := @FExtendedEqualityComparer_Int8_VMT ;
  2233. FExtendedEqualityComparer_Int16_Instance := @FExtendedEqualityComparer_Int16_VMT ;
  2234. FExtendedEqualityComparer_Int32_Instance := @FExtendedEqualityComparer_Int32_VMT ;
  2235. FExtendedEqualityComparer_Int64_Instance := @FExtendedEqualityComparer_Int64_VMT ;
  2236. FExtendedEqualityComparer_UInt8_Instance := @FExtendedEqualityComparer_UInt8_VMT ;
  2237. FExtendedEqualityComparer_UInt16_Instance := @FExtendedEqualityComparer_UInt16_VMT ;
  2238. FExtendedEqualityComparer_UInt32_Instance := @FExtendedEqualityComparer_UInt32_VMT ;
  2239. FExtendedEqualityComparer_UInt64_Instance := @FExtendedEqualityComparer_UInt64_VMT ;
  2240. FExtendedEqualityComparer_Single_Instance := @FExtendedEqualityComparer_Single_VMT ;
  2241. FExtendedEqualityComparer_Double_Instance := @FExtendedEqualityComparer_Double_VMT ;
  2242. FExtendedEqualityComparer_Extended_Instance := @FExtendedEqualityComparer_Extended_VMT ;
  2243. FExtendedEqualityComparer_Currency_Instance := @FExtendedEqualityComparer_Currency_VMT ;
  2244. FExtendedEqualityComparer_Comp_Instance := @FExtendedEqualityComparer_Comp_VMT ;
  2245. //FExtendedEqualityComparer_Binary_Instance := @FExtendedEqualityComparer_Binary_VMT ; // dynamic instance
  2246. //FExtendedEqualityComparer_DynArray_Instance := @FExtendedEqualityComparer_DynArray_VMT ; // dynamic instance
  2247. FExtendedEqualityComparer_ShortString1_Instance := @FExtendedEqualityComparer_ShortString1_VMT ;
  2248. FExtendedEqualityComparer_ShortString2_Instance := @FExtendedEqualityComparer_ShortString2_VMT ;
  2249. FExtendedEqualityComparer_ShortString3_Instance := @FExtendedEqualityComparer_ShortString3_VMT ;
  2250. FExtendedEqualityComparer_ShortString_Instance := @FExtendedEqualityComparer_ShortString_VMT ;
  2251. FExtendedEqualityComparer_AnsiString_Instance := @FExtendedEqualityComparer_AnsiString_VMT ;
  2252. FExtendedEqualityComparer_WideString_Instance := @FExtendedEqualityComparer_WideString_VMT ;
  2253. FExtendedEqualityComparer_UnicodeString_Instance := @FExtendedEqualityComparer_UnicodeString_VMT;
  2254. FExtendedEqualityComparer_Method_Instance := @FExtendedEqualityComparer_Method_VMT ;
  2255. FExtendedEqualityComparer_Variant_Instance := @FExtendedEqualityComparer_Variant_VMT ;
  2256. FExtendedEqualityComparer_Pointer_Instance := @FExtendedEqualityComparer_Pointer_VMT ;
  2257. //////
  2258. FExtendedEqualityComparerInstances[tkUnknown] := TInstance.CreateSelector(TMethod(TSelectMethod(TExtendedHashService<T>.SelectBinaryEqualityComparer)).Code);
  2259. FExtendedEqualityComparerInstances[tkInteger] := TInstance.CreateSelector(TMethod(TSelectMethod(TExtendedHashService<T>.SelectIntegerEqualityComparer)).Code);
  2260. FExtendedEqualityComparerInstances[tkChar] := TInstance.Create(False, @FExtendedEqualityComparer_UInt8_Instance);
  2261. FExtendedEqualityComparerInstances[tkEnumeration] := TInstance.CreateSelector(TMethod(TSelectMethod(TExtendedHashService<T>.SelectIntegerEqualityComparer)).Code);
  2262. FExtendedEqualityComparerInstances[tkFloat] := TInstance.CreateSelector(TMethod(TSelectMethod(TExtendedHashService<T>.SelectFloatEqualityComparer)).Code);
  2263. FExtendedEqualityComparerInstances[tkSet] := TInstance.CreateSelector(TMethod(TSelectMethod(TExtendedHashService<T>.SelectBinaryEqualityComparer)).Code);
  2264. FExtendedEqualityComparerInstances[tkMethod] := TInstance.Create(False, @FExtendedEqualityComparer_Method_Instance);
  2265. FExtendedEqualityComparerInstances[tkSString] := TInstance.CreateSelector(TMethod(TSelectMethod(TExtendedHashService<T>.SelectShortStringEqualityComparer)).Code);
  2266. FExtendedEqualityComparerInstances[tkLString] := TInstance.Create(False, @FExtendedEqualityComparer_AnsiString_Instance);
  2267. FExtendedEqualityComparerInstances[tkAString] := TInstance.Create(False, @FExtendedEqualityComparer_AnsiString_Instance);
  2268. FExtendedEqualityComparerInstances[tkWString] := TInstance.Create(False, @FExtendedEqualityComparer_WideString_Instance);
  2269. FExtendedEqualityComparerInstances[tkVariant] := TInstance.Create(False, @FExtendedEqualityComparer_Variant_Instance);
  2270. FExtendedEqualityComparerInstances[tkArray] := TInstance.CreateSelector(TMethod(TSelectMethod(TExtendedHashService<T>.SelectBinaryEqualityComparer)).Code);
  2271. FExtendedEqualityComparerInstances[tkRecord] := TInstance.CreateSelector(TMethod(TSelectMethod(TExtendedHashService<T>.SelectBinaryEqualityComparer)).Code);
  2272. FExtendedEqualityComparerInstances[tkInterface] := TInstance.Create(False, @FExtendedEqualityComparer_Pointer_Instance);
  2273. FExtendedEqualityComparerInstances[tkClass] := TInstance.Create(False, @FExtendedEqualityComparer_Pointer_Instance);
  2274. FExtendedEqualityComparerInstances[tkObject] := TInstance.CreateSelector(TMethod(TSelectMethod(TExtendedHashService<T>.SelectBinaryEqualityComparer)).Code);
  2275. FExtendedEqualityComparerInstances[tkWChar] := TInstance.Create(False, @FExtendedEqualityComparer_UInt16_Instance);
  2276. FExtendedEqualityComparerInstances[tkBool] := TInstance.CreateSelector(TMethod(TSelectMethod(TExtendedHashService<T>.SelectIntegerEqualityComparer)).Code);
  2277. FExtendedEqualityComparerInstances[tkInt64] := TInstance.Create(False, @FExtendedEqualityComparer_Int64_Instance);
  2278. FExtendedEqualityComparerInstances[tkQWord] := TInstance.Create(False, @FExtendedEqualityComparer_UInt64_Instance);
  2279. FExtendedEqualityComparerInstances[tkDynArray] := TInstance.CreateSelector(TMethod(TSelectMethod(TExtendedHashService<T>.SelectDynArrayEqualityComparer)).Code);
  2280. FExtendedEqualityComparerInstances[tkInterfaceRaw] := TInstance.Create(False, @FExtendedEqualityComparer_Pointer_Instance);
  2281. FExtendedEqualityComparerInstances[tkProcVar] := TInstance.Create(False, @FExtendedEqualityComparer_Pointer_Instance);
  2282. FExtendedEqualityComparerInstances[tkUString] := TInstance.Create(False, @FExtendedEqualityComparer_UnicodeString_Instance);
  2283. FExtendedEqualityComparerInstances[tkUChar] := TInstance.Create(False, @FExtendedEqualityComparer_UInt16_Instance);
  2284. FExtendedEqualityComparerInstances[tkHelper] := TInstance.Create(False, @FExtendedEqualityComparer_Pointer_Instance);
  2285. FExtendedEqualityComparerInstances[tkFile] := TInstance.CreateSelector(TMethod(TSelectMethod(TExtendedHashService<T>.SelectBinaryEqualityComparer)).Code);
  2286. FExtendedEqualityComparerInstances[tkClassRef] := TInstance.Create(False, @FExtendedEqualityComparer_Pointer_Instance);
  2287. FExtendedEqualityComparerInstances[tkPointer] := TInstance.Create(False, @FExtendedEqualityComparer_Pointer_Instance);
  2288. end;
  2289. { TEqualityComparer<T> }
  2290. class function TEqualityComparer<T>.Default: IEqualityComparer<T>;
  2291. begin
  2292. if TComparerService.TypeNeedsBinaryMethods<T> then
  2293. Result := TBinaryEqualityComparer<T>.Create(Nil)
  2294. else
  2295. Result := _LookupVtableInfo(giEqualityComparer, TypeInfo(T), SizeOf(T));
  2296. end;
  2297. class function TEqualityComparer<T>.Default(AHashFactoryClass: THashFactoryClass): IEqualityComparer<T>;
  2298. begin
  2299. if TComparerService.TypeNeedsBinaryMethods<T> then
  2300. Result := TBinaryEqualityComparer<T>.Create(AHashFactoryClass)
  2301. else if AHashFactoryClass.InheritsFrom(TExtendedHashFactory) then
  2302. Result := _LookupVtableInfoEx(giExtendedEqualityComparer, TypeInfo(T), SizeOf(T), AHashFactoryClass)
  2303. else if AHashFactoryClass.InheritsFrom(THashFactory) then
  2304. Result := _LookupVtableInfoEx(giEqualityComparer, TypeInfo(T), SizeOf(T), AHashFactoryClass);
  2305. end;
  2306. class function TEqualityComparer<T>.Construct(const AEqualityComparison: TOnEqualityComparison<T>;
  2307. const AHasher: TOnHasher<T>): IEqualityComparer<T>;
  2308. begin
  2309. Result := TDelegatedEqualityComparerEvents<T>.Create(AEqualityComparison, AHasher);
  2310. end;
  2311. class function TEqualityComparer<T>.Construct(const AEqualityComparison: TEqualityComparisonFunc<T>;
  2312. const AHasher: THasherFunc<T>): IEqualityComparer<T>;
  2313. begin
  2314. Result := TDelegatedEqualityComparerFunc<T>.Create(AEqualityComparison, AHasher);
  2315. end;
  2316. { TDelegatedEqualityComparerEvents<T> }
  2317. function TDelegatedEqualityComparerEvents<T>.Equals(const ALeft, ARight: T): Boolean;
  2318. begin
  2319. Result := FEqualityComparison(ALeft, ARight);
  2320. end;
  2321. function TDelegatedEqualityComparerEvents<T>.GetHashCode(const AValue: T): UInt32;
  2322. begin
  2323. Result := FHasher(AValue);
  2324. end;
  2325. constructor TDelegatedEqualityComparerEvents<T>.Create(const AEqualityComparison: TOnEqualityComparison<T>;
  2326. const AHasher: TOnHasher<T>);
  2327. begin
  2328. FEqualityComparison := AEqualityComparison;
  2329. FHasher := AHasher;
  2330. end;
  2331. { TDelegatedEqualityComparerFunc<T> }
  2332. function TDelegatedEqualityComparerFunc<T>.Equals(const ALeft, ARight: T): Boolean;
  2333. begin
  2334. Result := FEqualityComparison(ALeft, ARight);
  2335. end;
  2336. function TDelegatedEqualityComparerFunc<T>.GetHashCode(const AValue: T): UInt32;
  2337. begin
  2338. Result := FHasher(AValue);
  2339. end;
  2340. constructor TDelegatedEqualityComparerFunc<T>.Create(const AEqualityComparison: TEqualityComparisonFunc<T>;
  2341. const AHasher: THasherFunc<T>);
  2342. begin
  2343. FEqualityComparison := AEqualityComparison;
  2344. FHasher := AHasher;
  2345. end;
  2346. { TDelegatedExtendedEqualityComparerEvents<T> }
  2347. function TDelegatedExtendedEqualityComparerEvents<T>.GetHashCodeMethod(const AValue: T): UInt32;
  2348. var
  2349. LHashList: array[0..1] of Int32;
  2350. LHashListParams: array[0..3] of Int16 absolute LHashList;
  2351. begin
  2352. LHashListParams[0] := -1;
  2353. FExtendedHasher(AValue, @LHashList[0]);
  2354. Result := LHashList[1];
  2355. end;
  2356. function TDelegatedExtendedEqualityComparerEvents<T>.Equals(const ALeft, ARight: T): Boolean;
  2357. begin
  2358. Result := FEqualityComparison(ALeft, ARight);
  2359. end;
  2360. function TDelegatedExtendedEqualityComparerEvents<T>.GetHashCode(const AValue: T): UInt32;
  2361. begin
  2362. Result := FHasher(AValue);
  2363. end;
  2364. procedure TDelegatedExtendedEqualityComparerEvents<T>.GetHashList(const AValue: T; AHashList: PUInt32);
  2365. begin
  2366. FExtendedHasher(AValue, AHashList);
  2367. end;
  2368. constructor TDelegatedExtendedEqualityComparerEvents<T>.Create(const AEqualityComparison: TOnEqualityComparison<T>;
  2369. const AHasher: TOnHasher<T>; const AExtendedHasher: TOnExtendedHasher<T>);
  2370. begin
  2371. FEqualityComparison := AEqualityComparison;
  2372. FHasher := AHasher;
  2373. FExtendedHasher := AExtendedHasher;
  2374. end;
  2375. constructor TDelegatedExtendedEqualityComparerEvents<T>.Create(const AEqualityComparison: TOnEqualityComparison<T>;
  2376. const AExtendedHasher: TOnExtendedHasher<T>);
  2377. begin
  2378. Create(AEqualityComparison, GetHashCodeMethod, AExtendedHasher);
  2379. end;
  2380. { TDelegatedExtendedEqualityComparerFunc<T> }
  2381. function TDelegatedExtendedEqualityComparerFunc<T>.Equals(const ALeft, ARight: T): Boolean;
  2382. begin
  2383. Result := FEqualityComparison(ALeft, ARight);
  2384. end;
  2385. function TDelegatedExtendedEqualityComparerFunc<T>.GetHashCode(const AValue: T): UInt32;
  2386. var
  2387. LHashList: array[0..1] of Int32;
  2388. LHashListParams: array[0..3] of Int16 absolute LHashList;
  2389. begin
  2390. if not Assigned(FHasher) then
  2391. begin
  2392. LHashListParams[0] := -1;
  2393. FExtendedHasher(AValue, @LHashList[0]);
  2394. Result := LHashList[1];
  2395. end
  2396. else
  2397. Result := FHasher(AValue);
  2398. end;
  2399. procedure TDelegatedExtendedEqualityComparerFunc<T>.GetHashList(const AValue: T; AHashList: PUInt32);
  2400. begin
  2401. FExtendedHasher(AValue, AHashList);
  2402. end;
  2403. constructor TDelegatedExtendedEqualityComparerFunc<T>.Create(const AEqualityComparison: TEqualityComparisonFunc<T>;
  2404. const AHasher: THasherFunc<T>; const AExtendedHasher: TExtendedHasherFunc<T>);
  2405. begin
  2406. FEqualityComparison := AEqualityComparison;
  2407. FHasher := AHasher;
  2408. FExtendedHasher := AExtendedHasher;
  2409. end;
  2410. constructor TDelegatedExtendedEqualityComparerFunc<T>.Create(const AEqualityComparison: TEqualityComparisonFunc<T>;
  2411. const AExtendedHasher: TExtendedHasherFunc<T>);
  2412. begin
  2413. Create(AEqualityComparison, nil, AExtendedHasher);
  2414. end;
  2415. { TExtendedEqualityComparer<T> }
  2416. class function TExtendedEqualityComparer<T>.Default: IExtendedEqualityComparer<T>;
  2417. begin
  2418. if TComparerService.TypeNeedsBinaryMethods<T> then
  2419. Result := TBinaryExtendedEqualityComparer<T>.Create(Nil)
  2420. else
  2421. Result := _LookupVtableInfo(giExtendedEqualityComparer, TypeInfo(T), SizeOf(T));
  2422. end;
  2423. class function TExtendedEqualityComparer<T>.Default(
  2424. AExtenedHashFactoryClass: TExtendedHashFactoryClass
  2425. ): IExtendedEqualityComparer<T>;
  2426. begin
  2427. if TComparerService.TypeNeedsBinaryMethods<T> then
  2428. Result := TBinaryExtendedEqualityComparer<T>.Create(Nil)
  2429. else
  2430. Result := _LookupVtableInfoEx(giExtendedEqualityComparer, TypeInfo(T), SizeOf(T), AExtenedHashFactoryClass);
  2431. end;
  2432. class function TExtendedEqualityComparer<T>.Construct(
  2433. const AEqualityComparison: TOnEqualityComparison<T>; const AHasher: TOnHasher<T>;
  2434. const AExtendedHasher: TOnExtendedHasher<T>): IExtendedEqualityComparer<T>;
  2435. begin
  2436. Result := TDelegatedExtendedEqualityComparerEvents<T>.Create(AEqualityComparison, AHasher, AExtendedHasher);
  2437. end;
  2438. class function TExtendedEqualityComparer<T>.Construct(
  2439. const AEqualityComparison: TEqualityComparisonFunc<T>; const AHasher: THasherFunc<T>;
  2440. const AExtendedHasher: TExtendedHasherFunc<T>): IExtendedEqualityComparer<T>;
  2441. begin
  2442. Result := TDelegatedExtendedEqualityComparerFunc<T>.Create(AEqualityComparison, AHasher, AExtendedHasher);
  2443. end;
  2444. class function TExtendedEqualityComparer<T>.Construct(
  2445. const AEqualityComparison: TOnEqualityComparison<T>;
  2446. const AExtendedHasher: TOnExtendedHasher<T>): IExtendedEqualityComparer<T>;
  2447. begin
  2448. Result := TDelegatedExtendedEqualityComparerEvents<T>.Create(AEqualityComparison, AExtendedHasher);
  2449. end;
  2450. class function TExtendedEqualityComparer<T>.Construct(
  2451. const AEqualityComparison: TEqualityComparisonFunc<T>;
  2452. const AExtendedHasher: TExtendedHasherFunc<T>): IExtendedEqualityComparer<T>;
  2453. begin
  2454. Result := TDelegatedExtendedEqualityComparerFunc<T>.Create(AEqualityComparison, AExtendedHasher);
  2455. end;
  2456. { TBinaryComparer<T> }
  2457. function TBinaryComparer<T>.Compare(const ALeft, ARight: T): Integer;
  2458. begin
  2459. Result := BinaryCompare(@ALeft, @ARight, SizeOf(T));
  2460. end;
  2461. { TBinaryEqualityComparer<T> }
  2462. constructor TBinaryEqualityComparer<T>.Create(AHashFactoryClass: THashFactoryClass);
  2463. begin
  2464. if not Assigned(AHashFactoryClass) then
  2465. FHashFactory := TDefaultHashFactory
  2466. else
  2467. FHashFactory := AHashFactoryClass;
  2468. end;
  2469. function TBinaryEqualityComparer<T>.Equals(const ALeft, ARight: T): Boolean;
  2470. begin
  2471. Result := CompareMem(@ALeft, @ARight, SizeOf(T));
  2472. end;
  2473. function TBinaryEqualityComparer<T>.GetHashCode(const AValue: T): UInt32;
  2474. begin
  2475. Result := FHashFactory.GetHashCode(@AValue, SizeOf(T), 0);
  2476. end;
  2477. { TBinaryExtendedEqualityComparer<T> }
  2478. constructor TBinaryExtendedEqualityComparer<T>.Create(AHashFactoryClass: TExtendedHashFactoryClass);
  2479. begin
  2480. if not Assigned(AHashFactoryClass) then
  2481. FExtendedHashFactory := TDelphiDoubleHashFactory
  2482. else
  2483. FExtendedHashFactory := AHashFactoryClass;
  2484. inherited Create(FExtendedHashFactory);
  2485. end;
  2486. procedure TBinaryExtendedEqualityComparer<T>.GetHashList(const AValue: T; AHashList: PUInt32);
  2487. begin
  2488. FExtendedHashFactory.GetHashList(@AValue, SizeOf(T), AHashList, []);
  2489. end;
  2490. { TDelphiHashFactory }
  2491. class function TDelphiHashFactory.GetHashService: THashServiceClass;
  2492. begin
  2493. Result := THashService<TDelphiHashFactory>;
  2494. end;
  2495. class function TDelphiHashFactory.GetHashCode(AKey: Pointer; ASize: SizeInt; AInitVal: UInt32): UInt32;
  2496. begin
  2497. Result := DelphiHashLittle(AKey, ASize, AInitVal);
  2498. end;
  2499. { TGenericsHashFactory }
  2500. class function TGenericsHashFactory.GetHashService: THashServiceClass;
  2501. begin
  2502. Result := THashService<TGenericsHashFactory>;
  2503. end;
  2504. class function TGenericsHashFactory.GetHashCode(AKey: Pointer; ASize: SizeInt; AInitVal: UInt32): UInt32;
  2505. begin
  2506. Result := mORMotHasher(AInitVal, AKey, ASize);
  2507. end;
  2508. { TxxHash32HashFactory }
  2509. class function TxxHash32HashFactory.GetHashService: THashServiceClass;
  2510. begin
  2511. Result := THashService<TxxHash32HashFactory>;
  2512. end;
  2513. class function TxxHash32HashFactory.GetHashCode(AKey: Pointer; ASize: SizeInt;
  2514. AInitVal: UInt32): UInt32;
  2515. begin
  2516. Result := xxHash32(AInitVal, AKey, ASize);
  2517. end;
  2518. { TxxHash32PascalHashFactory }
  2519. class function TxxHash32PascalHashFactory.GetHashService: THashServiceClass;
  2520. begin
  2521. Result := THashService<TxxHash32PascalHashFactory>;
  2522. end;
  2523. class function TxxHash32PascalHashFactory.GetHashCode(AKey: Pointer; ASize: SizeInt;
  2524. AInitVal: UInt32): UInt32;
  2525. begin
  2526. Result := xxHash32Pascal(AInitVal, AKey, ASize);
  2527. end;
  2528. { TAdler32HashFactory }
  2529. class function TAdler32HashFactory.GetHashService: THashServiceClass;
  2530. begin
  2531. Result := THashService<TAdler32HashFactory>;
  2532. end;
  2533. class function TAdler32HashFactory.GetHashCode(AKey: Pointer; ASize: SizeInt;
  2534. AInitVal: UInt32): UInt32;
  2535. begin
  2536. Result := Adler32(AKey, ASize);
  2537. end;
  2538. { TSdbmHashFactory }
  2539. class function TSdbmHashFactory.GetHashService: THashServiceClass;
  2540. begin
  2541. Result := THashService<TSdbmHashFactory>;
  2542. end;
  2543. class function TSdbmHashFactory.GetHashCode(AKey: Pointer; ASize: SizeInt;
  2544. AInitVal: UInt32): UInt32;
  2545. begin
  2546. Result := sdbm(AKey, ASize);
  2547. end;
  2548. { TSimpleChecksumFactory }
  2549. class function TSimpleChecksumFactory.GetHashService: THashServiceClass;
  2550. begin
  2551. Result := THashService<TSimpleChecksumFactory>;
  2552. end;
  2553. class function TSimpleChecksumFactory.GetHashCode(AKey: Pointer; ASize: SizeInt;
  2554. AInitVal: UInt32): UInt32;
  2555. begin
  2556. Result := SimpleChecksumHash(AKey, ASize);
  2557. end;
  2558. { TDelphiDoubleHashFactory }
  2559. class function TDelphiDoubleHashFactory.GetHashService: THashServiceClass;
  2560. begin
  2561. Result := TExtendedHashService<TDelphiDoubleHashFactory>;
  2562. end;
  2563. class function TDelphiDoubleHashFactory.GetHashCode(AKey: Pointer; ASize: SizeInt; AInitVal: UInt32): UInt32;
  2564. begin
  2565. Result := DelphiHashLittle(AKey, ASize, AInitVal);
  2566. end;
  2567. class procedure TDelphiDoubleHashFactory.GetHashList(AKey: Pointer; ASize: SizeInt; AHashList: PUInt32;
  2568. AOptions: TGetHashListOptions);
  2569. var
  2570. LHash: UInt32;
  2571. AHashListParams: PUInt16 absolute AHashList;
  2572. begin
  2573. {$WARNINGS OFF}
  2574. case AHashListParams[0] of
  2575. -2:
  2576. begin
  2577. if not (ghloHashListAsInitData in AOptions) then
  2578. AHashList[1] := 0;
  2579. LHash := 0;
  2580. DelphiHashLittle2(AKey, ASize, LHash, AHashList[1]);
  2581. Exit;
  2582. end;
  2583. -1:
  2584. begin
  2585. if not (ghloHashListAsInitData in AOptions) then
  2586. AHashList[1] := 0;
  2587. LHash := 0;
  2588. DelphiHashLittle2(AKey, ASize, AHashList[1], LHash);
  2589. Exit;
  2590. end;
  2591. 0: Exit;
  2592. 1:
  2593. begin
  2594. if not (ghloHashListAsInitData in AOptions) then
  2595. AHashList[1] := 0;
  2596. LHash := 0;
  2597. DelphiHashLittle2(AKey, ASize, AHashList[1], LHash);
  2598. Exit;
  2599. end;
  2600. 2:
  2601. begin
  2602. if not (ghloHashListAsInitData in AOptions) then
  2603. begin
  2604. AHashList[1] := 0;
  2605. AHashList[2] := 0;
  2606. end;
  2607. DelphiHashLittle2(AKey, ASize, AHashList[1], AHashList[2]);
  2608. Exit;
  2609. end;
  2610. else
  2611. raise EArgumentOutOfRangeException.CreateRes(@SArgumentOutOfRange);
  2612. end;
  2613. {.$WARNINGS ON} // do not enable warnings ever in this unit, or you will get many warnings about uninitialized TEqualityComparerVMT fields
  2614. end;
  2615. { TDelphiQuadrupleHashFactory }
  2616. class function TDelphiQuadrupleHashFactory.GetHashService: THashServiceClass;
  2617. begin
  2618. Result := TExtendedHashService<TDelphiQuadrupleHashFactory>;
  2619. end;
  2620. class function TDelphiQuadrupleHashFactory.GetHashCode(AKey: Pointer; ASize: SizeInt; AInitVal: UInt32): UInt32;
  2621. begin
  2622. Result := DelphiHashLittle(AKey, ASize, AInitVal);
  2623. end;
  2624. class procedure TDelphiQuadrupleHashFactory.GetHashList(AKey: Pointer; ASize: SizeInt; AHashList: PUInt32;
  2625. AOptions: TGetHashListOptions);
  2626. var
  2627. LHash: UInt32;
  2628. AHashListParams: PInt16 absolute AHashList;
  2629. begin
  2630. case AHashListParams[0] of
  2631. -4:
  2632. begin
  2633. if not (ghloHashListAsInitData in AOptions) then
  2634. AHashList[1] := 1988;
  2635. LHash := 2004;
  2636. DelphiHashLittle2(AKey, ASize, LHash, AHashList[1]);
  2637. Exit;
  2638. end;
  2639. -3:
  2640. begin
  2641. if not (ghloHashListAsInitData in AOptions) then
  2642. AHashList[1] := 2004;
  2643. LHash := 1988;
  2644. DelphiHashLittle2(AKey, ASize, AHashList[1], LHash);
  2645. Exit;
  2646. end;
  2647. -2:
  2648. begin
  2649. if not (ghloHashListAsInitData in AOptions) then
  2650. AHashList[1] := 0;
  2651. LHash := 0;
  2652. DelphiHashLittle2(AKey, ASize, LHash, AHashList[1]);
  2653. Exit;
  2654. end;
  2655. -1:
  2656. begin
  2657. if not (ghloHashListAsInitData in AOptions) then
  2658. AHashList[1] := 0;
  2659. LHash := 0;
  2660. DelphiHashLittle2(AKey, ASize, AHashList[1], LHash);
  2661. Exit;
  2662. end;
  2663. 0: Exit;
  2664. 1:
  2665. begin
  2666. if not (ghloHashListAsInitData in AOptions) then
  2667. AHashList[1] := 0;
  2668. LHash := 0;
  2669. DelphiHashLittle2(AKey, ASize, AHashList[1], LHash);
  2670. Exit;
  2671. end;
  2672. 2:
  2673. begin
  2674. case AHashListParams[1] of
  2675. 0, 1:
  2676. begin
  2677. if not (ghloHashListAsInitData in AOptions) then
  2678. begin
  2679. AHashList[1] := 0;
  2680. AHashList[2] := 0;
  2681. end;
  2682. DelphiHashLittle2(AKey, ASize, AHashList[1], AHashList[2]);
  2683. Exit;
  2684. end;
  2685. 2:
  2686. begin
  2687. if not (ghloHashListAsInitData in AOptions) then
  2688. begin
  2689. AHashList[1] := 2004;
  2690. AHashList[2] := 1988;
  2691. end;
  2692. DelphiHashLittle2(AKey, ASize, AHashList[1], AHashList[2]);
  2693. Exit;
  2694. end;
  2695. else
  2696. raise EArgumentOutOfRangeException.CreateRes(@SArgumentOutOfRange);
  2697. end;
  2698. end;
  2699. 4:
  2700. case AHashListParams[1] of
  2701. 1:
  2702. begin
  2703. if not (ghloHashListAsInitData in AOptions) then
  2704. begin
  2705. AHashList[1] := 0;
  2706. AHashList[2] := 0;
  2707. end;
  2708. DelphiHashLittle2(AKey, ASize, AHashList[1], AHashList[2]);
  2709. Exit;
  2710. end;
  2711. 2:
  2712. begin
  2713. if not (ghloHashListAsInitData in AOptions) then
  2714. begin
  2715. AHashList[3] := 2004;
  2716. AHashList[4] := 1988;
  2717. end;
  2718. DelphiHashLittle2(AKey, ASize, AHashList[3], AHashList[4]);
  2719. Exit;
  2720. end;
  2721. else
  2722. raise EArgumentOutOfRangeException.CreateRes(@SArgumentOutOfRange);
  2723. end;
  2724. else
  2725. raise EArgumentOutOfRangeException.CreateRes(@SArgumentOutOfRange);
  2726. end;
  2727. end;
  2728. { TDelphiSixfoldHashFactory }
  2729. class function TDelphiSixfoldHashFactory.GetHashService: THashServiceClass;
  2730. begin
  2731. Result := TExtendedHashService<TDelphiSixfoldHashFactory>;
  2732. end;
  2733. class function TDelphiSixfoldHashFactory.GetHashCode(AKey: Pointer; ASize: SizeInt; AInitVal: UInt32): UInt32;
  2734. begin
  2735. Result := DelphiHashLittle(AKey, ASize, AInitVal);
  2736. end;
  2737. class procedure TDelphiSixfoldHashFactory.GetHashList(AKey: Pointer; ASize: SizeInt; AHashList: PUInt32;
  2738. AOptions: TGetHashListOptions);
  2739. var
  2740. LHash: UInt32;
  2741. AHashListParams: PInt16 absolute AHashList;
  2742. begin
  2743. case AHashListParams[0] of
  2744. -6:
  2745. begin
  2746. if not (ghloHashListAsInitData in AOptions) then
  2747. AHashList[1] := 2;
  2748. LHash := 1;
  2749. DelphiHashLittle2(AKey, ASize, LHash, AHashList[1]);
  2750. Exit;
  2751. end;
  2752. -5:
  2753. begin
  2754. if not (ghloHashListAsInitData in AOptions) then
  2755. AHashList[1] := 1;
  2756. LHash := 2;
  2757. DelphiHashLittle2(AKey, ASize, AHashList[1], LHash);
  2758. Exit;
  2759. end;
  2760. -4:
  2761. begin
  2762. if not (ghloHashListAsInitData in AOptions) then
  2763. AHashList[1] := 1988;
  2764. LHash := 2004;
  2765. DelphiHashLittle2(AKey, ASize, LHash, AHashList[1]);
  2766. Exit;
  2767. end;
  2768. -3:
  2769. begin
  2770. if not (ghloHashListAsInitData in AOptions) then
  2771. AHashList[1] := 2004;
  2772. LHash := 1988;
  2773. DelphiHashLittle2(AKey, ASize, AHashList[1], LHash);
  2774. Exit;
  2775. end;
  2776. -2:
  2777. begin
  2778. if not (ghloHashListAsInitData in AOptions) then
  2779. AHashList[1] := 0;
  2780. LHash := 0;
  2781. DelphiHashLittle2(AKey, ASize, LHash, AHashList[1]);
  2782. Exit;
  2783. end;
  2784. -1:
  2785. begin
  2786. if not (ghloHashListAsInitData in AOptions) then
  2787. AHashList[1] := 0;
  2788. LHash := 0;
  2789. DelphiHashLittle2(AKey, ASize, AHashList[1], LHash);
  2790. Exit;
  2791. end;
  2792. 0: Exit;
  2793. 1:
  2794. begin
  2795. if not (ghloHashListAsInitData in AOptions) then
  2796. AHashList[1] := 0;
  2797. LHash := 0;
  2798. DelphiHashLittle2(AKey, ASize, AHashList[1], LHash);
  2799. Exit;
  2800. end;
  2801. 2:
  2802. begin
  2803. case AHashListParams[1] of
  2804. 0, 1:
  2805. begin
  2806. if not (ghloHashListAsInitData in AOptions) then
  2807. begin
  2808. AHashList[1] := 0;
  2809. AHashList[2] := 0;
  2810. end;
  2811. DelphiHashLittle2(AKey, ASize, AHashList[1], AHashList[2]);
  2812. Exit;
  2813. end;
  2814. 2:
  2815. begin
  2816. if not (ghloHashListAsInitData in AOptions) then
  2817. begin
  2818. AHashList[1] := 2004;
  2819. AHashList[2] := 1988;
  2820. end;
  2821. DelphiHashLittle2(AKey, ASize, AHashList[1], AHashList[2]);
  2822. Exit;
  2823. end;
  2824. else
  2825. raise EArgumentOutOfRangeException.CreateRes(@SArgumentOutOfRange);
  2826. end;
  2827. end;
  2828. 6:
  2829. case AHashListParams[1] of
  2830. 1:
  2831. begin
  2832. if not (ghloHashListAsInitData in AOptions) then
  2833. begin
  2834. AHashList[1] := 0;
  2835. AHashList[2] := 0;
  2836. end;
  2837. DelphiHashLittle2(AKey, ASize, AHashList[1], AHashList[2]);
  2838. Exit;
  2839. end;
  2840. 2:
  2841. begin
  2842. if not (ghloHashListAsInitData in AOptions) then
  2843. begin
  2844. AHashList[3] := 2004;
  2845. AHashList[4] := 1988;
  2846. end;
  2847. DelphiHashLittle2(AKey, ASize, AHashList[3], AHashList[4]);
  2848. Exit;
  2849. end;
  2850. 3:
  2851. begin
  2852. if not (ghloHashListAsInitData in AOptions) then
  2853. begin
  2854. AHashList[5] := 1;
  2855. AHashList[6] := 2;
  2856. end;
  2857. DelphiHashLittle2(AKey, ASize, AHashList[5], AHashList[6]);
  2858. Exit;
  2859. end;
  2860. else
  2861. raise EArgumentOutOfRangeException.CreateRes(@SArgumentOutOfRange);
  2862. end;
  2863. else
  2864. raise EArgumentOutOfRangeException.CreateRes(@SArgumentOutOfRange);
  2865. end;
  2866. end;
  2867. { TOrdinalComparer<T, THashFactory> }
  2868. class constructor TOrdinalComparer<T, THashFactory>.Create;
  2869. begin
  2870. if THashFactory.InheritsFrom(TExtendedHashService) then
  2871. begin
  2872. FExtendedEqualityComparer := TExtendedEqualityComparer<T>.Default(TExtendedHashFactoryClass(THashFactory));
  2873. FEqualityComparer := IEqualityComparer<T>(FExtendedEqualityComparer);
  2874. end
  2875. else
  2876. FEqualityComparer := TEqualityComparer<T>.Default(THashFactory);
  2877. FComparer := TComparer<T>.Default;
  2878. end;
  2879. { TGStringComparer<T, THashFactory> }
  2880. class destructor TGStringComparer<T, THashFactory>.Destroy;
  2881. begin
  2882. if Assigned(FOrdinal) then
  2883. FOrdinal.Free;
  2884. end;
  2885. class function TGStringComparer<T, THashFactory>.Ordinal: TCustomComparer<T>;
  2886. begin
  2887. if not Assigned(FOrdinal) then
  2888. FOrdinal := TGOrdinalStringComparer<T, THashFactory>.Create;
  2889. Result := FOrdinal;
  2890. end;
  2891. { TGOrdinalStringComparer<T, THashFactory> }
  2892. function TGOrdinalStringComparer<T, THashFactory>.Compare(const ALeft, ARight: T): Integer;
  2893. begin
  2894. Result := FComparer.Compare(ALeft, ARight);
  2895. end;
  2896. function TGOrdinalStringComparer<T, THashFactory>.Equals(const ALeft, ARight: T): Boolean;
  2897. begin
  2898. Result := FEqualityComparer.Equals(ALeft, ARight);
  2899. end;
  2900. function TGOrdinalStringComparer<T, THashFactory>.GetHashCode(const AValue: T): UInt32;
  2901. begin
  2902. Result := FEqualityComparer.GetHashCode(AValue);
  2903. end;
  2904. procedure TGOrdinalStringComparer<T, THashFactory>.GetHashList(const AValue: T; AHashList: PUInt32);
  2905. begin
  2906. FExtendedEqualityComparer.GetHashList(AValue, AHashList);
  2907. end;
  2908. { TGIStringComparer<T, THashFactory> }
  2909. class destructor TGIStringComparer<T, THashFactory>.Destroy;
  2910. begin
  2911. if Assigned(FOrdinal) then
  2912. FOrdinal.Free;
  2913. end;
  2914. class function TGIStringComparer<T, THashFactory>.Ordinal: TCustomComparer<T>;
  2915. begin
  2916. if not Assigned(FOrdinal) then
  2917. FOrdinal := TGOrdinalIStringComparer<T, THashFactory>.Create;
  2918. Result := FOrdinal;
  2919. end;
  2920. { TGOrdinalIStringComparer<T, THashFactory> }
  2921. function TGOrdinalIStringComparer<T, THashFactory>.Compare(const ALeft, ARight: T): Integer;
  2922. begin
  2923. Result := FComparer.Compare(ALeft.ToLower, ARight.ToLower);
  2924. end;
  2925. function TGOrdinalIStringComparer<T, THashFactory>.Equals(const ALeft, ARight: T): Boolean;
  2926. begin
  2927. Result := FEqualityComparer.Equals(ALeft.ToLower, ARight.ToLower);
  2928. end;
  2929. function TGOrdinalIStringComparer<T, THashFactory>.GetHashCode(const AValue: T): UInt32;
  2930. begin
  2931. Result := FEqualityComparer.GetHashCode(AValue.ToLower);
  2932. end;
  2933. procedure TGOrdinalIStringComparer<T, THashFactory>.GetHashList(const AValue: T; AHashList: PUInt32);
  2934. begin
  2935. FExtendedEqualityComparer.GetHashList(AValue.ToLower, AHashList);
  2936. end;
  2937. function BobJenkinsHash(const AData; ALength, AInitData: Integer): Integer;
  2938. begin
  2939. Result := DelphiHashLittle(@AData, ALength, AInitData);
  2940. end;
  2941. function BinaryCompare(const ALeft, ARight: Pointer; ASize: PtrUInt): Integer;
  2942. begin
  2943. Result := CompareMemRange(ALeft, ARight, ASize);
  2944. end;
  2945. function _LookupVtableInfo(AGInterface: TDefaultGenericInterface; ATypeInfo: PTypeInfo; ASize: SizeInt): Pointer;
  2946. begin
  2947. Result := _LookupVtableInfoEx(AGInterface, ATypeInfo, ASize, nil);
  2948. end;
  2949. function _LookupVtableInfoEx(AGInterface: TDefaultGenericInterface; ATypeInfo: PTypeInfo; ASize: SizeInt;
  2950. AFactory: THashFactoryClass): Pointer;
  2951. begin
  2952. if not Assigned(ATypeInfo) or (ATypeInfo^.Kind in TComparerService.UseBinaryMethods) then begin
  2953. System.Error(reInvalidCast);
  2954. Exit(Nil);
  2955. end;
  2956. case AGInterface of
  2957. giComparer:
  2958. Exit(
  2959. TComparerService.LookupComparer(ATypeInfo, ASize));
  2960. giEqualityComparer:
  2961. begin
  2962. if AFactory = nil then
  2963. AFactory := TDefaultHashFactory;
  2964. Exit(
  2965. AFactory.GetHashService.LookupEqualityComparer(ATypeInfo, ASize));
  2966. end;
  2967. giExtendedEqualityComparer:
  2968. begin
  2969. if AFactory = nil then
  2970. AFactory := TDelphiDoubleHashFactory;
  2971. Exit(
  2972. TExtendedHashServiceClass(AFactory.GetHashService).LookupExtendedEqualityComparer(ATypeInfo, ASize));
  2973. end;
  2974. else
  2975. System.Error(reRangeError);
  2976. Exit(nil);
  2977. end;
  2978. end;
  2979. { TCollectionHelper }
  2980. Function GenericCollSort(Item1,Item2 : TCollectionItem; aContext : Pointer) : Integer;
  2981. begin
  2982. Result:=TCollectionItemComparer(aContext).Compare(Item1,Item2);
  2983. end;
  2984. Procedure TCollectionHelper.sort(const AComparer: TCollectionItemComparer);
  2985. begin
  2986. aComparer._AddRef;
  2987. try
  2988. Sort(GenericCollSort,Pointer(aComparer));
  2989. finally
  2990. aComparer._Release;
  2991. end;
  2992. end;
  2993. end.