generics.defaults.pas 144 KB

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