Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.

225 righe
7.8 KiB

  1. unit uutlListBase;
  2. {$mode objfpc}{$H+}
  3. interface
  4. uses
  5. Classes, SysUtils,
  6. uutlArrayContainer, uutlInterfaces, uutlEnumerator;
  7. type
  8. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  9. generic TutlListBase<T> = class(
  10. specialize TutlArrayContainer<T>
  11. , specialize IEnumerable<T>
  12. , specialize IutlEnumerable<T>)
  13. public type
  14. IEnumerator = specialize IEnumerator<T>;
  15. IutlEnumerator = specialize IutlEnumerator<T>;
  16. private type
  17. TEnumerator = class(
  18. specialize TutlMemoryEnumerator<T>
  19. , IEnumerator
  20. , IutlEnumerator)
  21. private
  22. fOwner: TutlListBase;
  23. protected { IEnumerator }
  24. procedure InternalReset; override;
  25. {$IFDEF UTL_ENUMERATORS}
  26. public { IutlEnumerator }
  27. function Reverse: IutlEnumerator; override;
  28. {$ENDIF}
  29. public
  30. constructor Create(const aOwner: TutlListBase; const aReversed: Boolean); reintroduce;
  31. end;
  32. strict private
  33. fCount: Integer;
  34. protected
  35. function GetCount: Integer; override;
  36. procedure SetCount(const aValue: Integer); override;
  37. function GetItem (const aIndex: Integer): T; virtual;
  38. procedure SetItem (const aIndex: Integer; aValue: T); virtual;
  39. procedure InsertIntern(const aIndex: Integer; constref aValue: T); virtual;
  40. procedure DeleteIntern(const aIndex: Integer; const aFreeItem: Boolean); virtual;
  41. public { IEnumerable }
  42. function GetEnumerator: IEnumerator;
  43. public { IutlEnumerable }
  44. function GetUtlEnumerator: IutlEnumerator;
  45. public
  46. property Count;
  47. property IsEmpty;
  48. property Capacity;
  49. property CanShrink;
  50. property CanExpand;
  51. property OwnsItems;
  52. procedure Clear; virtual;
  53. procedure ShrinkToFit;
  54. constructor Create(const aOwnsItems: Boolean);
  55. destructor Destroy; override;
  56. end;
  57. implementation
  58. uses
  59. uutlCommon;
  60. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  61. //TutlListBase.TEnumerator//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  62. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  63. procedure TutlListBase.TEnumerator.InternalReset;
  64. begin
  65. First := 0;
  66. Last := fOwner.Count-1;
  67. if (Last >= First)
  68. then Memory := fOwner.GetInternalItem(0)
  69. else Memory := nil;
  70. inherited InternalReset;
  71. end;
  72. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  73. {$IFDEF UTL_ENUMERATORS}
  74. function TutlListBase.TEnumerator.Reverse: IutlEnumerator;
  75. begin
  76. result := TEnumerator.Create(fOwner, not Reversed);
  77. end;
  78. {$ENDIF}
  79. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  80. constructor TutlListBase.TEnumerator.Create(const aOwner: TutlListBase; const aReversed: Boolean);
  81. begin
  82. if not Assigned(aOwner) then
  83. raise EArgumentNilException.Create('aOwner');
  84. fOwner := aOwner;
  85. inherited Create(nil, aReversed, 0, -1);
  86. end;
  87. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  88. //TutlListBase//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  89. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  90. function TutlListBase.GetCount: Integer;
  91. begin
  92. result := fCount;
  93. end;
  94. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  95. procedure TutlListBase.SetCount(const aValue: Integer);
  96. begin
  97. if (aValue < Capacity) then
  98. Capacity := aValue;
  99. fCount := aValue;
  100. end;
  101. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  102. function TutlListBase.GetItem(const aIndex: Integer): T;
  103. begin
  104. if (aIndex < 0) or (aIndex >= Count) then
  105. raise EOutOfRangeException.Create(aIndex, 0, Count-1);
  106. result := GetInternalItem(aIndex)^;
  107. end;
  108. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  109. procedure TutlListBase.SetItem(const aIndex: Integer; aValue: T);
  110. var
  111. p: PT;
  112. begin
  113. if (aIndex < 0) or (aIndex >= Count) then
  114. raise EOutOfRangeException.Create(aIndex, 0, Count-1);
  115. p := GetInternalItem(aIndex);
  116. Release(p^, true);
  117. p^ := aValue;
  118. end;
  119. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  120. procedure TutlListBase.InsertIntern(const aIndex: Integer; constref aValue: T);
  121. var
  122. p: PT;
  123. begin
  124. if (aIndex < 0) or (aIndex > fCount) then
  125. raise EOutOfRangeException.Create(aIndex, 0, fCount);
  126. if (fCount = Capacity) then
  127. Expand;
  128. p := GetInternalItem(aIndex);
  129. if (aIndex < fCount) then
  130. System.Move(p^, (p+1)^, (fCount - aIndex) * SizeOf(T));
  131. p^ := aValue;
  132. inc(fCount);
  133. end;
  134. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  135. procedure TutlListBase.DeleteIntern(const aIndex: Integer; const aFreeItem: Boolean);
  136. var
  137. p: PT;
  138. begin
  139. if (aIndex < 0) or (aIndex >= fCount) then
  140. raise EOutOfRangeException.Create(aIndex, 0, fCount-1);
  141. dec(fCount);
  142. p := GetInternalItem(aIndex);
  143. Release(p^, aFreeItem);
  144. System.Move((p+1)^, p^, SizeOf(T) * (fCount - aIndex));
  145. if CanShrink and (Capacity > 128) and (fCount < Capacity shr 2) then // only 25% used
  146. SetCapacity(Capacity shr 1); // set to 50% Capacity
  147. FillByte(GetInternalItem(fCount)^, (Capacity-fCount) * SizeOf(T), 0);
  148. end;
  149. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  150. function TutlListBase.GetEnumerator: IEnumerator;
  151. begin
  152. result := TEnumerator.Create(self, false);
  153. end;
  154. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  155. function TutlListBase.GetUtlEnumerator: specialize IutlEnumerator<T>;
  156. begin
  157. result := TEnumerator.Create(self, false);
  158. end;
  159. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  160. procedure TutlListBase.Clear;
  161. begin
  162. while (Count > 0) do begin
  163. dec(fCount);
  164. Release(GetInternalItem(fCount)^, true);
  165. end;
  166. fCount := 0;
  167. if CanShrink then
  168. ShrinkToFit;
  169. end;
  170. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  171. procedure TutlListBase.ShrinkToFit;
  172. begin
  173. Shrink(true);
  174. end;
  175. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  176. constructor TutlListBase.Create(const aOwnsItems: Boolean);
  177. begin
  178. inherited Create(aOwnsItems);
  179. fCount := 0;
  180. end;
  181. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  182. destructor TutlListBase.Destroy;
  183. begin
  184. Clear;
  185. inherited Destroy;
  186. end;
  187. end.