+ INitial implementation

This commit is contained in:
michael 1998-12-14 23:17:02 +00:00
parent 30fa4efbd4
commit 981e423a9e
2 changed files with 866 additions and 0 deletions

192
docs/heaptrc.tex Normal file
View File

@ -0,0 +1,192 @@
%
% $Id$
% This file is part of the FPC documentation.
% Copyright (C) 1998, by Michael Van Canneyt
%
% The FPC documentation is free text; you can redistribute it and/or
% modify it under the terms of the GNU Library General Public License as
% published by the Free Software Foundation; either version 2 of the
% License, or (at your option) any later version.
%
% The FPC Documentation is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
% Library General Public License for more details.
%
% You should have received a copy of the GNU Library General Public
% License along with the FPC documentation; see the file COPYING.LIB. If not,
% write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
% Boston, MA 02111-1307, USA.
%
\chapter{The HEAPTRC unit.}
This chapter describes the HEAPTRC unit for \fpc. It was written by
Pierre Muller.
\section{Purpose}
The HEAPTRC unit can be used to debug your memory allocation/deallocation.
It keeps track of the calls to getmem/freemem, and, implicitly, of
New/Dispose statements.
When the program exits, or when you request it explicitly.
It displays the total memory used, and then dumps a list of blocks that
were allocated but not freed. It also displays where the memory was
allocated.
If there are any inconsistencies, such as memory blocks being allocated
or freed twice, or a memory block that is released but with wrong size,
this will be displayed also.
The information that is stored/displayed can be customized using
some constants.
\section{Usage}
All that you need to do is to include \file{heaptrc} in the uses clause
of your program. Make sure that it is the first unit in the clause,
otherwise memory allocated in initialization code of units that precede the
heaptrc unit will not be accounted for, causing an incorrect memory usage
report.
The following example shows how to use the heaptrc unit.
\latex{\inputlisting{heapex/heapex.pp}}
\html{\input{heapex/heapex.tex}}
This is the memory dump shown when running this program:
\begin{verbatim}
Marked memory at 08052C48 invalid
Wrong size : 128 allocated 64 freed
0x0804C29C
0x080509E2
0x080480A4
0x00000000
Heap dump by heaptrc unit
13 memory blocks allocated : 1416/1424
6 memory blocks freed : 708/712
7 unfreed memory blocks : 708
True heap size : 2097152
True free heap : 2096040
Should be : 2096104
Call trace for block 0x08052C48 size 128
0x080509D6
0x080480A4
Call trace for block 0x08052B98 size 128
0x08050992
0x080480A4
Call trace for block 0x08052AE8 size 128
0x08050992
0x080480A4
Call trace for block 0x08052A38 size 128
0x08050992
0x080480A4
Call trace for block 0x08052988 size 128
0x08050992
0x080480A4
Call trace for block 0x080528D8 size 128
0x08050992
0x080480A4
Call trace for block 0x080528A0 size 4
0x08050961
0x080480A4
\end{verbatim}
\section{Constants, Types and variables}
The \var{fill\_extra\_info\_type} is a procedural type used in the
\seepl{Set\_Extra\_Info}{SetExtraInfo} call.
\begin{listing}
type
fill_extra_info_type = procedure(p : pointer);
\end{listing}
The following typed constants allow to fine-tune the standard dump of the
memory usage by \seepl{Dump\_Heap}{DumpHeap}:
\begin{listing}
const
tracesize = 8;
quicktrace : boolean = true;
halt_on_error : boolean = true;
keepreleased : boolean = false;
\end{listing}
\var{Tracesize} specifies how many levels of calls are displayed of the
call stack during the memory dump. If you specify \var{keepreleased:=True}
then half the \var{TraceSize} is reserved for the \var{GetMem} call stack,
and the other half is reserved for the \var{FreeMem} call stack.
For example, the default value of 8 will cause eight levels of call frames
to be dumped for the getmem call if \var{keepreleased} is \var{False}. If
\var{KeepReleased} is true, then 4 levels of call frames will be dumped for
the \var{GetMem} call and 4 frames wil be dumped for the \var{FreeMem} call.
If you want to change this value, you must recode the \file{heaptrc} unit.
\var{Quicktrace} determines whether
If \var{halt\_on\_error} is set to \var{True} then an illegal call to
\var{FreeMem} will cause the memory manager to execute a \var{halt(1)}
instruction, causing a memory dump.
If \var{keepreleased} is set to true, then a list of freed memory
blocks is kept. This is useful if you suspect that the same memory block is
released twice. However, this option is very memory intensive, so use it
sparingly, and only when it's really necessary.
\section{Functions and procedures}
\begin{procedurel}{Dump\_Heap}{DumpHeap}
\Declaration
procedure Dump\_Heap;
\Description
\var{dump\_heap} dumps to standard output a summary of memory usage.
It is called automatically by the heaptrc unit when your program exits
(by instaling an exit procedure), but it can be called at any time
\Errors
None.
\SeeAlso
\seepl{Mark\_Heap}{MarkHeap}
\end{procedurel}
\begin{procedurel}{Mark\_Heap}{MarkHeap}
\Declaration
procedure Mark\_Heap;
\Description
\var{Mark\_Heap} marks all memory blocks with a special signature.
You can use this if you think that you corruped the
\Errors
None.
\SeeAlso
\seepl{Dump\_Heap}{DumpHeap}
\end{procedurel}
\begin{procedurel}{Set\_Extra\_Info}{SetExtraInfo}
\Declaration
procedure Set\_Extra\_Info( size : longint;func : fill\_extra\_info\_type);
\Description
You can use \var{Set\_Extra\_Info} to store extra info in the blocks that
the heaptrc unit reserves when tracing getmem calls. \var{Size} indicates the
size (in bytes) that the trace mechanism should reserve for your extra
information. For each call to \var{getmem}, \var{func} will be called,
and passed a pointer to the memory reserved.
When dumping the memory summary, the extra info is shown as Longint values.
\Errors
You can only call \var{Set\_Extra\_Info} if no memroy has been allocated
yet. If memory was already allocated prior to the call to
\var{Set\_Extra\_Info}, then an error will be displayed on standard error
output, and a \seepl{Dump\_Heap}{DumpHeap} is executed.
\SeeAlso
\seepl{Dump\_Heap}{DumpHeap}
\end{procedurel}
\latex{\inputlisting{heapex/setinfo.pp}}
\html{\input{heapex/setinfo.tex}}
%
% $Log$
% Revision 1.1 1998-12-14 23:17:02 michael
% + INitial implementation
%
%

674
docs/objects.tex Normal file
View File

@ -0,0 +1,674 @@
%
% $Id$
% This file is part of the FPC documentation.
% Copyright (C) 1998, by Michael Van Canneyt
%
% The FPC documentation is free text; you can redistribute it and/or
% modify it under the terms of the GNU Library General Public License as
% published by the Free Software Foundation; either version 2 of the
% License, or (at your option) any later version.
%
% The FPC Documentation is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
% Library General Public License for more details.
%
% You should have received a copy of the GNU Library General Public
% License along with the FPC documentation; see the file COPYING.LIB. If not,
% write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
% Boston, MA 02111-1307, USA.
%
\chapter{The Objects unit.}
This chapte documents te \file{objects} unit. The unit was implemented by
many people, and was mainly taken from the FreeVision sources.
The methods and fields that are in a \var{Private} part of an object
declaration have been left out of this documentation.
\section{Constants}
The following constants are error codes, returned by the various stream
objects.
\begin{verbatim}
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 }
\end{verbatim}
These constants can be passed to constructors of file streams:
\begin{verbatim}
CONST
stCreate = $3C00; { Create new file }
stOpenRead = $3D00; { Read access only }
stOpenWrite = $3D01; { Write access only }
stOpen = $3D02; { Read/write access }
\end{verbatim}
The following constants are error codes, returned by the collection list
objects:
\begin{verbatim}
CONST
coIndexError = -1; { Index out of range }
coOverflow = -2; { Overflow }
\end{verbatim}
Maximum data sizes (used in determining how many data can be used.
\begin{verbatim}
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 }
\end{verbatim}
\section{Types}
The follwing auxiliary types are defined:
\begin{verbatim}
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;
\end{verbatim}
The following records are used internaly for easy type conversion:
\begin{verbatim}
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;
\end{verbatim}
The following record is used when streaming objects:
\begin{verbatim}
TYPE
PStreamRec = ^TStreamRec;
TStreamRec = Packed RECORD
ObjType: Sw_Word;
VmtLink: pointer;
Load : Pointer;
Store: Pointer;
Next : PStreamRec;
END;
\end{verbatim}
The \var{TPoint} basic object is used in the \var{TRect} object (see
\sees{TRect}):
\begin{verbatim}
TYPE
PPoint = ^TPoint;
TPoint = OBJECT
X, Y: Sw_Integer;
END;
\end{verbatim}
\section{TRect}
\label{se:TRect}
The \var{TRect} object is declared as follows:
\begin{verbatim}
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;
\end{verbatim}
\begin{function}{TRect.Empty}
\Declaration
Function TRect.Empty: Boolean;
\Description
\var{Empty} returns \var{True} if the rectangle defined by the corner points
\var{A}, \var{B} has zero or negative surface.
\Errors
None.
\SeeAlso
\seef{TRect.Equals}, \seef{TRect.Contains}
\end{function}
\latex{\inputlisting{objectex/ex1.pp}}
\html{\input{objectex/ex1.tex}}
\begin{function}{TRect.Equals}
\Declaration
Function TRect.Equals (R: TRect): Boolean;
\Description
\var{Equals} returns \var{True} if the rectangle has the
same corner points \var{A,B} as the rectangle R, and \var{False}
otherwise.
\Errors
None.
\SeeAlso
\seef{TRect.Empty}, \seef{TRect.Contains}
\end{function}
For an example, see \seef{TRect.Empty}
\begin{function}{TRect.Contains}
\Declaration
Function TRect.Contains (P: TPoint): Boolean;
\Description
\var{Contains} returns \var{True} if the point \var{P} is contained
in the rectangle (including borders), \var{False} otherwise.
\Errors
None.
\SeeAlso
\seep{TRect.Intersect}, \seef{TRect.Equals}
\end{function}
\begin{procedure}{TRect.Copy}
\Declaration
Procedure TRect.Copy (R: TRect);
\Description
Assigns the rectangle R to the object. After the call to \var{Copy}, the
rectangle R has been copied to the object that invoked \var{Copy}.
\Errors
None.
\SeeAlso
\seep{TRect.Assign}
\end{procedure}
\latex{\inputlisting{objectex/ex2.pp}}
\html{\input{objectex/ex2.tex}}
\begin{procedure}{TRect.Union}
\Declaration
Procedure TRect.Union (R: TRect);
\Description
\var{Union} enlarges the current rectangle so that it becomes the union
of the current rectangle with the rectangle \var{R}.
\Errors
None.
\SeeAlso
\seep{TRect.Intersect}
\end{procedure}
\latex{\inputlisting{objectex/ex3.pp}}
\html{\input{objectex/ex3.tex}}
\begin{procedure}{TRect.Intersect}
\Declaration
Procedure TRect.Intersect (R: TRect);
\Description
\var{Intersect} makes the intersection of the current rectangle with
\var{R}. If the intersection is empty, then the rectangle is set to the empty
rectangle at coordinate (0,0).
\Errors
None.
\SeeAlso
\var{TRect.Union}
\end{procedure}
\latex{\inputlisting{objectex/ex4.pp}}
\html{\input{objectex/ex4.tex}}
\begin{procedure}{TRect.Move}
\Declaration
Procedure TRect.Move (ADX, ADY: Sw\_Integer);
\Description
\var{Move} moves the current rectangle along a vector with components
\var{(ADX,ADY)}. It adds \var{ADX} to the X-coordinate of both corner
points, and \var{ADY} to both end points.
\Errors
None.
\SeeAlso
\seep{TRect.Grow}
\end{procedure}
\latex{\inputlisting{objectex/ex5.pp}}
\html{\input{objectex/ex5.tex}}
\begin{procedure}{TRect.Grow}
\Declaration
Procedure TRect.Grow (ADX, ADY: Sw\_Integer);
\Description
\var{Grow} expands the rectangle with an amount \var{ADX} in the \var{X}
direction (both on the left and right side of the rectangle, thus adding a
length 2*ADX to the width of the rectangle), and an amount \var{ADY} in
the \var{Y} direction (both on the top and the bottom side of the rectangle,
adding a length 2*ADY to the height of the rectangle.
X and Y can be negative. If the resulting rectangle is empty, it is set
to the empty rectangle at \var{(0,0)}.
\Errors
None.
\SeeAlso
\seep{TRect.Move}.
\end{procedure}
\latex{\inputlisting{objectex/ex6.pp}}
\html{\input{objectex/ex7.tex}}
\begin{procedure}{TRect.Assign}
\Declaration
Procedure Trect.Assign (XA, YA, XB, YB: Sw\_Integer);
\Description
\var{Assign} sets the corner points of the rectangle to \var{(XA,YA)} and
\var{(Xb,Yb)}.
\Errors
None.
\end{procedure}
For an example, see \seep{TRect.Copy}.
\section{TObject}
\label{se:TObject}
The full declaration of the \var{TObject} type is:
\begin{verbatim}
TYPE
TObject = OBJECT
CONSTRUCTOR Init;
PROCEDURE Free;
DESTRUCTOR Done;Virtual;
END;
PObject = ^TObject;
\end{verbatim}
\begin{procedure}{TObject.Init}
\Declaration
Constructor TObject.Init;
\Description
Instantiates a new object of type \var{TObject}. It fills the instance up
with Zero bytes.
\Errors
None.
\SeeAlso
\seep{TObject.Free}, \seep{TObject.Done}
\end{procedure}
For an example, see \seep{TObject.Free}
\begin{procedure}{TObject.Free}
\Declaration
Procedure TObject.Free;
\Description
\var{Free} calls the destructor of the object, and releases the memory
occupied by the instance of the object.
\Errors
No checking is performed to see whether \var{self} is \var{nil} and whether
the object is indeed allocated on the heap.
\SeeAlso
\seep{TObject.Init}, \seep{TObject.Done}
\end{procedure}
\latex{\inputlisting{objectex/ex7.pp}}
\html{\input{objectex/ex7.tex}}
\begin{procedure}{TObject.Done}
\Declaration
Destructor TObject.Done;Virtual;
\Description
\var{Done}, the destructor of \var{TObject} does nothing. It is mainly
intended to be used in the \seep{TObject.Free} method.
\Errors
None.
\SeeAlso
\seep{TObject.Free}, \seep{TObject.Init}
\end{procedure}
\section{TStream}
\label{se:TStream}
The \var{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
descendant types.
Programs should not instantiate objects of type TStream directly, but
instead instantiate a descendant type.
This is the full declaration of the \var{TStream} object:
\begin{verbatim}
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;
\end{verbatim}
\section{TDosStream}
\label{se:TDosStream}
\begin{verbatim}
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;
\end{verbatim}
\section{TBufStream}
\label{se:TBufStream}
\begin{verbatim}
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;
\end{verbatim}
\section{TMemoryStream}
\section{se:TMemoryStream}
\begin{verbatim}
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;
PRIVATE
FUNCTION ChangeListSize (ALimit: Sw_Word): Boolean;
END;
PMemoryStream = ^TMemoryStream;
\end{verbatim}
\section{TCollection}
\label{se:TCollection}
\begin{verbatim}
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;
\end{verbatim}
\section{TSortedCollection}
\label{se:TSortedCollection}
\begin{verbatim}
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;
\end{verbatim}
\section{TStringCollection}
\label{se:TStringCollection}
\begin{verbatim}
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;
\end{verbatim}
\section{TStrCollection}
\label{se:TStrCollection}
\begin{verbatim}
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;
\end{verbatim}
\section{TUnSortedStrCollection}
\label{se:TUnSortedStrCollection}
\begin{verbatim}
TYPE
TUnSortedStrCollection = OBJECT (TStringCollection)
PROCEDURE Insert (Item: Pointer); Virtual;
END;
PUnSortedStrCollection = ^TUnSortedStrCollection;
\end{verbatim}
\section{TResourceCollection}
\label{se:TResourceCollection}
\begin{verbatim}
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;
\end{verbatim}
\section{TResourceFile}
\label{se:TResourceFile}
\begin{verbatim}
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;
\end{verbatim}
\section{TStringList}
\label{se:TStringList}
\begin{verbatim}
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;
\end{verbatim}
\section{TStrListMaker}
\label{se:TStrListMaker}
\begin{verbatim}
TYPE
TStrListMaker = OBJECT (TObject)
CONSTRUCTOR Init (AStrSize, AIndexSize: Sw_Word);
DESTRUCTOR Done; Virtual;
PROCEDURE Put (Key: Sw_Word; S: String);
PROCEDURE Store (Var S: TStream);
END;
PStrListMaker = ^TStrListMaker;
\end{verbatim}
\begin{verbatim}
FUNCTION NewStr (Const S: String): PString;
PROCEDURE DisposeStr (P: PString);
PROCEDURE Abstract;
PROCEDURE RegisterObjects;
PROCEDURE RegisterType (Var S: TStreamRec);
FUNCTION LongMul (X, Y: Integer): LongInt;
FUNCTION LongDiv (X: Longint; Y: Integer): Integer;
CONST
StreamError: Pointer = Nil; { Stream error ptr }
DosStreamError: Word = $0; { Dos stream error }
CONST
RCollection: TStreamRec = (
ObjType: 50;
VmtLink: Ofs(TypeOf(TCollection)^);
Load: @TCollection.Load;
Store: @TCollection.Store);
RStringCollection: TStreamRec = (
ObjType: 51;
VmtLink: Ofs(TypeOf(TStringCollection)^);
Load: @TStringCollection.Load;
Store: @TStringCollection.Store);
RStrCollection: TStreamRec = (
ObjType: 69;
VmtLink: Ofs(TypeOf(TStrCollection)^);
Load: @TStrCollection.Load;
Store: @TStrCollection.Store);
RStringList: TStreamRec = (
ObjType: 52;
VmtLink: Ofs(TypeOf(TStringList)^);
Load: @TStringList.Load;
Store: Nil);
RStrListMaker: TStreamRec = (
ObjType: 52;
VmtLink: Ofs(TypeOf(TStrListMaker)^);
Load: Nil;
Store: @TStrListMaker.Store);
\end{verbatim}