The methods and fields that are in a Private part of an object declaration have been left out of this documentation.
CONST stOk = 0; { No stream error } stError = -1; { Access error } stInitError = -2; { Initialize error } stReadError = -3; { Stream read error } stWriteError = -4; { Stream write error } stGetError = -5; { Get object error } stPutError = -6; { Put object error } stSeekError = -7; { Seek error in stream } stOpenError = -8; { Error opening stream }These constants can be passed to constructors of file streams:
CONST stCreate = $3C00; { Create new file } stOpenRead = $3D00; { Read access only } stOpenWrite = $3D01; { Write access only } stOpen = $3D02; { Read/write access }
The following constants are error codes, returned by the collection list objects:
CONST coIndexError = -1; { Index out of range } coOverflow = -2; { Overflow }
Maximum data sizes (used in determining how many data can be used.
CONST MaxBytes = 128*1024*1024; { Maximum data size } MaxWords = MaxBytes DIV SizeOf(Word); { Max word data size } MaxPtrs = MaxBytes DIV SizeOf(Pointer); { Max ptr data size } MaxCollectionSize = MaxBytes DIV SizeOf(Pointer); { Max collection size }
TYPE { Character set } TCharSet = SET Of Char; PCharSet = ^TCharSet; { Byte array } TByteArray = ARRAY [0..MaxBytes-1] Of Byte; PByteArray = ^TByteArray; { Word array } TWordArray = ARRAY [0..MaxWords-1] Of Word; PWordArray = ^TWordArray; { Pointer array } TPointerArray = Array [0..MaxPtrs-1] Of Pointer; PPointerArray = ^TPointerArray; { String pointer } PString = ^String; { Filename array } AsciiZ = Array [0..255] Of Char; Sw_Word = Cardinal; Sw_Integer = LongInt;The following records are used internaly for easy type conversion:
TYPE { Word to bytes} WordRec = packed RECORD Lo, Hi: Byte; END; { LongInt to words } LongRec = packed RECORD Lo, Hi: Word; END; { Pointer to words } PtrRec = packed RECORD Ofs, Seg: Word; END;
The following record is used when streaming objects:
TYPE PStreamRec = ^TStreamRec; TStreamRec = Packed RECORD ObjType: Sw_Word; VmtLink: pointer; Load : Pointer; Store: Pointer; Next : PStreamRec; END;
The TPoint basic object is used in the TRect object (see section TRect):
TYPE PPoint = ^TPoint; TPoint = OBJECT X, Y: Sw_Integer; END;
The allocated memory is not based on the declared size of the string passed to NewStr, but is baed on the actual length of the string.
Program ex40; { Program to demonstrate the NewStr function } Uses Objects; Var S : String; P : PString; begin S:='Some really cute string'; Writeln ('Memavail : ',Memavail); P:=NewStr(S); If P^<>S then Writeln ('Oh-oh... Something is wrong !!'); Writeln ('Allocated string. Memavail : ',Memavail); DisposeStr(P); Writeln ('Deallocated string. Memavail : ',Memavail); end.
For an example, see NewStr.
The current implementation of Abstract terminates the program with a run-time error 211.
VmtLink: Ofs(TypeOf(MyType)^);
Unit MyObject; Interface Uses Objects; Type PMyObject = ^TMyObject; TMyObject = Object(TObject) Field : Longint; Constructor Init; Constructor Load (Var Stream : TStream); Destructor Done; Procedure Store (Var Stream : TStream); Function GetField : Longint; Procedure SetField (Value : Longint); end; Implementation Constructor TMyobject.Init; begin Inherited Init; Field:=-1; end; Constructor TMyobject.Load (Var Stream : TStream); begin Stream.Read(Field,Sizeof(Field)); end; Destructor TMyObject.Done; begin end; Function TMyObject.GetField : Longint; begin GetField:=Field; end; Procedure TMyObject.SetField (Value : Longint); begin Field:=Value; end; Procedure TMyObject.Store (Var Stream : TStream); begin Stream.Write(Field,SizeOf(Field)); end; Const MyObjectRec : TStreamRec = ( Objtype : 666; vmtlink : Ofs(TypeOf(TMyObject)^); Load : @TMyObject.Load; Store : @TMyObject.Store; ); begin RegisterObjects; RegisterType (MyObjectRec); end.
The TRect object is declared as follows:
TRect = OBJECT A, B: TPoint; FUNCTION Empty: Boolean; FUNCTION Equals (R: TRect): Boolean; FUNCTION Contains (P: TPoint): Boolean; PROCEDURE Copy (R: TRect); PROCEDURE Union (R: TRect); PROCEDURE Intersect (R: TRect); PROCEDURE Move (ADX, ADY: Sw_Integer); PROCEDURE Grow (ADX, ADY: Sw_Integer); PROCEDURE Assign (XA, YA, XB, YB: Sw_Integer); END;
Program ex1; { Program to demonstrate TRect.Empty } Uses objects; Var ARect,BRect : TRect; P : TPoint; begin With ARect.A do begin X:=10; Y:=10; end; With ARect.B do begin X:=20; Y:=20; end; { Offset B by (5,5) } With BRect.A do begin X:=15; Y:=15; end; With BRect.B do begin X:=25; Y:=25; end; { Point } With P do begin X:=15; Y:=15; end; Writeln ('A empty : ',ARect.Empty); Writeln ('B empty : ',BRect.Empty); Writeln ('A Equals B : ',ARect.Equals(BRect)); Writeln ('A Contains (15,15) : ',ARect.Contains(P)); end.
For an example, see TRect.Empty
Program ex2; { Program to demonstrate TRect.Copy } Uses objects; Var ARect,BRect,CRect : TRect; begin ARect.Assign(10,10,20,20); BRect.Assign(15,15,25,25); CRect.Copy(ARect); If ARect.Equals(CRect) Then Writeln ('ARect equals CRect') Else Writeln ('ARect does not equal CRect !'); end.
Program ex3; { Program to demonstrate TRect.Union } Uses objects; Var ARect,BRect,CRect : TRect; begin ARect.Assign(10,10,20,20); BRect.Assign(15,15,25,25); { CRect is union of ARect and BRect } CRect.Assign(10,10,25,25); { Calculate it explicitly} ARect.Union(BRect); If ARect.Equals(CRect) Then Writeln ('ARect equals CRect') Else Writeln ('ARect does not equal CRect !'); end.
Program ex4; { Program to demonstrate TRect.Intersect } Uses objects; Var ARect,BRect,CRect : TRect; begin ARect.Assign(10,10,20,20); BRect.Assign(15,15,25,25); { CRect is intersection of ARect and BRect } CRect.Assign(15,15,20,20); { Calculate it explicitly} ARect.Intersect(BRect); If ARect.Equals(CRect) Then Writeln ('ARect equals CRect') Else Writeln ('ARect does not equal CRect !'); BRect.Assign(25,25,30,30); Arect.Intersect(BRect); If ARect.Empty Then Writeln ('ARect is empty'); end.
Program ex5; { Program to demonstrate TRect.Move } Uses objects; Var ARect,BRect : TRect; begin ARect.Assign(10,10,20,20); ARect.Move(5,5); // Brect should be where new ARect is. BRect.Assign(15,15,25,25); If ARect.Equals(BRect) Then Writeln ('ARect equals BRect') Else Writeln ('ARect does not equal BRect !'); end.
ADX and ADY can be negative. If the resulting rectangle is empty, it is set to the empty rectangle at (0,0).
program ex7; { Program to demonstrate the TObject.Free call } Uses Objects; Var O : PObject; begin Writeln ('Memavail : ',Memavail); // Allocate memory for object. O:=New(PObject,Init); Writeln ('Memavail : ',Memavail); // Free memory of object. O^.free; Writeln ('Memavail : ',Memavail); end.
For an example, see TRect.Copy.
The full declaration of the TObject type is:
TYPE TObject = OBJECT CONSTRUCTOR Init; PROCEDURE Free; DESTRUCTOR Done;Virtual; END; PObject = ^TObject;
For an example, see Free
program ex7; { Program to demonstrate the TObject.Free call } Uses Objects; Var O : PObject; begin Writeln ('Memavail : ',Memavail); // Allocate memory for object. O:=New(PObject,Init); Writeln ('Memavail : ',Memavail); // Free memory of object. O^.free; Writeln ('Memavail : ',Memavail); end.
The destructore Done does not free the memory occupied by the object.
program ex8; { Program to demonstrate the TObject.Done call } Uses Objects; Var O : PObject; begin Writeln ('Memavail : ',Memavail); // Allocate memory for object. O:=New(PObject,Init); Writeln ('Memavail : ',Memavail); O^.Done; Writeln ('Memavail : ',Memavail); end.
The TStream object is the ancestor for all streaming objects, i.e. objects that have the capability to store and retrieve data.
It defines a number of methods that are common to all objects that implement streaming, many of them are virtual, and are only implemented in the descendrnt types.
Programs should not instantiate objects of type TStream directly, but instead instantiate a descendant type, such as TDosStream, TMemoryStream.
This is the full declaration of the TStream object:
TYPE TStream = OBJECT (TObject) Status : Integer; { Stream status } ErrorInfo : Integer; { Stream error info } StreamSize: LongInt; { Stream current size } Position : LongInt; { Current position } FUNCTION Get: PObject; FUNCTION StrRead: PChar; FUNCTION GetPos: Longint; Virtual; FUNCTION GetSize: Longint; Virtual; FUNCTION ReadStr: PString; PROCEDURE Open (OpenMode: Word); Virtual; PROCEDURE Close; Virtual; PROCEDURE Reset; PROCEDURE Flush; Virtual; PROCEDURE Truncate; Virtual; PROCEDURE Put (P: PObject); PROCEDURE StrWrite (P: PChar); PROCEDURE WriteStr (P: PString); PROCEDURE Seek (Pos: LongInt); Virtual; PROCEDURE Error (Code, Info: Integer); Virtual; PROCEDURE Read (Var Buf; Count: Sw_Word); Virtual; PROCEDURE Write (Var Buf; Count: Sw_Word); Virtual; PROCEDURE CopyFrom (Var S: TStream; Count: Longint); END; PStream = ^TStream;
Program ex9; { Program to demonstrate TStream.Get and TStream.Put } Uses Objects,MyObject; { Definition and registration of TMyObject} Var Obj : PMyObject; S : PStream; begin Obj:=New(PMyObject,Init); Obj^.SetField($1111) ; Writeln ('Field value : ',Obj^.GetField); { Since Stream is an abstract type, we instantiate a TMemoryStream } S:=New(PMemoryStream,Init(100,10)); S^.Put(Obj); Writeln ('Disposing object'); S^.Seek(0); Dispose(Obj,Done); Writeln ('Reading object'); Obj:=PMyObject(S^.Get); Writeln ('Field Value : ',Obj^.GetField); Dispose(Obj,Done); end.
Program ex10; { Program to demonstrate the TStream.StrRead TStream.StrWrite functions } Uses objects; Var P : PChar; S : PStream; begin P:='Constant Pchar string'; Writeln ('Writing to stream : "',P,'"'); S:=New(PMemoryStream,Init(100,10)); S^.StrWrite(P); S^.Seek(0); P:=Nil; P:=S^.StrRead; DisPose (S,Done); Writeln ('Read from stream : "',P,'"'); Freemem(P,Strlen(P)+1); end.
Program ex11; { Program to demonstrate the TStream.GetPos function } Uses objects; Var L : String; S : PStream; begin L:='Some kind of string'; S:=New(PMemoryStream,Init(100,10)); Writeln ('Stream position before write: ',S^.GetPos); S^.WriteStr(@L); Writeln ('Stream position after write : ',S^.GetPos); Dispose(S,Done); end.
Program ex12; { Program to demonstrate the TStream.GetSize function } Uses objects; Var L : String; S : PStream; begin L:='Some kind of string'; S:=New(PMemoryStream,Init(100,10)); Writeln ('Stream size before write: ',S^.GetSize); S^.WriteStr(@L); Writeln ('Stream size after write : ',S^.GetSize); Dispose(S,Done); end.
Program ex13; { Program to demonstrate the TStream.ReadStr TStream.WriteStr functions } Uses objects; Var P : PString; L : String; S : PStream; begin L:='Constant string line'; Writeln ('Writing to stream : "',L,'"'); S:=New(PMemoryStream,Init(100,10)); S^.WriteStr(@L); S^.Seek(0); P:=S^.ReadStr; L:=P^; DisposeStr(P); DisPose (S,Done); Writeln ('Read from stream : "',L,'"'); end.
For an example, see TDosStream.Open.
for an example, see TDosStream.Open.
for an example, see TBufStream.Flush.
For an example, see TDosStream.Truncate.
After the object has been written, it can be read again with Get.
For an example, see TStream.Get;
For an example, see TStream.StrRead.
For an example, see TStream.ReadStr.
For an example, see TDosStream.Seek.
This method should not be called directly from a program. It is intended to be used in descendent objects.
Read reads Count bytes from the stream into Buf. It updates the position pointer, increasing it's value with Count. Buf must be large enough to contain Count bytes.
program ex18; { Program to demonstrate the TStream.Read method } Uses Objects; Var Buf1,Buf2 : Array[1..1000] of Byte; I : longint; S : PMemorySTream; begin For I:=1 to 1000 do Buf1[I]:=Random(1000); Buf2:=Buf1; S:=New(PMemoryStream,Init(100,10)); S^.Write(Buf1,SizeOf(Buf1)); S^.Seek(0); For I:=1 to 1000 do Buf1[I]:=0; S^.Read(Buf1,SizeOf(Buf1)); For I:=1 to 1000 do If Buf1[I]<>buf2[i] then Writeln ('Buffer differs at position ',I); Dispose(S,Done); end.
Write writes Count bytes to the stream from Buf. It updates the position pointer, increasing it's value with Count.
For an example, see TStream.Read.
Program ex19; { Program to demonstrate the TStream.CopyFrom function } Uses objects; Var P : PString; L : String; S1,S2 : PStream; begin L:='Constant string line'; Writeln ('Writing to stream 1 : "',L,'"'); S1:=New(PMemoryStream,Init(100,10)); S2:=New(PMemoryStream,Init(100,10)); S1^.WriteStr(@L); S1^.Seek(0); Writeln ('Copying contents of stream 1 to stream 2'); S2^.Copyfrom(S1^,S1^.GetSize); S2^.Seek(0); P:=S2^.ReadStr; L:=P^; DisposeStr(P); Dispose (S1,Done); Dispose (S2,Done); Writeln ('Read from stream 2 : "',L,'"'); end.
TDosStream is a stream that stores it's contents in a file. it overrides a couple of methods of TSteam for this.
In addition to the fields inherited from TStream (see section TStream), there are some extra fields, that describe the file. (mainly the name and the OS file handle)
No buffering in memory is done when using TDosStream. All data are written directly to the file. For a stream that buffers in memory, see section TBufStream.
Here is the full declaration of the TDosStream object:
TYPE TDosStream = OBJECT (TStream) Handle: THandle; { DOS file handle } FName : AsciiZ; { AsciiZ filename } CONSTRUCTOR Init (FileName: FNameStr; Mode: Word); DESTRUCTOR Done; Virtual; PROCEDURE Close; Virtual; PROCEDURE Truncate; Virtual; PROCEDURE Seek (Pos: LongInt); Virtual; PROCEDURE Open (OpenMode: Word); Virtual; PROCEDURE Read (Var Buf; Count: Sw_Word); Virtual; PROCEDURE Write (Var Buf; Count: Sw_Word); Virtual; END; PDosStream = ^TDosStream;
For an example, see TDosStream.Truncate.
for an example, see e.g. TDosStream.Truncate.
For an example, see TDosStream.Open.
Program ex16; { Program to demonstrate the TStream.Truncate method } Uses Objects; Var L : String; P : PString; S : PDosStream; { Only one with Truncate implemented. } begin L:='Some constant string'; { Buffer size of 100 } S:=New(PDosStream,Init('test.dat',stcreate)); Writeln ('Writing "',L,'" to stream with handle ',S^.Handle); S^.WriteStr(@L); S^.WriteStr(@L); { Close calls flush first } S^.Close; S^.Open (stOpen); Writeln ('Size of stream is : ',S^.GetSize); P:=S^.ReadStr; L:=P^; DisposeStr(P); Writeln ('Read "',L,'" from stream with handle ',S^.Handle); S^.Truncate; Writeln ('Truncated stream. Size is : ',S^.GetSize); S^.Close; Dispose (S,Done); end.
Program ex17; { Program to demonstrate the TStream.Seek method } Uses Objects; Var L : String; Marker : Word; P : PString; S : PDosStream; begin L:='Some constant string'; { Buffer size of 100 } S:=New(PDosStream,Init('test.dat',stcreate)); Writeln ('Writing "',L,'" to stream.'); S^.WriteStr(@L); Marker:=S^.GetPos; Writeln ('Set marker at ',Marker); L:='Some other constant String'; Writeln ('Writing "',L,'" to stream.'); S^.WriteStr(@L); S^.Close; S^.Open (stOpenRead); Writeln ('Size of stream is : ',S^.GetSize); Writeln ('Seeking to marker'); S^.Seek(Marker); P:=S^.ReadStr; L:=P^; DisposeStr(P); Writeln ('Read "',L,'" from stream.'); S^.Close; Dispose (S,Done); end.
Program ex14; { Program to demonstrate the TStream.Close method } Uses Objects; Var L : String; P : PString; S : PDosStream; { Only one with Close implemented. } begin L:='Some constant string'; S:=New(PDosStream,Init('test.dat',stcreate)); Writeln ('Writing "',L,'" to stream with handle ',S^.Handle); S^.WriteStr(@L); S^.Close; Writeln ('Closed stream. File handle is ',S^.Handle); S^.Open (stOpenRead); P:=S^.ReadStr; L:=P^; DisposeStr(P); Writeln ('Read "',L,'" from stream with handle ',S^.Handle); S^.Close; Dispose (S,Done); end.
For an example, see TStream.Read.
For an example, see TStream.Read.
Bufstream implements a buffered file stream. That is, all data written to the stream is written to memory first. Only when the buffer is full, or on explicit request, the data is written to disk.
Also, when reading from the stream, first the buffer is checked if there is any unread data in it. If so, this is read first. If not the buffer is filled again, and then the data is read from the buffer.
The size of the buffer is fixed and is set when constructing the file.
This is useful if you need heavy throughput for your stream, because it speeds up operations.
TYPE TBufStream = OBJECT (TDosStream) LastMode: Byte; { Last buffer mode } BufSize : Sw_Word; { Buffer size } BufPtr : Sw_Word; { Buffer start } BufEnd : Sw_Word; { Buffer end } Buffer : PByteArray; { Buffer allocated } CONSTRUCTOR Init (FileName: FNameStr; Mode, Size: Word); DESTRUCTOR Done; Virtual; PROCEDURE Close; Virtual; PROCEDURE Flush; Virtual; PROCEDURE Truncate; Virtual; PROCEDURE Seek (Pos: LongInt); Virtual; PROCEDURE Open (OpenMode: Word); Virtual; PROCEDURE Read (Var Buf; Count: Sw_Word); Virtual; PROCEDURE Write (Var Buf; Count: Sw_Word); Virtual; END; PBufStream = ^TBufStream;
For an example see TBufStream.Flush.
For an example see TBufStream.Flush.
For an example see TBufStream.Flush.
When the stream is in read mode, the buffer position is set to zero.
Program ex15; { Program to demonstrate the TStream.Flush method } Uses Objects; Var L : String; P : PString; S : PBufStream; { Only one with Flush implemented. } begin L:='Some constant string'; { Buffer size of 100 } S:=New(PBufStream,Init('test.dat',stcreate,100)); Writeln ('Writing "',L,'" to stream with handle ',S^.Handle); S^.WriteStr(@L); { At this moment, there is no data on disk yet. } S^.Flush; { Now there is. } S^.WriteStr(@L); { Close calls flush first } S^.Close; Writeln ('Closed stream. File handle is ',S^.Handle); S^.Open (stOpenRead); P:=S^.ReadStr; L:=P^; DisposeStr(P); Writeln ('Read "',L,'" from stream with handle ',S^.Handle); S^.Close; Dispose (S,Done); end.
For an example, see TDosStream.Truncate.
For an example, see TStream.Seek;
For an example, see TDosStream.Open.
Read will first try to read the data from the stream's internal buffer. If insufficient data is available, the buffer will be filled before contiunuing to read. This process is repeated until all needed data has been read.
For an example, see TStream.Read.
Write will first try to write the data to the stream's internal buffer. When the internal buffer is full, then the contents will be written to disk. This process is repeated until all data has been written.
For an example, see TStream.Read.
The TMemoryStream object implements a stream that stores it's data in memory. The data is stored on the heap, with the possibility to specify the maximum amout of data, and the the size of the memory blocks being used.
TYPE TMemoryStream = OBJECT (TStream) BlkCount: Sw_Word; { Number of segments } BlkSize : Word; { Memory block size } MemSize : LongInt; { Memory alloc size } BlkList : PPointerArray; { Memory block list } CONSTRUCTOR Init (ALimit: Longint; ABlockSize: Word); DESTRUCTOR Done; Virtual; PROCEDURE Truncate; Virtual; PROCEDURE Read (Var Buf; Count: Sw_Word); Virtual; PROCEDURE Write (Var Buf; Count: Sw_Word); Virtual; END; PMemoryStream = ^TMemoryStream;
By default, the number of blocks is 1, and the size of a block is 8192. This is selected if you specify 0 as the blocksize.
For an example, see e.g TStream.CopyFrom.
For an example, see e.g TStream.CopyFrom.
Program ex20; { Program to demonstrate the TMemoryStream.Truncate method } Uses Objects; Var L : String; P : PString; S : PMemoryStream; I,InitMem : Longint; begin initMem:=Memavail; L:='Some constant string'; { Buffer size of 100 } S:=New(PMemoryStream,Init(1000,100)); Writeln ('Free memory : ',Memavail); Writeln ('Writing 100 times "',L,'" to stream.'); For I:=1 to 100 do S^.WriteStr(@L); Writeln ('Finished. Free memory : ',Memavail); S^.Seek(100); S^.Truncate; Writeln ('Truncated at byte 100. Free memory : ',Memavail); Dispose (S,Done); Writeln ('Finished. Lost ',InitMem-Memavail,' Bytes.'); end.
For an example, see TStream.Read.
If not enough memory is available to hold the extra Count bytes, then the stream will try to expand, by allocating as much blocks with size BlkSize (as specified in the constuctor call Init) as needed.
For an example, see TStream.Read.
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;
For an example, see TCollection.ForEach.
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.
For an example, see TCollection.ForEach.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
This function is used internally by the TCollection object, and should not be called directly.
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.
Action is a procedural type variable that accepts a pointer as an argument.
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.
For an example, see Pack.
This method can be overridden by descendent objects to implement a different error-handling.
For an example, see Pack.
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.
The contents of the stream are then suitable for instantiating another collection with Load.
For an example, see seeplLoadTCollection.Load.
TSortedCollection is an abstract class, implementing a sorted collection. You should never use an instance of TSortedCollection directly, instead you should declare a descendent type, and override the Compare method.
Because the collection is ordered, TSortedCollection overrides some TCollection methods, to provide faster routines for lookup.
The Compare method decides how elements in the collection should be ordered. Since TCollection has no way of knowing how to order pointers, you must override the compare method.
Additionally, TCollection provides a means to filter out duplicates. if you set Duplicates to False (the default) then duplicates will not be allowed.
Here is the complete declaration of TSortedCollection
TYPE TSortedCollection = OBJECT (TCollection) Duplicates: Boolean; { Duplicates flag } Constructor Init (ALimit, ADelta: Sw_Integer); Constructor Load (Var S: TStream); Function KeyOf (Item: Pointer): Pointer; Virtual; Function IndexOf (Item: Pointer): Sw_Integer; Virtual; Function Compare (Key1, Key2: Pointer): Sw_Integer; Virtual; Function Search (Key: Pointer; Var Index: Sw_Integer): Boolean;Virtual; Procedure Insert (Item: Pointer); Virtual; Procedure Store (Var S: TStream); END; PSortedCollection = ^TSortedCollection;
In the subsequent examples, the following descendent of TSortedCollection is used:
Unit MySortC; Interface Uses Objects; Type PMySortedCollection = ^TMySortedCollection; TMySortedCollection = Object(TSortedCollection) Function Compare (Key1,Key2 : Pointer): Sw_integer; virtual; end; Implementation Uses MyObject; Function TMySortedCollection.Compare (Key1,Key2 : Pointer) :sw_integer; begin Compare:=PMyobject(Key1)^.GetField - PMyObject(Key2)^.GetField; end; end.
You should not call this method directly, since TSortedCollection is a abstract class. Instead, the descendent classes should call it via the inherited keyword.
For an example, see
You should not call this method directly, since TSortedCollection is a abstract class. Instead, the descendent classes should call it via the inherited keyword.
For an example, see TCollection.Load.
Keys are used to sort the objects, they are used to search and sort the items in the collection. If descendent types override this method then it allows possibly for faster search/sort methods based on keys rather than on the objects themselves.
In case Item is not found in the collection, -1 is returned.
For an example, see TCollection.IndexOf
The function should compare the two keys of items and return the following function results:
Unit MySortC; Interface Uses Objects; Type PMySortedCollection = ^TMySortedCollection; TMySortedCollection = Object(TSortedCollection) Function Compare (Key1,Key2 : Pointer): Sw_integer; virtual; end; Implementation Uses MyObject; Function TMySortedCollection.Compare (Key1,Key2 : Pointer) :sw_integer; begin Compare:=PMyobject(Key1)^.GetField - PMyObject(Key2)^.GetField; end; end.
Instead of a linear search as TCollection does, TSortedCollection uses a binary search based on the keys of the objects. It uses the Compare function to implement this search.
If the item is found, Search returns True, otherwise False is returned.
Program ex36; { Program to demonstrate the TSortedCollection.Insert method } Uses Objects,MyObject,MySortC; { For TMyObject,TMySortedCollection definition and registration } Var C : PSortedCollection; M : PMyObject; I : Longint; Procedure PrintField (Dummy: Pointer;P : PMyObject); begin Writeln ('Field : ',P^.GetField); end; begin Randomize; C:=New(PMySortedCollection,Init(120,10)); C^.Duplicates:=True; Writeln ('Inserting 100 records at random places.'); For I:=1 to 100 do begin M:=New(PMyObject,Init); M^.SetField(Random(100)); C^.Insert(M) end; M:=New(PMyObject,Init); Repeat; Write ('Value to search for (-1 stops) :'); read (I); If I<>-1 then begin M^.SetField(i); If Not C^.Search (M,I) then Writeln ('No such value found') else begin Write ('Value ',PMyObject(C^.At(I))^.GetField); Writeln (' present at position ',I); end; end; Until I=-1; Dispose(M,Done); Dispose(C,Done); end.
If Item is already present in the collection, and Duplicates is False, the item will not be inserted.
Program ex35; { Program to demonstrate the TSortedCollection.Insert method } Uses Objects,MyObject,MySortC; { For TMyObject,TMySortedCollection definition and registration } Var C : PSortedCollection; M : PMyObject; I : Longint; Procedure PrintField (Dummy: Pointer;P : PMyObject); begin Writeln ('Field : ',P^.GetField); end; begin Randomize; C:=New(PMySortedCollection,Init(120,10)); Writeln ('Inserting 100 records at random places.'); For I:=1 to 100 do begin M:=New(PMyObject,Init); M^.SetField(Random(100)); C^.Insert(M) end; Writeln ('Values : '); C^.Foreach(@PrintField); Dispose(C,Done); end.
After a Store, the collection can be loaded from the stream with the constructor Load
For an example, see TCollection.Load.
The TStringCollection object manages a sorted collection of pascal strings. To this end, it overrides the Compare method of TSortedCollection, and it introduces methods to read/write strings from a stream.
Here is the full declaration of the TStringCollection object:
TYPE TStringCollection = OBJECT (TSortedCollection) Function GetItem (Var S: TStream): Pointer; Virtual; Function Compare (Key1, Key2: Pointer): Sw_Integer; Virtual; Procedure FreeItem (Item: Pointer); Virtual; Procedure PutItem (Var S: TStream; Item: Pointer); Virtual; END; PStringCollection = ^TStringCollection;
This method is primarily introduced to be able to load and store the collection from and to a stream.
Program ex37; { Program to demonstrate the TStringCollection.Compare method } Uses Objects; Var C : PStringCollection; S : String; I : longint; begin Randomize; C:=New(PStringCollection,Init(120,10)); C^.Duplicates:=True; { Duplicates allowed } Writeln ('Inserting 100 records at random places.'); For I:=1 to 100 do begin Str(Random(100),S); S:='String with value '+S; C^.Insert(NewStr(S)); end; For I:=0 to 98 do With C^ do If Compare (At(i),At(I+1))=0 then Writeln ('Duplicate string found at position ',i); Dispose(C,Done); end.
This method is primarily used in the Load and Store methods, and should not be used directly.
The TStrCollection object manages a sorted collection of null-terminated strings (pchar strings). To this end, it overrides the Compare method of TSortedCollection, and it introduces methods to read/write strings from a stream.
Here is the full declaration of the TStrCollection object:
TYPE TStrCollection = OBJECT (TSortedCollection) Function Compare (Key1, Key2: Pointer): Sw_Integer; Virtual; Function GetItem (Var S: TStream): Pointer; Virtual; Procedure FreeItem (Item: Pointer); Virtual; Procedure PutItem (Var S: TStream; Item: Pointer); Virtual; END; PStrCollection = ^TStrCollection;
This method is primarily introduced to be able to load and store the collection from and to a stream.
Program ex38; { Program to demonstrate the TStrCollection.Compare method } Uses Objects,Strings; Var C : PStrCollection; S : String; I : longint; P : Pchar; begin Randomize; C:=New(PStrCollection,Init(120,10)); C^.Duplicates:=True; { Duplicates allowed } Writeln ('Inserting 100 records at random places.'); For I:=1 to 100 do begin Str(Random(100),S); S:='String with value '+S; P:=StrAlloc(Length(S)+1); C^.Insert(StrPCopy(P,S)); end; For I:=0 to 98 do With C^ do If Compare (At(I),At(I+1))=0 then Writeln ('Duplicate string found at position ',I); Dispose(C,Done); end.
This method is primarily used in the Load and Store methods, and should not be used directly.
The TUnSortedStrCollection object manages an unsorted list of objects. To this end, it overrides the TSortedCollection.Insert method to add strings at the end of the collection, rather than in the alphabetically correct position.
Take care, the Search and IndexOf methods will not work on an unsorted string collection.
Here is the full declaration of the TUnsortedStrCollection object:
TYPE TUnSortedStrCollection = OBJECT (TStringCollection) Procedure Insert (Item: Pointer); Virtual; END; PUnSortedStrCollection = ^TUnSortedStrCollection;
Program ex39; { Program to demonstrate the TUnsortedStrCollection.Insert method } Uses Objects,Strings; Var C : PUnsortedStrCollection; S : String; I : longint; P : Pchar; begin Randomize; C:=New(PUnsortedStrCollection,Init(120,10)); Writeln ('Inserting 100 records at random places.'); For I:=1 to 100 do begin Str(Random(100),S); S:='String with value '+S; P:=StrAlloc(Length(S)+1); C^.Insert(StrPCopy(P,S)); end; For I:=0 to 99 do Writeln (I:2,': ',PChar(C^.At(i))); Dispose(C,Done); end.
A TResourceCollection manages a collection of resource names. It stores the position and the size of a resource, as well as the name of the resource. It stores these items in records that look like this:
TYPE TResourceItem = packed RECORD Posn: LongInt; Size: LongInt; Key : String; End; PResourceItem = ^TResourceItem;
It overrides some methods of TStringCollection in order to accomplish this.
Remark that the TResourceCollection manages the names of the resources and their assiciated positions and sizes, it doesn't manage the resources themselves.
Here is the full declaration of the TResourceCollection object:
TYPE TResourceCollection = OBJECT (TStringCollection) Function KeyOf (Item: Pointer): Pointer; Virtual; Function GetItem (Var S: TStream): Pointer; Virtual; Procedure FreeItem (Item: Pointer); Virtual; Procedure PutItem (Var S: TStream; Item: Pointer); Virtual; END; PResourceCollection = ^TResourceCollection;
The resulting item is not inserted in the collection. This call is manly for internal use by the TCollection.Load method.
It does NOT remove the item from the collection.
This method is used primarily by the Store method.
TYPE TResourceFile = OBJECT (TObject) Stream : PStream; { File as a stream } Modified: Boolean; { Modified flag } Constructor Init (AStream: PStream); Destructor Done; Virtual; Function Count: Sw_Integer; Function KeyAt (I: Sw_Integer): String; Function Get (Key: String): PObject; Function SwitchTo (AStream: PStream; Pack: Boolean): PStream; Procedure Flush; Procedure Delete (Key: String); Procedure Put (Item: PObject; Key: String); END; PResourceFile = ^TResourceFile;
TResourceFile has the following fields:
Init will try to position the stream on the start of the resources section, and read all resources from the stream.
If Pack is true, then all the known resources will be copied from the current stream to the new stream (AStream). If Pack is False, then only the current resource is copied.
The return value is the value of the original stream: Stream.
The Modified flag is set as a consequence of this call.
A TStringList object can be used to read a collection of strings stored in a stream. If you register this object with the RegisterType function, you cannot register the TStrListMaker object.
This is the public declaration of the TStringList object:
TYPE TStrIndexRec = Packed RECORD Key, Count, Offset: Word; END; TStrIndex = Array [0..9999] Of TStrIndexRec; PStrIndex = ^TStrIndex; TStringList = OBJECT (TObject) Constructor Load (Var S: TStream); Destructor Done; Virtual; Function Get (Key: Sw_Word): String; END; PStringList = ^TStringList;
The TStrListMaker object can be used to generate a stream with strings, which can be read with the TStringList object. If you register this object with the RegisterType function, you cannot register the TStringList object.
This is the public declaration of the TStrListMaker object:
TYPE TStrListMaker = OBJECT (TObject) Constructor Init (AStrSize, AIndexSize: Sw_Word); Destructor Done; Virtual; Procedure Put (Key: SwWord; S: String); Procedure Store (Var S: TStream); END; PStrListMaker = ^TStrListMaker;
AStrSize must be large enough to contain all the strings you wish to store. If not enough memory is allocated, other memory will be overwritten. The same is true for AIndexSize : maximally AIndexSize strings can be written to the stream.