17.10 TCollection

The TCollection object manages a collection of pointers or objects. It also provides a series of methods to manipulate these pointers or objects.

Whether or not objects are used depends on the kind of calls you use. ALl kinds come in 2 flavors, one for objects, one for pointers.

This is the full declaration of the TCollection object:

 TYPE
    TItemList = Array [0..MaxCollectionSize - 1] Of Pointer;
    PItemList = ^TItemList;
 
    TCollection = OBJECT (TObject)
          Items: PItemList;  { Item list pointer }
          Count: Sw_Integer; { Item count }
          Limit: Sw_Integer; { Item limit count }
          Delta: Sw_Integer; { Inc delta size }
       Constructor Init (ALimit, ADelta: Sw_Integer);
       Constructor Load (Var S: TStream);
       Destructor Done; Virtual;
       Function At (Index: Sw_Integer): Pointer;
       Function IndexOf (Item: Pointer): Sw_Integer; Virtual;
       Function GetItem (Var S: TStream): Pointer; Virtual;
       Function LastThat (Test: Pointer): Pointer;
       Function FirstThat (Test: Pointer): Pointer;
       Procedure Pack;
       Procedure FreeAll;
       Procedure DeleteAll;
       Procedure Free (Item: Pointer);
       Procedure Insert (Item: Pointer); Virtual;
       Procedure Delete (Item: Pointer);
       Procedure AtFree (Index: Sw_Integer);
       Procedure FreeItem (Item: Pointer); Virtual;
       Procedure AtDelete (Index: Sw_Integer);
       Procedure ForEach (Action: Pointer);
       Procedure SetLimit (ALimit: Sw_Integer); Virtual;
       Procedure Error (Code, Info: Integer); Virtual;
       Procedure AtPut (Index: Sw_Integer; Item: Pointer);
       Procedure AtInsert (Index: Sw_Integer; Item: Pointer);
       Procedure Store (Var S: TStream);
       Procedure PutItem (Var S: TStream; Item: Pointer); Virtual;
    END;
    PCollection = ^TCollection;

TCollection.Init

Declaration:
Constructor TCollection.Init (ALimit, ADelta: Sw_Integer);
Description:
Init initializes a new instance of a collection. It sets the (initial) maximum number of items in the collection to ALimit. ADelta is the increase size : The number of memory places that will be allocatiod in case ALimit is reached, and another element is added to the collection.
Errors:
None.
See also:
Load (594), Done (595)

For an example, see TCollection.ForEach (606).

TCollection.Load

Declaration:
Constructor TCollection.Load (Var S: TStream);
Description:
Load initializes a new instance of a collection. It reads from stream S the item count, the item limit count, and the increase size. After that, it reads the specified number of items from the stream.
Errors:
Errors returned can be those of GetItem (597).
See also:
Init (593), GetItem (597), Done (595).

Listing: objectex/ex22.pp


Program ex22;

{ Program to demonstrate the TCollection.Load method }

Uses Objects,MyObject; { For TMyObject definition and registration }

Var C : PCollection;
    M : PMyObject;
    I : Longint;
    S : PMemoryStream;

begin
  C:=New(PCollection,Init(100,10));
  For I:=1 to 100 do
    begin
    M:=New(PMyObject,Init);
    M^.SetField(100-I);
    C^.Insert(M);
    end;
  Writeln ('Inserted ',C^.Count,' objects');
  S:=New(PMemorySTream,Init(1000,10));
  C^.Store(S^);
  C^.FreeAll;
  Dispose(C,Done);
  S^.Seek(0);
  C^.Load(S^);
  Writeln ('Read ',C^.Count,' objects from stream.');
  Dispose(S,Done);
  Dispose(C,Done);
end.

TCollection.Done

Declaration:
Destructor TCollection.Done; Virtual;
Description:
Done frees all objects in the collection, and then releases all memory occupied by the instance.
Errors:
None.
See also:
Init (593), FreeAll (600)

For an example, see TCollection.ForEach (606).

TCollection.At

Declaration:
Function TCollection.At (Index: Sw_Integer): Pointer;
Description:
At returns the item at position Index.
Errors:
If Index is less than zero or larger than the number of items in the collection, seeplErrorTCollection.Error is called with coIndexError and Index as arguments, resulting in a run-time error.
See also:
Insert (603)

Listing: objectex/ex23.pp


Program ex23;

{ Program to demonstrate the TCollection.At method }

Uses Objects,MyObject; { For TMyObject definition and registration }

Var C : PCollection;
    M : PMyObject;
    I : Longint;

begin
  C:=New(PCollection,Init(100,10));
  For I:=1 to 100 do
    begin
    M:=New(PMyObject,Init);
    M^.SetField(100-I);
    C^.Insert(M);
    end;
  For I:=0 to C^.Count-1 do
    begin
    M:=C^.At(I);
    Writeln ('Object ',i,' has field : ',M^.GetField);
    end;
  C^.FreeAll;
  Dispose(C,Done);
end.

TCollection.IndexOf

Declaration:
Function TCollection.IndexOf (Item: Pointer): Sw_Integer; Virtual;
Description:
IndexOf returns the index of Item in the collection. If Item isn’t present in the collection, -1 is returned.
Errors:
See also:

Listing: objectex/ex24.pp


Program ex24;

{ Program to demonstrate the TCollection.IndexOf method }

Uses Objects,MyObject; { For TMyObject definition and registration }

Var C : PCollection;
    M,Keep : PMyObject;
    I : Longint;

begin
  Randomize;
  C:=New(PCollection,Init(100,10));
  Keep:=Nil;
  For I:=1 to 100 do
    begin
    M:=New(PMyObject,Init);
    M^.SetField(I-1);
    If Random<0.1 then
     Keep:=M;
    C^.Insert(M);
    end;
  If Keep=Nil then
    begin
    Writeln ('Please run again. No object selected');
    Halt(1);
    end;
  Writeln ('Selected object has field : ',Keep^.GetField);
  Write ('Selected object has index : ',C^.IndexOf(Keep));
  Writeln (' should match it''s field.');
  C^.FreeAll;
  Dispose(C,Done);
end.

TCollection.GetItem

Declaration:
Function TCollection.GetItem (Var S: TStream): Pointer; Virtual;
Description:
GetItem reads a single item off the stream S, and returns a pointer to this item. This method is used internally by the Load method, and should not be used directly.
Errors:
Possible errors are the ones from TStream.Get (566).
See also:
TStream.Get (566), seeplStoreTCollection.Store

TCollection.LastThat

Declaration:
Function TCollection.LastThat (Test: Pointer): Pointer;
Description:
This function returns the last item in the collection for which Test returns a non-nil result. Test is a function that accepts 1 argument: a pointer to an object, and that returns a pointer as a result.
Errors:
None.
See also:
FirstThat (598)

Listing: objectex/ex25.pp


Program ex21;

{ Program to demonstrate the TCollection.Foreach method }

Uses Objects,MyObject; { For TMyObject definition and registration }

Var C : PCollection;
    M : PMyObject;
    I : Longint;

Function CheckField (Dummy: Pointer;P : PMyObject) : Longint;

begin
  If P^.GetField<56 then
    Checkfield:=1
  else
    CheckField:=0;
end;

begin
  C:=New(PCollection,Init(100,10));
  For I:=1 to 100 do
    begin
    M:=New(PMyObject,Init);
    M^.SetField(I);
    C^.Insert(M);
    end;
  Writeln ('Inserted ',C^.Count,' objects');
  Writeln ('Last one for which Field<56  has index (should be 54) : ',
            C^.IndexOf(C^.LastThat(@CheckField)));
  C^.FreeAll;
  Dispose(C,Done);
end.

TCollection.FirstThat

Declaration:
Function TCollection.FirstThat (Test: Pointer): Pointer;
Description:
This function returns the first item in the collection for which Test returns a non-nil result. Test is a function that accepts 1 argument: a pointer to an object, and that returns a pointer as a result.
Errors:
None.
See also:
LastThat (597)

Listing: objectex/ex26.pp


Program ex21;

{ Program to demonstrate the TCollection.FirstThat method }

Uses Objects,MyObject; { For TMyObject definition and registration }

Var C : PCollection;
    M : PMyObject;
    I : Longint;

Function CheckField (Dummy: Pointer;P : PMyObject) : Longint;

begin
  If P^.GetField>56 then
    Checkfield:=1
  else
    CheckField:=0;
end;

begin
  C:=New(PCollection,Init(100,10));
  For I:=1 to 100 do
    begin
    M:=New(PMyObject,Init);
    M^.SetField(I);
    C^.Insert(M);
    end;
  Writeln ('Inserted ',C^.Count,' objects');
  Writeln ('first one for which Field>56  has index (should be 56) : ',
            C^.IndexOf(C^.FirstThat(@CheckField)));
  C^.FreeAll;
  Dispose(C,Done);
end.

TCollection.Pack

Declaration:
Procedure TCollection.Pack;
Description:
Pack removes all Nil pointers from the collection, and adjusts Count to reflect this change. No memory is freed as a result of this call. In order to free any memory, you can call SetLimit with an argument of Count after a call to Pack.
Errors:
None.
See also:
SetLimit (607)

Listing: objectex/ex26.pp


Program ex21;

{ Program to demonstrate the TCollection.FirstThat method }

Uses Objects,MyObject; { For TMyObject definition and registration }

Var C : PCollection;
    M : PMyObject;
    I : Longint;

Function CheckField (Dummy: Pointer;P : PMyObject) : Longint;

begin
  If P^.GetField>56 then
    Checkfield:=1
  else
    CheckField:=0;
end;

begin
  C:=New(PCollection,Init(100,10));
  For I:=1 to 100 do
    begin
    M:=New(PMyObject,Init);
    M^.SetField(I);
    C^.Insert(M);
    end;
  Writeln ('Inserted ',C^.Count,' objects');
  Writeln ('first one for which Field>56  has index (should be 56) : ',
            C^.IndexOf(C^.FirstThat(@CheckField)));
  C^.FreeAll;
  Dispose(C,Done);
end.

TCollection.FreeAll

Declaration:
Procedure TCollection.FreeAll;
Description:
FreeAll calls the destructor of each object in the collection. It doesn’t release any memory occumpied by the collection itself, but it does set Count to zero.
Errors:
See also:
DeleteAll (601), FreeItem (605)

Listing: objectex/ex28.pp


Program ex28;

{ Program to demonstrate the TCollection.FreeAll method }

Uses Objects,MyObject; { For TMyObject definition and registration }

Var C : PCollection;
    M : PMyObject;
    I,InitMem : Longint;

begin
  Randomize;
  C:=New(PCollection,Init(120,10));
  InitMem:=Memavail;
  Writeln ('Initial memory : ',InitMem);
  For I:=1 to 100 do
    begin
    M:=New(PMyObject,Init);
    M^.SetField(I-1);
    C^.Insert(M);
    end;
  Writeln ('Added 100 Items. Memory available : ',Memavail);
  Write ('Lost : ',Initmem-Memavail,' bytes.');
  Write   ('(Should be 100*',SizeOF(TMyObject));
  Writeln ('=',100*SizeOf(TMyObject),')');
  C^.FreeAll;
  Writeln ('Freed all objects. Memory available : ',Memavail);
  Writeln ('Lost : ',Initmem-Memavail,' bytes.');
  Dispose(C,Done);
end.

TCollection.DeleteAll

Declaration:
Procedure TCollection.DeleteAll;
Description:
DeleteAll deletes all elements from the collection. It just sets the Count variable to zero. Contrary to FreeAll (600), DeletAll doesn’t call the destructor of the objects.
Errors:
None.
See also:
FreeAll (600), Delete (603)

Listing: objectex/ex29.pp


Program ex29;

{
 Program to demonstrate the TCollection.DeleteAll method
 Compare with example 28, where FreeAll is used.
}

Uses Objects,MyObject; { For TMyObject definition and registration }

Var C : PCollection;
    M : PMyObject;
    I,InitMem : Longint;

begin
  Randomize;
  C:=New(PCollection,Init(120,10));
  InitMem:=Memavail;
  Writeln ('Initial memory : ',InitMem);
  For I:=1 to 100 do
    begin
    M:=New(PMyObject,Init);
    M^.SetField(I-1);
    C^.Insert(M);
    end;
  Writeln ('Added 100 Items. Memory available : ',Memavail);
  Write ('Lost : ',Initmem-Memavail,' bytes.');
  Write   ('(Should be 100*',SizeOF(TMyObject));
  Writeln ('=',100*SizeOf(TMyObject),')');
  C^.DeleteAll;
  Writeln ('Deleted all objects. Memory available : ',Memavail);
  Writeln ('Lost : ',Initmem-Memavail,' bytes.');
  Dispose(C,Done);
end.

TCollection.Free

Declaration:
Procedure TCollection.Free (Item: Pointer);
Description:
Free Deletes Item from the collection, and calls the destructor Done of the object.
Errors:
If the Item is not in the collection, Error will be called with coIndexError.
See also:
FreeItem (605),

Listing: objectex/ex30.pp


Program ex30;

{ Program to demonstrate the TCollection.Free method }

Uses Objects,MyObject; { For TMyObject definition and registration }

Var C : PCollection;
    M : PMyObject;
    I,InitMem : Longint;

begin
  Randomize;
  C:=New(PCollection,Init(120,10));
  InitMem:=Memavail;
  Writeln ('Initial memory : ',InitMem);
  For I:=1 to 100 do
    begin
    M:=New(PMyObject,Init);
    M^.SetField(I-1);
    C^.Insert(M);
    end;
  Writeln ('Added 100 Items. Memory available : ',Memavail);
  Write ('Lost : ',Initmem-Memavail,' bytes.');
  Write   ('(Should be 100*',SizeOF(TMyObject));
  Writeln ('=',100*SizeOf(TMyObject),')');
  With C^ do
    While Count>0 do Free(At(Count-1));
  Writeln ('Freed all objects. Memory available : ',Memavail);
  Writeln ('Lost : ',Initmem-Memavail,' bytes.');
  Dispose(C,Done);
end.

TCollection.Insert

Declaration:
Procedure TCollection.Insert (Item: Pointer); Virtual;
Description:
Insert inserts Item in the collection. TCollection inserts this item at the end, but descendent objects may insert it at another place.
Errors:
None.
See also:
AtInsert (608), AtPut (608),

TCollection.Delete

Declaration:
Procedure TCollection.Delete (Item: Pointer);
Description:
Delete deletes Item from the collection. It doesn’t call the item’s destructor, though. For this the Free (602) call is provided.
Errors:
If the Item is not in the collection, Error will be called with coIndexError.
See also:
AtDelete (605),Free (602)

Listing: objectex/ex31.pp


Program ex31;

{ Program to demonstrate the TCollection.Delete method }

Uses Objects,MyObject; { For TMyObject definition and registration }

Var C : PCollection;
    M : PMyObject;
    I,InitMem : Longint;

begin
  Randomize;
  C:=New(PCollection,Init(120,10));
  InitMem:=Memavail;
  Writeln ('Initial memory : ',InitMem);
  For I:=1 to 100 do
    begin
    M:=New(PMyObject,Init);
    M^.SetField(I-1);
    C^.Insert(M);
    end;
  Writeln ('Added 100 Items. Memory available : ',Memavail);
  Write ('Lost : ',Initmem-Memavail,' bytes.');
  Write   ('(Should be 100*',SizeOF(TMyObject));
  Writeln ('=',100*SizeOf(TMyObject),')');
  With C^ do
    While Count>0 do Delete(At(Count-1));
  Writeln ('Freed all objects. Memory available : ',Memavail);
  Writeln ('Lost : ',Initmem-Memavail,' bytes.');
  Dispose(C,Done);
end.

TCollection.AtFree

Declaration:
Procedure TCollection.AtFree (Index: Sw_Integer);
Description:
AtFree deletes the item at position Index in the collection, and calls the item’s destructor if it is not Nil.
Errors:
If Index isn’t valid then Error (608) is called with CoIndexError.
See also:
Free (602), AtDelete (605)

Listing: objectex/ex32.pp


Program ex32;

{ Program to demonstrate the TCollection.AtFree method }

Uses Objects,MyObject; { For TMyObject definition and registration }

Var C : PCollection;
    M : PMyObject;
    I,InitMem : Longint;

begin
  Randomize;
  C:=New(PCollection,Init(120,10));
  InitMem:=Memavail;
  Writeln ('Initial memory : ',InitMem);
  For I:=1 to 100 do
    begin
    M:=New(PMyObject,Init);
    M^.SetField(I-1);
    C^.Insert(M);
    end;
  Writeln ('Added 100 Items. Memory available : ',Memavail);
  Write ('Lost : ',Initmem-Memavail,' bytes.');
  Write   ('(Should be 100*',SizeOF(TMyObject));
  Writeln ('=',100*SizeOf(TMyObject),')');
  With C^ do
    While Count>0 do AtFree(Count-1);
  Writeln ('Freed all objects. Memory available : ',Memavail);
  Writeln ('Lost : ',Initmem-Memavail,' bytes.');
  Dispose(C,Done);
end.

TCollection.FreeItem

Declaration:
Procedure TCollection.FreeItem (Item: Pointer); Virtual;
Description:
FreeItem calls the destructor of Item if it is not nil.

This function is used internally by the TCollection object, and should not be called directly.

Errors:
None.
See also:
Free (604), seeplAtFreeTCollection.AtFree

TCollection.AtDelete

Declaration:
Procedure TCollection.AtDelete (Index: Sw_Integer);
Description:
AtDelete deletes the pointer at position Index in the collection. It doesn’t call the object’s destructor.
Errors:
If Index isn’t valid then Error (608) is called with CoIndexError.
See also:
Delete (603)

Listing: objectex/ex33.pp


Program ex33;

{ Program to demonstrate the TCollection.AtDelete method }

Uses Objects,MyObject; { For TMyObject definition and registration }

Var C : PCollection;
    M : PMyObject;
    I,InitMem : Longint;

begin
  Randomize;
  C:=New(PCollection,Init(120,10));
  InitMem:=Memavail;
  Writeln ('Initial memory : ',InitMem);
  For I:=1 to 100 do
    begin
    M:=New(PMyObject,Init);
    M^.SetField(I-1);
    C^.Insert(M);
    end;
  Writeln ('Added 100 Items. Memory available : ',Memavail);
  Write ('Lost : ',Initmem-Memavail,' bytes.');
  Write   ('(Should be 100*',SizeOF(TMyObject));
  Writeln ('=',100*SizeOf(TMyObject),')');
  With C^ do
    While Count>0 do AtDelete(Count-1);
  Writeln ('Freed all objects. Memory available : ',Memavail);
  Writeln ('Lost : ',Initmem-Memavail,' bytes.');
  Dispose(C,Done);
end.

TCollection.ForEach

Declaration:
Procedure TCollection.ForEach (Action: Pointer);
Description:
ForEach calls Action for each element in the collection, and passes the element as an argument to Action.

Action is a procedural type variable that accepts a pointer as an argument.

Errors:
None.
See also:
FirstThat (598), LastThat (597)

Listing: objectex/ex21.pp


Program ex21;

{ Program to demonstrate the TCollection.Foreach method }

Uses Objects,MyObject; { For TMyObject definition and registration }

Var C : PCollection;
    M : PMyObject;
    I : Longint;

Procedure PrintField (Dummy: Pointer;P : PMyObject);

begin
  Writeln ('Field : ',P^.GetField);
end;

begin
  C:=New(PCollection,Init(100,10));
  For I:=1 to 100 do
    begin
    M:=New(PMyObject,Init);
    M^.SetField(100-I);
    C^.Insert(M);
    end;
  Writeln ('Inserted ',C^.Count,' objects');
  C^.ForEach(@PrintField);
  C^.FreeAll;
  Dispose(C,Done);
end.

TCollection.SetLimit

Declaration:
Procedure TCollection.SetLimit (ALimit: Sw_Integer); Virtual;
Description:
SetLimit sets the maximum number of elements in the collection. ALimit must not be less than Count, and should not be larger than MaxCollectionSize
Errors:
None.
See also:
Init (593)

For an example, see Pack (599).

TCollection.Error

Declaration:
Procedure TCollection.Error (Code, Info: Integer); Virtual;
Description:
Error is called by the various TCollection methods in case of an error condition. The default behaviour is to make a call to RunError with an error of 212-Code.

This method can be overridden by descendent objects to implement a different error-handling.

Errors:
See also:
Abstract (549)

TCollection.AtPut

Declaration:
Procedure TCollection.AtPut (Index: Sw_Integer; Item: Pointer);
Description:
AtPut sets the element at position Index in the collection to Item. Any previous value is overwritten.
Errors:
If Index isn’t valid then Error (608) is called with CoIndexError.
See also:

For an example, see Pack (599).

TCollection.AtInsert

Declaration:
Procedure TCollection.AtInsert (Index: Sw_Integer; Item: Pointer);
Description:
AtInsert inserts Item in the collection at position Index, shifting all elements by one position. In case the current limit is reached, the collection will try to expand with a call to SetLimit
Errors:
If Index isn’t valid then Error (608) is called with CoIndexError. If the collection fails to expand, then coOverFlow is passd to Error.
See also:
Insert (603)

Listing: objectex/ex34.pp


Program ex34;

{ Program to demonstrate the TCollection.AtInsert method }

Uses Objects,MyObject; { For TMyObject definition and registration }

Var C : PCollection;
    M : PMyObject;
    I : Longint;

Procedure PrintField (Dummy: Pointer;P : PMyObject);

begin
  Writeln ('Field : ',P^.GetField);
end;


begin
  Randomize;
  C:=New(PCollection,Init(120,10));
  Writeln ('Inserting 100 records at random places.');
  For I:=1 to 100 do
    begin
    M:=New(PMyObject,Init);
    M^.SetField(I-1);
    If I=1 then
      C^.Insert(M)
    else
      With C^ do
        AtInsert(Random(Count),M);
    end;
  Writeln ('Values : ');
  C^.Foreach(@PrintField);
  Dispose(C,Done);
end.

TCollection.Store

Declaration:
Procedure TCollection.Store (Var S: TStream);
Description:
Store writes the collection to the stream S. It does this by writeing the current Count, Limit and Delta to the stream, and then writing each item to the stream.

The contents of the stream are then suitable for instantiating another collection with Load (594).

Errors:
Errors returned are those by TStream.Put (571).
See also:
Load (594), PutItem (610)

For an example, see seeplLoadTCollection.Load.

TCollection.PutItem

Declaration:
Procedure TCollection.PutItem (Var S: TStream; Item: Pointer); Virtual;
Description:
PutItem writes Item to stream S. This method is used internaly by the TCollection object, and should not be called directly.
Errors:
Errors are those returned by TStream.Put (571).
See also:
Store (609), GetItem (597).