Browse Source

* Start of array utils

michael 4 years ago
parent
commit
82ca0ecd8e
1 changed files with 194 additions and 0 deletions
  1. 194 0
      packages/rtl/arrayutils.pas

+ 194 - 0
packages/rtl/arrayutils.pas

@@ -0,0 +1,194 @@
+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.
+