Project: Array Utilities Unit
Unit: DelphiDabbler.Lib.ArrayUtils
Record: TArrayUtils
Applies to: ~>0.1
type
TCallback<T> = reference to procedure (const AElem: T);
class procedure DeleteAndReleaseRange<T>(var A: TArray<T>;
AStartIndex, AEndIndex: Integer; const AReleaser: TCallback<T>);
overload; static;
class procedure DeleteAndReleaseRange<T>(var A: TArray<T>;
AStartIndex: Integer; const AReleaser: TCallback<T>);
overload; static;Deletes a range of one or more elements from an array and releases any resources associated with the deleted elements.
The length of the array is reduced by the number of elements deleted.
Parameters:
-
A - Array from which the elements are to be deleted and associated resources released. The array is updated in place. Empty arrays are ignored.
-
AStartIndex - Index of the first element in the range to be deleted and released.
If AStartIndex <
0then it is adjusted to be equal to0. -
AEndIndex - Optional parameter containing the index of the last element in the range to be deleted.
If AEndIndex is not supplied then the end of the range is assumed to be the last element of the array, so that all elements from AStartIndex to the end of the array are deleted.
If AEndIndex is ≥
Length(A)then it is adjusted to be equal toLength(A) - 1.If AEndIndex < AStartIndex, after both have been adjusted, then no elements are deleted, no resources are released and A is not changed.
-
AReleaser - Callback procedure called for each deleted element. Must release any resource associated with the element.
Parameter(s):
- AElem - Element whose associated resource is to be released.
If you want to delete and release associated resources of all the elements of an array with indices ≥ AStartIndex then there is no need to provide AEndIndex.
To delete and release the associated resource of a single element set both AStartIndex and AEndIndex to the same index. Alternatively use DeleteAndRelease<T>.
Both examples below use a custom TMockResource record that emulates a resource that must be released. The record keeps track of the total number of instantiations. It is defined as follows:
type
TMockResource = record
public
constructor Create(const AField: Integer);
procedure Release;
var Field: Integer;
class var InstanceCount: Cardinal;
end;
{ TMockResource }
constructor TMockResource.Create(const AField: Integer);
begin
Field := AField;
Inc(InstanceCount);
end;
procedure TMockResource.Release;
begin
Dec(InstanceCount);
end;This first example uses the overload of DeleteAndReleaseRange<T> that takes both the start and end indices of a range as parameters.
procedure DeleteAndReleaseRange_Eg1;
var
R, R0, R1, R2, R3, R4: TMockResource;
RA, Expected: TArray<TMockResource>;
begin
// create array of 5 "resources"
R0 := TMockResource.Create(0);
R1 := TMockResource.Create(1);
R2 := TMockResource.Create(2);
R3 := TMockResource.Create(3);
R4 := TMockResource.Create(4);
RA := TArray<TMockResource>.Create(R0, R1, R2, R3, R4);
Assert(Length(RA) = 5, '5 element array expected');
Assert(TMockResource.InstanceCount = 5, 'Expected 5 "resources" allocated');
// delete and release elements in range 1..3
TArrayUtils.DeleteAndReleaseRange<TMockResource>(
RA,
1,
3,
procedure (const AElem: TMockResource) begin AElem.Release end
);
// check array size reduced and one resource released
Assert(Length(RA) = 2, '2 element array expected following deletion');
Assert(TMockResource.InstanceCount = 2, 'Expected 2 "resources" allocated');
Expected := TArray<TMockResource>.Create(R0, R4);
Assert(TArrayUtils.Equal<TMockResource>(Expected, RA),
'updated array content not as expected');
// clear up remaining allocations
for R in RA do R.Release;
Assert(TMockResource.InstanceCount = 0, 'Expected all "resources" released');
end;The second example uses the overload of DeleteAndReleaseRange<T> that takes only the start index of a range as a parameter.
procedure DeleteAndReleaseRange_Eg2;
var
R, R0, R1, R2, R3, R4: TMockResource;
RA, Expected: TArray<TMockResource>;
begin
// create array of 5 "resources"
R0 := TMockResource.Create(0);
R1 := TMockResource.Create(1);
R2 := TMockResource.Create(2);
R3 := TMockResource.Create(3);
R4 := TMockResource.Create(4);
RA := TArray<TMockResource>.Create(R0, R1, R2, R3, R4);
Assert(Length(RA) = 5, '5 element array expected');
Assert(TMockResource.InstanceCount = 5, 'Expected 5 "resources" allocated');
// delete and release elements @ indices 2..end of array
TArrayUtils.DeleteAndReleaseRange<TMockResource>(
RA,
2,
procedure (const AElem: TMockResource) begin AElem.Release end
);
// check array size reduced and three resources released
Assert(Length(RA) = 2, '2 element array expected following deletion');
Assert(TMockResource.InstanceCount = 2, 'Expected 2 "resources" allocated');
Expected := TArray<TMockResource>.Create(R0, R1);
Assert(TArrayUtils.Equal<TMockResource>(Expected, RA),
'updated array content not as expected');
// clear up remaining allocations
for R in RA do R.Release;
Assert(TMockResource.InstanceCount = 0, 'Expected all "resources" released');
end;