source: Generics/NativeGenerics/Generic/GenericList.pas

Last change on this file was 496, checked in by chronos, 7 years ago
  • Modified: New native generics classes working under FPC 3.0 transformed from TemplateGenerics package.
File size: 21.4 KB
Line 
1unit GenericList;
2
3{$mode delphi}
4
5interface
6
7uses
8 Classes, SysUtils;
9
10type
11 // TGList implemented using templates
12 // - item operations (Add, Insert, ReplaceArray, Get, Set, IndexOf,
13 // Extract, Delete, Exchange)
14 // - item range operations (DeleteItems, InsertItems, ReplaceItems,
15 // Move, Fill)
16 // - other TGList operations (AddList, InsertList,
17 // ReplaceList, GetList, IndexOfList)
18 // - dynamic array operations (AddArray, InsertArray,
19 // ReplaceArray, GetArray, IndexOfArray)
20 // - all items operations (Clear, Reverse, Sort)
21
22 //TGAbstractList = class
23
24 //end;
25
26 TGList<T> = class//(TGAbstractList)
27 public
28 type
29 PItem = ^T;
30 TSortCompare = function(Item1, Item2: T): Integer of object;
31 TToStringConverter = function(Item: T): string;
32 TFromStringConverter = function(Text: string): T;
33 TItemArray = array of T;
34 private
35 FItems: array of T;
36 FCount: Integer;
37 FUpdateCount: Integer;
38 FOnUpdate: TNotifyEvent;
39 function Get(Index: Integer): T;
40 function GetCapacity: Integer;
41 function GetLast: T;
42 function GetFirst: T;
43 procedure SetCapacity(const AValue: Integer);
44 procedure SetCapacityOptimized(const NewCapacity: Integer);
45 procedure SetLast(AValue: T);
46 procedure SetFirst(AValue: T);
47 procedure QuickSort(L, R : Integer; Compare: TSortCompare);
48 procedure DoUpdate;
49 protected
50 procedure Put(Index: Integer; const AValue: T); virtual;
51 procedure SetCount(const AValue: Integer); virtual;
52 public
53 function CompareMem(P1, P2: Pointer; Length: cardinal): Boolean; inline;
54 function Add(Item: T): Integer;
55 procedure AddArray(Values: array of T);
56 procedure AddList(List: TGList<T>);
57 procedure AddListPart(List: TGList<T>; ItemIndex, ItemCount: Integer);
58 procedure Assign(Source: TGList<T>); virtual;
59 constructor Create; virtual;
60 procedure Clear; virtual;
61 procedure Delete(Index: Integer); virtual;
62 procedure DeleteItems(Index, Count: Integer);
63 function EqualTo(List: TGList<T>): Boolean;
64 procedure Exchange(Index1, Index2: Integer);
65 procedure Explode(Text, Separator: string; Converter: TFromStringConverter; SlicesCount: Integer = -1);
66 function Extract(Item: T): T;
67 property First: T read GetFirst write SetFirst;
68 procedure Fill(Start, Count: Integer; Value: T);
69 function GetArray(Index, ACount: Integer): TItemArray;
70 procedure GetList(List: TGList<T>; Index, ACount: Integer);
71 procedure GetBuffer(Index: Integer; var Buffer; Count: Integer);
72 function Implode(Separator: string; Converter: TToStringConverter): string;
73 function IndexOf(Item: T; Start: Integer = 0): Integer; virtual;
74 function IndexOfList(List: TGList<T>; Start: Integer = 0): Integer;
75 function IndexOfArray(Values: array of T; Start: Integer = 0): Integer;
76 procedure Insert(Index: Integer; Item: T);
77 procedure InsertList(Index: Integer; List: TGList<T>);
78 procedure InsertArray(Index: Integer; Values: array of T);
79 procedure InsertCount(Index: Integer; ACount: Integer);
80 procedure Move(CurIndex, NewIndex: Integer);
81 procedure MoveItems(CurIndex, NewIndex, Count: Integer);
82 function Remove(Item: T): Integer;
83 procedure Reverse;
84 procedure ReplaceArray(Index: Integer; Values: array of T);
85 procedure ReplaceList(Index: Integer; Source: TGList<T>);
86 procedure ReplaceListPart(Index: Integer; Source: TGList<T>;
87 SourceIndex, SourceCount: Integer);
88 procedure ReplaceBuffer(Index: Integer; var Buffer; Count: Integer);
89 procedure Sort(Compare: TSortCompare);
90 procedure SetArray(Values: array of T);
91 procedure BeginUpdate;
92 procedure EndUpdate;
93 procedure Update;
94 property Count: Integer read FCount write SetCount;
95 property Capacity: Integer read GetCapacity write SetCapacity;
96 property Items[Index: Integer]: T read Get write Put; default;
97 property Last: T read GetLast write SetLast;
98 property OnUpdate: TNotifyEvent read FOnUpdate write FOnUpdate;
99 end;
100
101 TGListObject<T> = class(TGList<T>)
102 protected
103 procedure Put(Index: Integer; const AValue: T); override;
104 procedure SetCount(const AValue: Integer); override;
105 public
106 OwnsObjects: Boolean;
107 function AddNew(NewObject: T = nil): T;
108 function InsertNew(Index: Integer; NewObject: T = nil): T;
109 procedure Delete(Index: Integer); override;
110 procedure Assign(Source: TGList<T>); override;
111 constructor Create; override;
112 destructor Destroy; override;
113 end;
114
115 TGListString<T> = class(TGList<T>)
116 public
117 procedure Delete(Index: Integer); override;
118 procedure Clear; override;
119 procedure Assign(Source: TGList<T>); override;
120 function IndexOf(Item: T; Start: Integer = 0): Integer; override;
121 constructor Create; override;
122 destructor Destroy; override;
123 end;
124
125 TGAbstractList<T> = class
126 private
127 FOnUpdate: TNotifyEvent;
128 function Get(const Index: Integer): T; virtual; abstract;
129 function GetCapacity: Integer; virtual; abstract;
130 function GetCount: Integer; virtual; abstract;
131 function GetFirst: T; virtual; abstract;
132 function GetLast: T; virtual; abstract;
133 procedure Put(const Index: Integer; const AValue: T); virtual; abstract;
134 procedure SetCapacity(const AValue: Integer); virtual; abstract;
135 procedure SetCount(const AValue: Integer); virtual; abstract;
136 procedure SetFirst(const AValue: T); virtual; abstract;
137 procedure SetLast(const AValue: T); virtual; abstract;
138 public
139 type
140 PItem = ^T;
141 property Count: Integer read GetCount write SetCount;
142 property Capacity: Integer read GetCapacity write SetCapacity;
143 property Items[Index: Integer]: T read Get write Put; default;
144 property First: T read GetFirst write SetFirst;
145 property Last: T read GetLast write SetLast;
146 property OnUpdate: TNotifyEvent read FOnUpdate write FOnUpdate;
147 end;
148
149
150implementation
151
152uses
153 RtlConsts;
154
155
156{ TGList }
157
158constructor TGList<T>.Create;
159begin
160 FCount := 0;
161 FUpdateCount := 0;
162end;
163
164procedure TGList<T>.GetBuffer(Index: Integer; var Buffer; Count: Integer);
165var
166 P: PItem;
167 I: Integer;
168begin
169 if (Index + Count) > FCount then
170 raise EListError.CreateFmt(SListIndexError, [Index + Count]);
171 P := PItem(@Buffer);
172 I := 0;
173 while I < Count do begin
174 P^ := Items[Index + I];
175 Inc(P, 1);
176 I := I + 1;
177 end;
178end;
179
180procedure TGList<T>.ReplaceBuffer(Index: Integer; var Buffer; Count: Integer);
181var
182 P: PItem;
183 I: Integer;
184begin
185 if (Index + Count) > FCount then
186 raise EListError.CreateFmt(SListIndexError, [Index + Count]);
187 P := PItem(@Buffer);
188 I := 0;
189 while I < Count do begin
190 Items[Index + I] := P^;
191 Inc(P, 1);
192 I := I + 1;
193 end;
194end;
195
196procedure TGList<T>.ReplaceArray(Index: Integer; Values: array of T);
197var
198 I: Integer;
199begin
200 I := 0;
201 while I < Length(Values) do begin
202 Items[Index + I] := Values[I];
203 I := I + 1;
204 end;
205 Update;
206end;
207
208procedure TGList<T>.ReplaceList(Index: Integer; Source: TGList<T>);
209var
210 I: Integer;
211begin
212 I := 0;
213 while I < Source.Count do begin
214 Items[Index + I] := Source[I];
215 I := I + 1;
216 end;
217 Update;
218end;
219
220procedure TGList<T>.ReplaceListPart(Index: Integer; Source: TGList<T>;
221 SourceIndex, SourceCount: Integer);
222var
223 I: Integer;
224begin
225 I := 0;
226 while I < SourceCount do begin
227 Items[Index + I] := Source[SourceIndex + I];
228 I := I + 1;
229 end;
230 Update;
231end;
232
233function TGList<T>.GetCapacity: Integer;
234begin
235 Result := Length(FItems);
236end;
237
238procedure TGList<T>.SetCapacity(const AValue: Integer);
239begin
240 if (AValue < FCount) then
241 raise EListError.CreateFmt(SListCapacityError, [AValue]);
242 SetLength(FItems, AValue);
243end;
244
245procedure TGList<T>.SetCapacityOptimized(const NewCapacity: Integer);
246var
247 IncSize: Integer;
248begin
249 if NewCapacity > Capacity then begin
250 IncSize := NewCapacity - Capacity;
251 // Expand
252 if IncSize = 1 then begin
253 IncSize := 4;
254 if Capacity > 3 then IncSize := IncSize + 4;
255 if Capacity > 8 then IncSize := IncSize + 8;
256 if Capacity > 63 then IncSize := IncSize + Capacity shr 2; // Grow by one quarter
257 end;
258 Capacity := Capacity + IncSize;
259 end else
260 if NewCapacity < Capacity then begin
261 // Contract
262 if (Capacity > 256) and (FCount < Capacity shr 2) then
263 begin
264 Capacity := Capacity shr 1;
265 end;
266 end;
267end;
268
269function TGList<T>.Get(Index: Integer): T;
270begin
271 if (Index < 0) or (Index >= Count) then
272 raise EListError.CreateFmt(SListIndexError, [Index]);
273 Result := FItems[Index];
274end;
275
276procedure TGList<T>.Put(Index: Integer; const AValue: T);
277begin
278 if (Index < 0) or (Index >= Count) then
279 raise EListError.CreateFmt(SListIndexError, [Index]);
280 FItems[Index] := AValue;
281end;
282
283procedure TGList<T>.SetCount(const AValue: Integer);
284begin
285 if (AValue < 0) then
286 raise EListError.CreateFmt(SListCountError, [AValue]);
287 if AValue > Capacity then SetCapacityOptimized(AValue); // Before FCount change
288 FCount := AValue;
289 if AValue < Capacity then SetCapacityOptimized(AValue); // After FCount change
290end;
291
292function TGList<T>.GetArray(Index, ACount: Integer): TItemArray;
293var
294 I: Integer;
295begin
296 SetLength(Result, ACount);
297 I := 0;
298 while I < Count do begin
299 Result[I] := FItems[Index + I];
300 I := I + 1;
301 end;
302end;
303
304procedure TGList<T>.GetList(List: TGList<T>; Index, ACount: Integer);
305begin
306 List.Clear;
307 List.AddListPart(Self, Index, ACount);
308end;
309
310procedure TGList<T>.QuickSort(L, R: Integer; Compare: TSortCompare);
311var
312 I, J: Integer;
313 P, Q: T;
314begin
315 repeat
316 I := L;
317 J := R;
318 P := FItems[(L + R) div 2];
319 repeat
320 while Compare(P, FItems[I]) > 0 do
321 I := I + 1;
322 while Compare(P, FItems[J]) < 0 do
323 J := J - 1;
324 if I <= J then
325 begin
326 Q := FItems[I];
327 FItems[I] := FItems[J];
328 FItems[J] := Q;
329 I := I + 1;
330 J := J - 1;
331 end;
332 until I > J;
333 if L < J then
334 QuickSort(L, J, Compare);
335 L := I;
336 until I >= R;
337end;
338
339procedure TGList<T>.Assign(Source: TGList<T>);
340var
341 I: Integer;
342begin
343 Count := Source.Count;
344 I := 0;
345 while I < Count do begin
346 FItems[I] := Source[I];
347 I := I + 1;
348 end;
349 Update;
350end;
351
352function TGList<T>.Extract(Item: T): T;
353var
354 I: Integer;
355begin
356 I := IndexOf(Item);
357 if I >= 0 then begin
358 Result := Item;
359 Delete(I);
360 end else
361 raise EListError.CreateFmt(SListIndexError, [0]);
362end;
363
364function TGList<T>.CompareMem(P1, P2: Pointer; Length: cardinal): Boolean;
365var
366 I: Cardinal;
367begin
368 Result := True;
369 I := 0;
370 if (P1) <> (P2) then
371 while Result and (I < Length) do
372 begin
373 Result := PByte(P1)^ = PByte(P2)^;
374 Inc(I);
375 Inc(pchar(P1));
376 Inc(pchar(P2));
377 end;
378end;
379
380function TGList<T>.IndexOf(Item: T; Start: Integer): Integer;
381var
382 List: PItem;
383begin
384 Result := 0;
385 List := @(FItems[Start]);
386 while (Result < FCount) and
387// not CompareMem(@FItems[Result], @Item, SizeOf(T)) do
388 (CompareByte(List^, Item, SizeOf(T)) <> 0) do begin
389 Inc(List);
390 Inc(Result);
391 end;
392 if Result = FCount then Result := -1;
393end;
394
395procedure TGList<T>.Insert(Index: Integer; Item: T);
396begin
397 if (Index < 0) or (Index > FCount) then
398 raise EListError.CreateFmt(SListIndexError, [Index]);
399 try
400 BeginUpdate;
401 InsertCount(Index, 1);
402 FItems[Index] := Item;
403 finally
404 EndUpdate;
405 end;
406end;
407
408procedure TGList<T>.InsertList(Index: Integer; List: TGList<T>);
409begin
410 if (Index < 0) or (Index > FCount) then
411 raise EListError.CreateFmt(SListIndexError, [Index]);
412 InsertCount(Index, List.Count);
413 ReplaceList(Index, List);
414end;
415
416procedure TGList<T>.InsertArray(Index: Integer; Values: array of T);
417begin
418 if (Index < 0) or (Index > FCount) then
419 raise EListError.CreateFmt(SListIndexError, [Index]);
420 InsertCount(Index, Length(Values));
421 ReplaceArray(Index, Values);
422end;
423
424procedure TGList<T>.InsertCount(Index: Integer; ACount: Integer);
425begin
426 if (Index < 0) or (Index > FCount) then
427 raise EListError.CreateFmt(SListIndexError, [Index]);
428 Count := Count + ACount;
429 if Index < FCount then
430 System.Move(FItems[Index], FItems[Index + ACount], (FCount - ACount - Index) * SizeOf(T));
431 Update;
432end;
433
434function TGList<T>.IndexOfList(List: TGList<T>; Start: Integer): Integer;
435var
436 I: Integer;
437begin
438 if List.Count > 0 then begin
439 Result := IndexOf(List[0], Start);
440 if Result <> -1 then begin
441 I := 1;
442 while I < List.Count do begin
443 if not CompareMem(Addr(FItems[Result + I]), Addr(List.FItems[I]), SizeOf(T)) then begin
444 Result := -1;
445 Break;
446 end;
447 I := I + 1;
448 end;
449 end;
450 end else Result := -1;
451end;
452
453function TGList<T>.IndexOfArray(Values: array of T; Start: Integer): Integer;
454var
455 I: Integer;
456begin
457 if Length(Values) > 0 then begin
458 Result := IndexOf(Values[0], Start);
459 if Result <> -1 then begin
460 I := 1;
461 while I < Length(Values) do begin
462 if not CompareMem(Addr(FItems[Result + I]), Addr(Values[I]), SizeOf(T)) then begin
463 Result := -1;
464 Break;
465 end;
466 I := I + 1;
467 end;
468 end;
469 end else Result := -1;
470end;
471
472function TGList<T>.GetLast: T;
473begin
474 if FCount = 0 then
475 raise EListError.CreateFmt(SListIndexError, [0])
476 else
477 Result := FItems[FCount - 1];
478end;
479
480procedure TGList<T>.SetLast(AValue: T);
481begin
482 if FCount = 0 then
483 raise EListError.CreateFmt(SListIndexError, [0])
484 else
485 FItems[FCount - 1] := AValue;
486end;
487
488function TGList<T>.GetFirst: T;
489begin
490 if FCount = 0 then
491 raise EListError.CreateFmt(SListIndexError, [0])
492 else
493 Result := FItems[0];
494end;
495
496procedure TGList<T>.SetFirst(AValue: T);
497begin
498 if FCount = 0 then
499 raise EListError.CreateFmt(SListIndexError, [0])
500 else
501 FItems[0] := AValue;
502end;
503
504procedure TGList<T>.Move(CurIndex, NewIndex: Integer);
505var
506 Temp: T;
507begin
508 if ((CurIndex < 0) or (CurIndex > Count - 1)) then
509 raise EListError.CreateFmt(SListIndexError, [CurIndex]);
510 if ((NewIndex < 0) or (NewIndex > Count -1)) then
511 raise EListError.CreateFmt(SlistIndexError, [NewIndex]);
512 Temp := FItems[CurIndex];
513 if NewIndex > CurIndex then begin
514 System.Move(FItems[CurIndex + 1], FItems[CurIndex], (NewIndex - CurIndex) * SizeOf(T));
515 end else
516 if NewIndex < CurIndex then begin
517 System.Move(FItems[NewIndex], FItems[NewIndex + 1], (CurIndex - NewIndex) * SizeOf(T));
518 end;
519 FItems[NewIndex] := Temp;
520 //Delete(CurIndex);
521 //Insert(NewIndex, Temp);
522 Update;
523end;
524
525procedure TGList<T>.MoveItems(CurIndex, NewIndex, Count: Integer);
526var
527 S: Integer;
528 D: Integer;
529begin
530 if CurIndex < NewIndex then begin
531 S := CurIndex + Count - 1;
532 D := NewIndex + Count - 1;
533 while S >= CurIndex do begin
534 Move(S, D);
535 S := S - 1;
536 D := D - 1;
537 end;
538 end else
539 if CurIndex > NewIndex then begin
540 S := CurIndex;
541 D := NewIndex;
542 while S < (CurIndex + Count) do begin
543 Move(S, D);
544 S := S + 1;
545 D := D + 1;
546 end;
547 end;
548 Update;
549end;
550
551function TGList<T>.Remove(Item: T): Integer;
552begin
553 Result := IndexOf(Item);
554 if Result <> -1 then
555 Delete(Result)
556 else raise Exception.CreateFmt(SItemNotFound, [0]);
557end;
558
559function TGList<T>.EqualTo(List: TGList<T>): Boolean;
560var
561 I: Integer;
562begin
563 Result := Count = List.Count;
564 if Result then begin
565 I := 0;
566 while I < Count do begin
567 if not CompareMem(Addr(FItems[I]), Addr(List.FItems[I]), SizeOf(T)) then begin
568 Result := False;
569 Break;
570 end;
571 I := I + 1;
572 end;
573 end;
574end;
575
576procedure TGList<T>.Reverse;
577var
578 I: Integer;
579begin
580 I := 0;
581 while I < (Count div 2) do begin
582 Exchange(I, Count - 1 - I);
583 I := I + 1;
584 end;
585 Update;
586end;
587
588procedure TGList<T>.Sort(Compare: TSortCompare);
589begin
590 if FCount > 1 then
591 QuickSort(0, FCount - 1, Compare);
592 Update;
593end;
594
595procedure TGList<T>.AddArray(Values: array of T);
596var
597 I: Integer;
598begin
599 I := 0;
600 while I <= High(Values) do begin
601 Add(Values[I]);
602 I := I + 1;
603 end;
604 Update;
605end;
606
607procedure TGList<T>.SetArray(Values: array of T);
608var
609 I: Integer;
610begin
611 Clear;
612 I := 0;
613 while I <= High(Values) do begin
614 Add(Values[I]);
615 I := I + 1;
616 end;
617end;
618
619procedure TGList<T>.BeginUpdate;
620begin
621 Inc(FUpdateCount);
622end;
623
624procedure TGList<T>.EndUpdate;
625begin
626 if FUpdateCount > 0 then Dec(FUpdateCount);
627 if FUpdateCount = 0 then DoUpdate;
628end;
629
630procedure TGList<T>.DoUpdate;
631begin
632 if Assigned(FOnUpdate) then FOnUpdate(Self);
633end;
634
635procedure TGList<T>.Update;
636begin
637 if FUpdateCount = 0 then DoUpdate;
638end;
639
640function TGList<T>.Implode(Separator: string; Converter: TToStringConverter): string;
641var
642 I: Integer;
643begin
644 Result := '';
645 I := 0;
646 while I < Count do begin
647 Result := Result + Converter(FItems[I]);
648 if I < (Count - 1) then
649 Result := Result + Separator;
650 I := I + 1;
651 end;
652end;
653
654procedure TGList<T>.Explode(Text, Separator: string; Converter: TFromStringConverter; SlicesCount: Integer = -1);
655begin
656 Clear;
657 while (Pos(Separator, Text) > 0) and
658 ((Count < (SlicesCount - 1)) or (SlicesCount = -1)) do begin
659 Add(Converter(Copy(Text, 1, Pos(Separator, Text) - 1)));
660 System.Delete(Text, 1, Pos(Separator, Text) + Length(Separator) - 1);
661 end;
662 Add(Converter(Text));
663end;
664
665function TGList<T>.Add(Item: T): Integer;
666begin
667 Count := Count + 1;
668 Result := FCount - 1;
669 FItems[Result] := Item;
670 Update;
671end;
672
673procedure TGList<T>.AddList(List: TGList<T>);
674var
675 I: Integer;
676 J: Integer;
677begin
678 I := Count;
679 J := 0;
680 Count := Count + List.Count;
681 while I < Count do begin
682 Items[I] := List[J];
683 I := I + 1;
684 J := J + 1;
685 end;
686 Update;
687end;
688
689procedure TGList<T>.AddListPart(List: TGList<T>; ItemIndex, ItemCount: Integer);
690var
691 I: Integer;
692 J: Integer;
693begin
694 I := Count;
695 J := ItemIndex;
696 Count := Count + ItemCount;
697 while I < Count do begin
698 Items[I] := List[J];
699 I := I + 1;
700 J := J + 1;
701 end;
702 Update;
703end;
704
705procedure TGList<T>.Clear;
706begin
707 Count := 0;
708 Capacity := 0;
709end;
710
711procedure TGList<T>.Delete(Index: Integer);
712begin
713 if (Index < 0) or (Index >= FCount) then
714 raise EListError.CreateFmt(SListIndexError, [Index]);
715 FCount := FCount - 1;
716 System.Move(FItems[Index + 1], FItems[Index], (FCount - Index) * SizeOf(T));
717 SetCapacityOptimized(Capacity - 1);
718 Update;
719end;
720
721procedure TGList<T>.DeleteItems(Index, Count: Integer);
722var
723 I: Integer;
724begin
725 I := Index;
726 while I < (Index + Count) do begin
727 Delete(Index);
728 I := I + 1;
729 end;
730 Update;
731end;
732
733procedure TGList<T>.Fill(Start, Count: Integer; Value: T);
734var
735 I: Integer;
736begin
737 I := Start;
738 while I < Count do begin
739 FItems[I] := Value;
740 I := I + 1;
741 end;
742 Update;
743end;
744
745procedure TGList<T>.Exchange(Index1, Index2: Integer);
746var
747 Temp: T;
748begin
749 if ((Index1 >= FCount) or (Index1 < 0)) then
750 raise EListError.CreateFmt(SListIndexError, [Index1]);
751 if ((Index2 >= FCount) or (Index2 < 0)) then
752 raise EListError.CreateFmt(SListIndexError, [Index2]);
753 Temp := FItems[Index1];
754 FItems[Index1] := FItems[Index2];
755 FItems[Index2] := Temp;
756 Update;
757end;
758
759procedure TGListString<T>.Assign(Source: TGList<T>);
760begin
761 Clear;
762 inherited;
763end;
764
765procedure TGListString<T>.Delete(Index: Integer);
766begin
767 FItems[Index] := '';
768 inherited Delete(Index);
769end;
770
771procedure TGListString<T>.Clear;
772var
773 I: Integer;
774begin
775 I := 0;
776 while I < Count do begin
777 FItems[I] := '';
778 I := I + 1;
779 end;
780 inherited Clear;
781end;
782
783function TGListString<T>.IndexOf(Item: T; Start: Integer): Integer;
784begin
785 Result := Start;
786 while (Result < Count) and
787 (CompareStr(FItems[Result], Item) <> 0) do
788 Result := Result + 1;
789 if Result = FCount then Result := -1;
790end;
791
792constructor TGListString<T>.Create;
793begin
794 inherited;
795end;
796
797destructor TGListString<T>.Destroy;
798begin
799 Clear;
800 inherited Destroy;
801end;
802
803
804{ TGListObject }
805
806function TGListObject<T>.AddNew(NewObject: T = nil): T;
807begin
808 if Assigned(NewObject) then Result := NewObject
809 else Result := T.Create;
810 Add(Result);
811end;
812
813function TGListObject<T>.InsertNew(Index: Integer;
814 NewObject: T = nil): T;
815begin
816 if Assigned(NewObject) then Result := NewObject
817 else Result := T.Create;
818 Insert(Index, Result);
819end;
820
821procedure TGListObject<T>.Assign(Source: TGList<T>);
822begin
823 Clear;
824 OwnsObjects := False;
825 inherited;
826end;
827
828procedure TGListObject<T>.Put(Index: Integer; const AValue: T);
829begin
830 if OwnsObjects and (FItems[Index] <> AValue) then FItems[Index].Free;
831 inherited Put(Index, AValue);
832end;
833
834procedure TGListObject<T>.Delete(Index: Integer);
835begin
836 if OwnsObjects then FItems[Index].Free;
837 inherited Delete(Index);
838end;
839
840procedure TGListObject<T>.SetCount(const AValue: Integer);
841var
842 I: Integer;
843begin
844 if OwnsObjects then begin
845 I := FCount - 1;
846 while I >= AValue do begin
847 FItems[I].Free;
848 I := I - 1;
849 end;
850 end;
851 I := FCount;
852 inherited;
853 // Nil newly allocated items
854 while I < AValue do begin
855 FItems[I] := nil;
856 I := I + 1;
857 end;
858end;
859
860constructor TGListObject<T>.Create;
861begin
862 inherited;
863 OwnsObjects := True;
864end;
865
866destructor TGListObject<T>.Destroy;
867begin
868 Clear;
869 inherited;
870end;
871
872
873end.
Note: See TracBrowser for help on using the repository browser.