generics.defaults.pas 146 KB

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