-
Couldn't load subscription status.
- Fork 113
Solution for Issue #125 and reverted change made in commit e90fee5 related to {$M-} #126
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 4 commits
a08120f
9d3fc34
936635e
f46ace6
f84d449
613eccf
ccd3c6a
ec5e5b6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -33,9 +33,20 @@ | |
| interface | ||
|
|
||
| uses | ||
| Rtti; | ||
| System.Generics.Collections, | ||
| System.Rtti; | ||
|
|
||
| type | ||
| //Allow custom comparisons | ||
| TCustomValueComparer = reference to function(const a, b: TValue): Integer; | ||
| TCustomValueComparerStore = record | ||
| private | ||
| class var CustomComparers: TDictionary<Pointer, TCustomValueComparer>; | ||
|
||
| public | ||
| class procedure RegisterCustomComparer<T>(const AComparer: TCustomValueComparer); static; | ||
| class procedure UnRegisterCustomComparer<T>; static; | ||
| end; | ||
|
|
||
| //TValue really needs to have an Equals operator overload! | ||
| TValueHelper = record helper for TValue | ||
| private | ||
|
|
@@ -64,6 +75,7 @@ TValueHelper = record helper for TValue | |
| function IsWord: Boolean; | ||
| function IsGuid: Boolean; | ||
| function IsInterface : Boolean; | ||
| function IsRecord: Boolean; | ||
| function AsDouble: Double; | ||
| function AsFloat: Extended; | ||
| function AsSingle: Single; | ||
|
|
@@ -101,11 +113,17 @@ function CompareValue(const Left, Right: TValue): Integer; | |
| EmptyResults: array[Boolean, Boolean] of Integer = ((0, -1), (1, 0)); | ||
| var | ||
| leftIsEmpty, rightIsEmpty: Boolean; | ||
| CustomComparer: TCustomValueComparer; | ||
| const | ||
| ErrorStr: String = 'Unable to compare %s. Use Delphi.Mocks.Helpers.TCustomValueComparerStore.RegisterCustomComparer<T> to add a ' + | ||
| 'method to compare records.'; | ||
| begin | ||
| leftIsEmpty := left.IsEmpty; | ||
| rightIsEmpty := right.IsEmpty; | ||
| if leftIsEmpty or rightIsEmpty then | ||
| Result := EmptyResults[leftIsEmpty, rightIsEmpty] | ||
| else if (Left.TypeInfo = Right.TypeInfo) and TCustomValueComparerStore.CustomComparers.TryGetValue(Left.TypeInfo, CustomComparer) then | ||
| Result := CustomComparer(Left, Right) | ||
| else if left.IsOrdinal and right.IsOrdinal then | ||
| Result := Math.CompareValue(left.AsOrdinal, right.AsOrdinal) | ||
| else if left.IsFloat and right.IsFloat then | ||
|
|
@@ -116,6 +134,8 @@ function CompareValue(const Left, Right: TValue): Integer; | |
| Result := NativeInt(left.AsObject) - NativeInt(right.AsObject) // TODO: instance comparer | ||
| else if Left.IsInterface and Right.IsInterface then | ||
| Result := NativeInt(left.AsInterface) - NativeInt(right.AsInterface) // TODO: instance comparer | ||
| else if Left.IsRecord and Right.IsRecord then | ||
| raise Exception.Create(Format(ErrorStr ,[Left.TypeInfo.Name])) | ||
| else if left.IsVariant and right.IsVariant then | ||
| begin | ||
| case VarCompareValue(left.AsVariant, right.AsVariant) of | ||
|
|
@@ -236,6 +256,11 @@ function TValueHelper.IsPointer: Boolean; | |
| Result := Kind = tkPointer; | ||
| end; | ||
|
|
||
| function TValueHelper.IsRecord: Boolean; | ||
| begin | ||
| Result := Kind = tkRecord; | ||
| end; | ||
|
|
||
| function TValueHelper.IsShortInt: Boolean; | ||
| begin | ||
| Result := TypeInfo = System.TypeInfo(ShortInt); | ||
|
|
@@ -307,4 +332,26 @@ function TRttiTypeHelper.TryGetMethod(const AName: string; out AMethod: TRttiMet | |
| Result := Assigned(AMethod); | ||
| end; | ||
|
|
||
|
|
||
|
|
||
| { TCustomValueComparerStore } | ||
|
|
||
| class procedure TCustomValueComparerStore.RegisterCustomComparer<T>(const AComparer: TCustomValueComparer); | ||
| begin | ||
| CustomComparers.AddOrSetValue(System.TypeInfo(T), AComparer); | ||
| end; | ||
|
|
||
| class procedure TCustomValueComparerStore.UnRegisterCustomComparer<T>; | ||
| begin | ||
| CustomComparers.Remove(System.TypeInfo(T)); | ||
| end; | ||
|
|
||
|
|
||
|
|
||
| initialization | ||
| TCustomValueComparerStore.CustomComparers := TDictionary<Pointer, TCustomValueComparer>.Create; | ||
|
|
||
| finalization | ||
| TCustomValueComparerStore.CustomComparers.Free; | ||
|
|
||
| end. | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No idea if it's possible, but did you try doing something like
TCustomValueComparer = reference to function<T>(const a, b: T): Integer;that would allow us to avoid TValue
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think that would be possible as I think you might need to declare it as
TCustomValueComparer<T> = reference to function<T>(const a, b: T): Integer;so it couldn't be stored in a common container. Having said that, I am sure there should be a way to do this without the need for TValue?