library ArrayUtils;
{ Reduce EXE size by disabling as much of RTTI as possible Delphi}
{$IF CompilerVersion >= 21.0}
{$WEAKLINKRTTI ON}
{$RTTI EXPLICIT METHODS([]) PROPERTIES([]) FIELDS([])}
{$IFEND}
uses
System.SysUtils,
System.Variants,
System.Generics.Collections,
System.Generics.Defaults;
{$R *.res}
type
TArrayType = (atInteger, atFloat, atString);
function CompareValue(A, B: Integer): Integer; overload;
begin
Result := A - B;
end;
function CompareValue(A, B: Double): Integer; overload;
begin
if A < B then
Result := -1
else if A > B then
Result := 1
else
Result := 0;
end;
function GetArrayType(const Arr: OleVariant): TArrayType;
var
VType: TVarType;
begin
VType := VarType(Arr[VarArrayLowBound(Arr, 1)]);
case VType of
varByte, varShortInt, varSmallInt, varInteger, varInt64: Result := atInteger;
varSingle, varDouble, varCurrency: Result := atFloat;
else Result := atString;
end;
end;
function CompareVariants(const Left, Right: Variant; ArrType: TArrayType; IsAscending: Boolean): Integer;
begin
case ArrType of
atInteger:
Result := CompareValue(Integer(Left), Integer(Right));
atFloat:
Result := CompareValue(Double(Left), Double(Right));
atString:
Result := AnsiCompareStr(VarToStr(Left), VarToStr(Right));
else
Result := 0;
end;
if not IsAscending then
Result := -Result;
end;
function ProcessArray(const InputArr: OleVariant; var OutputArr: OleVariant; SortOrder: Integer): WordBool; stdcall;
var
List: TList<Variant>;
I: Integer;
ArrType: TArrayType;
IsAscending: Boolean;
begin
Result := False;
if VarIsNull(InputArr) or VarIsEmpty(InputArr) then
Exit;
IsAscending := SortOrder = 1;
List := TList<Variant>.Create;
try
for I := VarArrayLowBound(InputArr, 1) to VarArrayHighBound(InputArr, 1) do
if List.IndexOf(InputArr[I]) = -1 then
List.Add(InputArr[I]);
ArrType := GetArrayType(InputArr);
List.Sort(TComparer<Variant>.Construct(
function(const Left, Right: Variant): Integer
begin
Result := CompareVariants(Left, Right, ArrType, IsAscending);
end));
OutputArr := VarArrayCreate([0, List.Count - 1], varVariant);
for I := 0 to List.Count - 1 do
OutputArr[I] := List[I];
Result := True;
finally
List.Free;
end;
end;
exports
ProcessArray;
begin
end.