Reputation: 9986
I'm trying to implement array append in Delphi 7, because the standard library does not have it. This is what I have so far, but it complains about incompatible types when I try to get the length of the array.
procedure ArrayAppend(var GenericArray; const Element);
var
len: Integer;
begin
len := Length(GenericArray);
SetLength(GenericArray, len+1);
GenericArray[len] := Element;
end;
I'm trying to find what the most generic type of array is in Delphi 7.
I also have no issue returning the modified array if that's the only way to do it.
Upvotes: 1
Views: 2128
Reputation: 613491
To illustrate what Rob Kennedy said in comments, here is a function that will append a value to a dynamic array. However, this is a rather crippled function in that it does not support managed types. So you cannot have strings, interfaces, variants or dynamic arrays. Or indeed compound structures that contain any managed types.
{$APPTYPE CONSOLE}
uses
SysUtils,
TypInfo;
type
PDynArrayTypeInfo = ^TDynArrayTypeInfo;
TDynArrayTypeInfo = packed record
kind: Byte;
name: Byte;
elSize: Longint;
elType: ^PDynArrayTypeInfo;
varType: Integer;
end;
function DynArraySize(a: Pointer): Integer;
asm
TEST EAX, EAX
JZ @@exit
MOV EAX, [EAX-4]
@@exit:
end;
type
TIntegerArray = array of Integer;
procedure AppendUnmanaged(var arr{: TArray<T>}; const Value{: T}; TypeInfo: PTypeInfo);
var
len, elSize: Integer;
begin
len := DynArraySize(Pointer(arr)) + 1;
DynArraySetLength(Pointer(arr), TypeInfo, 1, @len);
inc(PAnsiChar(TypeInfo), PDynArrayTypeInfo(TypeInfo).name);
elSize := PDynArrayTypeInfo(TypeInfo).elSize;
Move(Value, (PAnsiChar(Pointer(arr)) + (len-1)*elSize)^, elSize);
end;
procedure Main;
var
arr: TIntegerArray;
i, Value: Integer;
begin
Value := -1;
AppendUnmanaged(arr, Value, TypeInfo(TIntegerArray));
Value := 666;
AppendUnmanaged(arr, Value, TypeInfo(TIntegerArray));
Value := 42;
AppendUnmanaged(arr, Value, TypeInfo(TIntegerArray));
for i := low(arr) to high(arr) do
Writeln(arr[i]);
end;
begin
try
Main;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
Readln;
end.
You can see some obvious problems with this when compared with modern day Delphi which has generic types and array concatenation baked into the language. Specifically I'm thinking of these issues:
Now, it is certainly possible to replicate what the compiler does when assigning a managed type. But is it really worthwhile? Is the code above, especially the calling code, really an improvement over the type safe alternatives? Personally I don't think so.
Upvotes: 2