Skip to content

vittee/RecordArray

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

10 Commits
 
 
 
 
 
 
 
 

Repository files navigation

RecordArray

Delphi Typed Pointer made easy.

What is it?

It is just a small unit for creating an array of a certain type at runtime, forget the GetMem() and FreeMem() and try..finally block.

Usually when an array is needed to be used as a pointer, we must allocate a memory block representing the array by using the GetMem() or alloc() by specifing element's size times the number of elements, then call FreeMem() to free up the memory.

This will result in this boring code.

var
  pWordArray: PWord;
begin
  pWordArray := GetMem(SizeOf(Word) * 10); // create 10 elements of Word
  try
    // Do something with the memory
  finally
    FreeMem(pWordArray);
  end;
end;

This unit helps eliminate that long code blocks into a single line.

  pWordArray := TRecordArray<PWord>.Create(10); // create a memory block for array of 10 words.

Why not use built-in dynamic array?

Yes, we can use dynamic array instead of manually allocating/deallocating the memory, but Delphi's dynamic array has its own memory layout and byte alignment, which sometimes incompatible with most C API.

Features

  • Work with any pointer types.
  • Flat memory layout, no byte alignment (packed)
  • Suitable for using with Win/C API.
  • Automatic reference counting (via Interface/COM), auto release memory.
  • Accessing element without doing pointer math.
  • Memory re-allocation, resizable array.

How to use

Creating

var
  WordArray: IRecordArray<PWord>; // IRecordArray enables auto-release feature.
begin
  WordArray := TRecordArray<PWord>.Create(10); // Create an array with 10 elements of Word
  // WordArray will be automatically deallocated when the function exit or no longer used.
end;

The data is stored in memory as little-endian on x86-64 CPU

If the data is already allocated somewhere else, just put the pointer to that data and specify the length directly.

var
  WordArray: IRecordArray<PWord>;
begin
  WordArray := TRecordArray<PWord>.Create(PointerToWords, 10); // Create an array with 10 elements of Word using a pointer.
end;

Getting array's length

  WordArray.Length

Resizing

  WordArray.Length := WordArray.Length + 5; // Expand 5 elements
  WordArray.Length := WordArray.Length - 5; // Shrink the last 5 elements

Getting an element

var
  I: Integer;
begin
  for I := 0 to WordArray.Length - 1 do
    DoSomethingWithWord(WordArray[I]^);
end;

Getting element's size

  WordArray.ElementSize

Getting memory size

  WordArray.DataSize

Getting memory block

  WordArray.Data

Joining another array

  WordArray.Append(AnotherWordArray)

Using with record/struct

A record type must has its pointer type declared.

type
  TMyRecord = packed record
    Value1: Integer;
    Value2: Integer;
  end;
  
  PMyRecord = ^TMyRecord;
  
var
  MyRecordArray: IRecordArray<PMyRecord>;
  I: Integer;
begin
  MyRecordArray := TRecordArray<PMyRecord>.Create(100);
  for I := 0 to MyRecordArray.Length - 1 do
  begin
    MyRecordArray[I].Value1 := I * 5;
    MyRecordArray[I].Value2 := I * 10;
  end;
end;

About

Delphi Typed Pointer made easy

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages