@@ -3493,17 +3493,21 @@ TEnumerable = class
34933493 const resultSelector: Func<TFirst, TSecond, TResult>): IEnumerable<TResult>; overload; static;
34943494 end ;
34953495
3496- TStringComparer = class (TCustomComparer <string>)
3496+ TStringComparer = class (TObject, IComparer<string>, IEqualityComparer <string>)
34973497 private
34983498 fLocaleOptions: TLocaleOptions;
34993499 fIgnoreCase: Boolean;
35003500 class var
35013501 fOrdinal: TStringComparer;
35023502 fOrdinalIgnoreCase: TStringComparer;
35033503 protected
3504- function Compare (const Left, Right: string): Integer; override;
3505- function Equals (const Left, Right: string): Boolean; override;
3506- function GetHashCode (const Value : string): Integer; override;
3504+ function QueryInterface (const IID: TGUID; out Obj): HResult; stdcall;
3505+ function _AddRef : Integer; stdcall;
3506+ function _Release : Integer; stdcall;
3507+
3508+ function Compare (const left, right: string): Integer; reintroduce;
3509+ function Equals (const left, right: string): Boolean; reintroduce;
3510+ function GetHashCode (const value : string): Integer; reintroduce;
35073511 public
35083512 constructor Create(localeOptions: TLocaleOptions; ignoreCase: Boolean);
35093513 class constructor Create;
@@ -3553,9 +3557,6 @@ implementation
35533557
35543558uses
35553559 Character,
3556- { $IFDEF DELPHIXE8_UP}
3557- System.Hash,
3558- { $ENDIF}
35593560 Rtti,
35603561 Spring.Collections.Base,
35613562 Spring.Collections.Dictionaries,
@@ -3567,6 +3568,7 @@ implementation
35673568 Spring.Collections.Queues,
35683569 Spring.Collections.Sets,
35693570 Spring.Collections.Stacks,
3571+ Spring.Comparers,
35703572 Spring.ResourceStrings;
35713573
35723574
@@ -7580,68 +7582,89 @@ constructor TStringComparer.Create(localeOptions: TLocaleOptions;
75807582 FreeAndNil(fOrdinalIgnoreCase);
75817583end ;
75827584
7583- function TStringComparer.Compare (const Left, Right: string): Integer;
7584- var
7585- L, R: string;
7585+ function TStringComparer.Compare (const left, right: string): Integer;
75867586begin
75877587 if fIgnoreCase then
7588- begin
7589- { $IFNDEF DELPHIXE4_UP}
7590- L := TCharacter.ToUpper(Left);
7591- R := TCharacter.ToUpper(Right);
7592- { $ELSE}
7593- L := Char.ToUpper(Left);
7594- R := Char.ToUpper(Right);
7595- { $ENDIF}
7596- end else
7597- begin
7598- L := Left;
7599- R := Right;
7600- end ;
7601-
7602- Result := CompareStr(L, R, fLocaleOptions);
7588+ Result := AnsiCompareText(left, right)
7589+ else
7590+ Result := AnsiCompareStr(left, right);
76037591end ;
76047592
7605- function TStringComparer.Equals (const Left, Right: string): Boolean;
7606- var
7607- L, R: string;
7593+ function TStringComparer.Equals (const left, right: string): Boolean;
76087594begin
76097595 if fIgnoreCase then
7596+ Result := AnsiSameText(left, right)
7597+ else
7598+ Result := AnsiSameStr(left, right);
7599+ end ;
7600+
7601+ function TStringComparer.GetHashCode (const value : string): Integer;
7602+ const
7603+ FNV_Prime = 16777619 ;
7604+ FNV_OffsetBasis = Integer($811C9DC5); // 2166136261
7605+ NotAsciiMask = $FF80FF80;
7606+ LowerCaseMask = $00200020 ;
7607+
7608+ // for inlining when compiled as package - System.Length does not in that case
7609+ function Length (const s: string): NativeInt; inline;
76107610 begin
7611- { $IFNDEF DELPHIXE4_UP}
7612- L := TCharacter.ToUpper(Left);
7613- R := TCharacter.ToUpper(Right);
7614- { $ELSE}
7615- L := Char.ToUpper(Left);
7616- R := Char.ToUpper(Right);
7617- { $ENDIF}
7618- end else
7619- begin
7620- L := Left;
7621- R := Right;
7611+ Result := IntPtr(s);
7612+ if Result <> 0 then
7613+ Result := PInteger(@PByte(Result)[-4 ])^;
76227614 end ;
76237615
7624- Result := SameStr(L, R, fLocaleOptions);
7625- end ;
7616+ function GetHashCodeIgnoreCaseSlow (const value : string): Integer;
7617+ var
7618+ s: string;
7619+ len, i: NativeInt;
7620+ c: Integer;
7621+ begin
7622+ s := AnsiUpperCase(value );
7623+ len := Length(s);
7624+ Result := FNV_OffsetBasis;
7625+ i := 0 ;
7626+ while len > 0 do
7627+ begin
7628+ c := PIntegerArray(s)[i];
7629+ c := c or LowerCaseMask;
7630+ Result := Result xor c;
7631+ { $Q-}
7632+ Result := Result * FNV_PRIME;
7633+ { $IFDEF OVERFLOWCHECKS_ON}{ $Q+}{ $ENDIF}
7634+ Inc(i);
7635+ Dec(len, 2 );
7636+ end ;
7637+ end ;
76267638
7627- function TStringComparer.GetHashCode (const Value : string): Integer;
7639+ label
7640+ NotAscii;
76287641var
7629- s: string;
7642+ len, i: NativeInt;
7643+ hashCode, c: Integer;
76307644begin
7645+ len := Length(value );
76317646 if fIgnoreCase then
7632- { $IFNDEF DELPHIXE4_UP}
7633- S := TCharacter.ToUpper(Value )
7634- { $ELSE}
7635- S := Char.ToUpper(Value )
7636- { $ENDIF}
7647+ begin
7648+ hashCode := FNV_OffsetBasis;
7649+ i := 0 ;
7650+ while len > 0 do
7651+ begin
7652+ c := PIntegerArray(value )[i];
7653+ if c and NotAsciiMask <> 0 then goto NotAscii;
7654+ c := c or LowerCaseMask;
7655+ hashCode := hashCode xor c;
7656+ { $Q-}
7657+ hashCode := hashCode * FNV_PRIME;
7658+ { $IFDEF OVERFLOWCHECKS_ON}{ $Q+}{ $ENDIF}
7659+ Inc(i);
7660+ Dec(len, 2 );
7661+ end ;
7662+ Exit(hashCode);
7663+ NotAscii:
7664+ Result := GetHashCodeIgnoreCaseSlow(value );
7665+ end
76377666 else
7638- S := Value ;
7639-
7640- { $IFDEF DELPHIXE8_UP}
7641- Result := THashBobJenkins.GetHashValue(S);
7642- { $ELSE}
7643- Result := BobJenkinsHash(PChar(S)^, SizeOf(Char) * Length(S), 0 );
7644- { $ENDIF}
7667+ Result := DefaultHashFunction(Pointer(value )^, len * SizeOf(Char));
76457668end ;
76467669
76477670class function TStringComparer.Ordinal : TStringComparer;
@@ -7654,6 +7677,24 @@ class function TStringComparer.OrdinalIgnoreCase: TStringComparer;
76547677 Result := fOrdinalIgnoreCase;
76557678end ;
76567679
7680+ function TStringComparer.QueryInterface (const IID: TGUID; out Obj): HResult;
7681+ begin
7682+ if GetInterface(IID, Obj) then
7683+ Result := S_OK
7684+ else
7685+ Result := E_NOINTERFACE;
7686+ end ;
7687+
7688+ function TStringComparer._AddRef : Integer;
7689+ begin
7690+ Result := -1 ;
7691+ end ;
7692+
7693+ function TStringComparer._Release : Integer;
7694+ begin
7695+ Result := -1 ;
7696+ end ;
7697+
76577698{ $ENDREGION}
76587699
76597700
0 commit comments