arrayutils.pas 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. unit arrayutils;
  2. {$mode objfpc}
  3. {$modeswitch typehelpers}
  4. interface
  5. uses
  6. Types, SysUtils;
  7. Type
  8. TBytesHelper = type helper for TBytes
  9. strict private
  10. function get_Length: Integer;
  11. procedure set_Length(const AValue: Integer);
  12. public
  13. function Compare(const ARight: TBytes): Integer;
  14. function High: Integer;
  15. function Low: Integer;
  16. function SubBytes(const AStartIndex: Integer): TBytes; overload; inline;
  17. function SubBytes(const AStartIndex, ALength: Integer): TBytes; overload; inline;
  18. property Length: Integer read get_Length write set_Length;
  19. end;
  20. TWords = TWordDynArray;
  21. TWordDynArrayHelper = type helper for TWordDynArray
  22. private
  23. function get_Length: Integer;
  24. procedure set_Length(const AValue: Integer);
  25. public
  26. class function FromBytes(const ABytes: TBytes): TWords; static;
  27. function High: Integer;
  28. function Low: Integer;
  29. function ToBytes: TBytes;
  30. property Length: Integer read get_Length write set_Length;
  31. end;
  32. implementation
  33. Const
  34. GreaterThanValue = 1;
  35. LessThanValue = -1;
  36. EqualsValue = 0;
  37. { TBytesHelper }
  38. function TBytesHelper.Compare(const ARight: TBytes): Integer;
  39. var
  40. lCount: Integer;
  41. begin
  42. if Length > ARight.Length then
  43. Exit(GreaterThanValue);
  44. if Length < ARight.Length then
  45. Exit(LessThanValue);
  46. Result := EqualsValue;
  47. for lCount := Low to High do
  48. begin
  49. if Self[lCount] > ARight[lCount] then
  50. Exit(GreaterThanValue);
  51. if Self[lCount] < ARight[lCount] then
  52. Exit(LessThanValue);
  53. end;
  54. end;
  55. function TBytesHelper.get_Length: Integer;
  56. begin
  57. Result := System.Length(Self);
  58. end;
  59. function TBytesHelper.High: Integer;
  60. begin
  61. Result := System.High(Self);
  62. end;
  63. function TBytesHelper.Low: Integer;
  64. begin
  65. Result := System.Low(Self);
  66. end;
  67. procedure TBytesHelper.set_Length(const AValue: Integer);
  68. begin
  69. System.SetLength(Self, AValue);
  70. end;
  71. function TBytesHelper.SubBytes(const AStartIndex: Integer): TBytes;
  72. begin
  73. Result := System.Copy(Self, AStartIndex, Length);
  74. end;
  75. function TBytesHelper.SubBytes(const AStartIndex, ALength: Integer): TBytes;
  76. begin
  77. Result := System.Copy(Self, AStartIndex, ALength);
  78. end;
  79. function WordFromBytes(const ALow, AHigh: Byte): Word;
  80. const
  81. cMask: Byte = $FF;
  82. cBitPerByte = 8;
  83. begin
  84. Result := ALow + (AHigh and (cMask shl cBitPerByte));
  85. end;
  86. Type
  87. TWordBytes = Record
  88. aLow, aHigh: Byte;
  89. end;
  90. Function WordToBytes(aValue : Word) : TWordBytes;
  91. const
  92. cMask: Byte = $FF;
  93. cBitPerByte = 8;
  94. begin
  95. Result.aLow := aValue and cMask;
  96. Result.aHigh := aValue and (cMask shl cBitPerByte);
  97. end;
  98. class function TWordDynArrayHelper.FromBytes(const ABytes: TBytes): TWords;
  99. const
  100. cBytesPerWord = 2;
  101. var
  102. lCount: Integer;
  103. lLow: Byte;
  104. lHigh: Byte;
  105. begin
  106. lCount := ABytes.Length;
  107. if Odd(lCount) then
  108. Inc(lCount);
  109. Result.Length := lCount div cBytesPerWord;
  110. lCount := ABytes.Low;
  111. while lCount <= ABytes.High do
  112. begin
  113. lLow := ABytes[lCount];
  114. if lCount + 1 <= ABytes.High then
  115. lHigh := ABytes[lCount + 1]
  116. else
  117. lHigh := 0;
  118. Result[lCount div cBytesPerWord] := WordFromBytes(lLow, lHigh);
  119. Inc(lCount, cBytesPerWord);
  120. end;
  121. end;
  122. function TWordDynArrayHelper.get_Length: Integer;
  123. begin
  124. Result := System.Length(Self);
  125. end;
  126. function TWordDynArrayHelper.High: Integer;
  127. begin
  128. Result := System.High(Self);
  129. end;
  130. function TWordDynArrayHelper.Low: Integer;
  131. begin
  132. Result := System.Low(Self);
  133. end;
  134. procedure TWordDynArrayHelper.set_Length(const AValue: Integer);
  135. begin
  136. System.SetLength(Self, AValue);
  137. end;
  138. function TWordDynArrayHelper.ToBytes: TBytes;
  139. const
  140. cBytesPerWord = 2;
  141. var
  142. lCount: Integer;
  143. lNewIndex: Integer;
  144. aBytes : TWordBytes;
  145. begin
  146. Result.Length := Length * cBytesPerWord;
  147. for lCount := Low to High do
  148. begin
  149. aBytes:=WordToBytes(Self[lCount]);
  150. lNewIndex := lCount * cBytesPerWord;
  151. Result[lNewIndex] := aBytes.aLow;
  152. Result[lNewIndex + 1] := aBytes.aHigh;
  153. end;
  154. end;
  155. end.