pas2js/packages/rtl/arrayutils.pas
2020-12-11 16:48:44 +00:00

195 lines
3.9 KiB
ObjectPascal

unit arrayutils;
{$mode objfpc}
{$modeswitch typehelpers}
interface
uses
Types, SysUtils;
Type
TBytesHelper = type helper for TBytes
strict private
function get_Length: Integer;
procedure set_Length(const AValue: Integer);
public
function Compare(const ARight: TBytes): Integer;
function High: Integer;
function Low: Integer;
function SubBytes(const AStartIndex: Integer): TBytes; overload; inline;
function SubBytes(const AStartIndex, ALength: Integer): TBytes; overload; inline;
property Length: Integer read get_Length write set_Length;
end;
TWords = TWordDynArray;
TWordDynArrayHelper = type helper for TWordDynArray
private
function get_Length: Integer;
procedure set_Length(const AValue: Integer);
public
class function FromBytes(const ABytes: TBytes): TWords; static;
function High: Integer;
function Low: Integer;
function ToBytes: TBytes;
property Length: Integer read get_Length write set_Length;
end;
implementation
Const
GreaterThanValue = 1;
LessThanValue = -1;
EqualsValue = 0;
{ TBytesHelper }
function TBytesHelper.Compare(const ARight: TBytes): Integer;
var
lCount: Integer;
begin
if Length > ARight.Length then
Exit(GreaterThanValue);
if Length < ARight.Length then
Exit(LessThanValue);
Result := EqualsValue;
for lCount := Low to High do
begin
if Self[lCount] > ARight[lCount] then
Exit(GreaterThanValue);
if Self[lCount] < ARight[lCount] then
Exit(LessThanValue);
end;
end;
function TBytesHelper.get_Length: Integer;
begin
Result := System.Length(Self);
end;
function TBytesHelper.High: Integer;
begin
Result := System.High(Self);
end;
function TBytesHelper.Low: Integer;
begin
Result := System.Low(Self);
end;
procedure TBytesHelper.set_Length(const AValue: Integer);
begin
System.SetLength(Self, AValue);
end;
function TBytesHelper.SubBytes(const AStartIndex: Integer): TBytes;
begin
Result := System.Copy(Self, AStartIndex, Length);
end;
function TBytesHelper.SubBytes(const AStartIndex, ALength: Integer): TBytes;
begin
Result := System.Copy(Self, AStartIndex, ALength);
end;
function WordFromBytes(const ALow, AHigh: Byte): Word;
const
cMask: Byte = $FF;
cBitPerByte = 8;
begin
Result := ALow + (AHigh and (cMask shl cBitPerByte));
end;
Type
TWordBytes = Record
aLow, aHigh: Byte;
end;
Function WordToBytes(aValue : Word) : TWordBytes;
const
cMask: Byte = $FF;
cBitPerByte = 8;
begin
Result.aLow := aValue and cMask;
Result.aHigh := aValue and (cMask shl cBitPerByte);
end;
class function TWordDynArrayHelper.FromBytes(const ABytes: TBytes): TWords;
const
cBytesPerWord = 2;
var
lCount: Integer;
lLow: Byte;
lHigh: Byte;
begin
lCount := ABytes.Length;
if Odd(lCount) then
Inc(lCount);
Result.Length := lCount div cBytesPerWord;
lCount := ABytes.Low;
while lCount <= ABytes.High do
begin
lLow := ABytes[lCount];
if lCount + 1 <= ABytes.High then
lHigh := ABytes[lCount + 1]
else
lHigh := 0;
Result[lCount div cBytesPerWord] := WordFromBytes(lLow, lHigh);
Inc(lCount, cBytesPerWord);
end;
end;
function TWordDynArrayHelper.get_Length: Integer;
begin
Result := System.Length(Self);
end;
function TWordDynArrayHelper.High: Integer;
begin
Result := System.High(Self);
end;
function TWordDynArrayHelper.Low: Integer;
begin
Result := System.Low(Self);
end;
procedure TWordDynArrayHelper.set_Length(const AValue: Integer);
begin
System.SetLength(Self, AValue);
end;
function TWordDynArrayHelper.ToBytes: TBytes;
const
cBytesPerWord = 2;
var
lCount: Integer;
lNewIndex: Integer;
aBytes : TWordBytes;
begin
Result.Length := Length * cBytesPerWord;
for lCount := Low to High do
begin
aBytes:=WordToBytes(Self[lCount]);
lNewIndex := lCount * cBytesPerWord;
Result[lNewIndex] := aBytes.aLow;
Result[lNewIndex + 1] := aBytes.aHigh;
end;
end;
end.