Using the Conroy & Conroy Subroutine Library

Introduction

The Conroy & Conroy Co. Subroutine Library (hereinafter simply "the Subroutine
Library") was designed to allow rapid development of large applications in
Pascal under several different software environments including: MSDOS, 16-bit
Windows, and 32-bit Windows.  Further, in 32-bit Windows it serves in both
windowed and Console modes.  It alseo supports both Delphi and Borland Pascal
V7 for most of the code.  finally, it is designed to allow any Borland Pascal V7
code to compile under Delphi, although the opposite may not be true.  These
goals are supported by the use of the EDefines.inc file, which defines various
conditional compilation directives used by the modules of the Subroutine
Library.

Filename and Identifier Conventions

For readability, the coding standards used by Conroy & Conroy Company define
identifier naming conventions of mixed case (init-capped) identifiers with
underscores used to separate words within identifiers.  All-uppercase
identifiers are used for acronyms (such as CPU).  This convention allows one to
tell, at a glance, if the identifier is a Subroutine library identifier or one
from Windows, Borland, or other third-party code.

Filenames are limited to 8.3 notation for compatibility with Borland Pascal and
older versions of MSDOS.  However, files which are specific to Windows 95 (and
later) have names that are fully-spelled out and use the same conventions as
identifier names.  In the case where the filename (and thus, unit name) are in
conflict with some common identifier (such as String), an "s" is appended to the
end of the name (such as Strings.pas).  For abstract class definitions (pure
virtual classes, in C++ parlance), the filename begins with an underscore.
Including a reference to one of these files does not link in any significant
code, although other abstract definitions may be pulled into the compilation.

Hungarian notation is not used.  However, all type definitions begin with "T" to
distinguish them from other identifiers.  Futher, if a class is a static class,
the "T" is followed by "S".  Otherwise, the class is assumed to be dynamic.  In
most cases, both types of class are defined, where the dynamic version is a
wrapper for the static version.  Thus, you can use either version in Delphi.
For classes that descend from the common COM interface, the class name starts
with "TCOM_" (see "object model" for more information).  Finally, "P" is used to
denote the type of: a pointer to an object ("PS" indicates a pointer to a static
object).


Conditional Compilation

Certain conditional compilation symbols are reserved for use in the Subroutine
Library.  They are described as follows:

Debug   When set, the code does various sanity and consistency checks to catch
        various coding problems - especially memory corruptions.  Should (only)
        be used when running complete tests on code, or when trying to track
        down difficult problems.
Test    Automatically runs regression tests.


Subroutine Library Layers

The Subroutine Library is organized into layers.  Each layer represents a group
of related functionality.  Dependancy rules require that units only reference
units that are in the same, or a lower, layer.  The lowest layer is layer 0,
which has no dependencies except on the the VCL (for Delphi) and standard Pascal
units.


Layer 0 - The Object Model

The Subroutine Libray layers additional features on top of the standard Borland
object model.  The Subroutine Library object model is one of emancipated
objects.  Emancipated objects are not "owned" by any other object or code.
Although constructed by other code, they are never directly destructed by other
code.  Instead, the other code attaches to and detaches from instances of these
objects.  When an object detects that it is no longer referenced by anything, it
destructs itself.  Therefore, proper usage of Subroutine Lirbary objects is to
attach to an object after creating it, or when an object is passed to some code.
When code is done with an object it has attached to, it detaches from it.  There
should always be matching attaches and detaches to objects.  Code should never
attach or detach on behalf of other code as this requires knowledge of the
internal workings of other code (this is called coupling).

There are three different types of classes used by the Subroutine Library:
Dynamic objects are allocated on the heap and are defined with the class
keyword.  Static objects (the only kind supported by Borland Pascal), are
allocated in the data segment or on the stack and are defined with the object
keyword.  COM clases are Dynamic objects, but use stdcall calling convention
and use PChar in place of string in parameters and function results.  They are
used for objects that are passed between different code units, such as between
DLLs.  COM classes specifically match the Application Foundation Common COM
Interface standard, defined by the TCommon_COM_Interface class.  It is important
that TCommon_COM_Interface objects never be explicitly destructed since they may
have been constructed on a different heap.  Thus, they must always be attached
to and detached from.  This class will be described in more detail later.

_Common.pas contains the definitions of the base emancipated classes: TObject
for static objects and TDelphi_Object for dynamic objects.  COMInter.pas
contains the COM object definition, TCommon_COM_Interface.  _Common also
implements the Abstract_Error procedure which can be called from any
conceptually abstract class method to cause a run-time error if the said method
is invoked.

Delphi supports RTTI on objects, however earlier versions of Pascal do not.
Therefore, TObject supports Classname and Is_Class methods.  For compatibility,
TDelphi_Object also has an Is_Class method.

All classes defined in the Subroutine Library descend from one of these three
base classes, or from a Borland VCL class.  Common.pas contains implementations
of TObject and TDelphi_Object (called TBase_Object and TBase_Delphi_Object,
respectively) from which all new classes should descend, and from which most
Subroutine Library classes descend.  These classes are refered to as the "base"
Subroutine Library objects.  The base objects add the following standard
capabilities to the object model: dynamic properties, serialization,
persistance, debugging, and testing.  Testing is supported via the Test method.

In the base class, Test simply verifies the operation of Attach and Detach.
Descendants should override Test to do specific tests of the descendant, and
then should call the inherited Test to ensure that base class functionality has
not been broken by the descendant.

Debugging support is implemented via the Debugger method, which returns an
instance of the TSDebug_Interface, or TDebug_Interface.  TSDebug_Interface is a
static version of TDebug_Interface, which is an Application Foundation standard.

The Clone function constructs an exact copy of the object on the heap and
returns a pointer to it.  If cloning of the object is not supported, the Clone
method returns nil.


Basic Types

Some basic data types are defined in _Types.pas, both for compatibility and as a
help to the developer.  These types are:

Type      Description
----      -----------
int8      Signed 8-bit integer (shortint).
uint8     Unsigned 8-bit integer (byte).
int16     Signed 16-bit integer (smallint).
uint16    Unsigned 16-bit integer (word).
int32     Signed 32-bit integer (longint).
uint32    Unsigned 32-bit integer (cardinal) - Delphi only.
int64     Signed 64-bit integer.  In Borland Pascal, this is equivalent to Comp.

smallint  Defined for Borland Pascal.  Equivalent to Delphi smallint.


Additional data types are defined in TypeDefs.pas.  These types are:

Type                  Description
----                  -----------
TComparison           Scalar: LessThan, EqualTo, GreaterThan, LessThanOrEqual,
                              GreaterThanorEqual, NotEqualTo
TTri_State            Scalar: TS_False, TS_True, TS_Dont_Care
TClick_Notify_Event   Delphi only: procedure( Sender : TObject ;
                                       Point : TSmallPoint ) of object
TCommand_Event        Delphi only: procedure( Sender : TObject ;
                                       Command : integer ) of object
TPaint_Notify_Event   Delphi only: procedure( Sender : TObject ;
                                       Beginning : Boolean ) of object
TRequest_Data_Event   Delphi only: procedure( Sender : TObject ;
                                       Top : Boolean ) of object
TNotify_Blink_Event   Delphi only: procedure( Rect : TRect ) of object
TArrayOfInteger       Delphi only: Array of integer
Max_Memory            Maximum amount of memory, theoretical, that can be
                      allocated in a single allocation (DOS/32-bit Windows)
Zero64                0 in int64 format.
Max_String_Length     Maximum length of type string.
TRecord_Size          Integer of size sufficient for block reads/writes.
pByte                 Pointer to byte.
tByte_Array           Type of a byte array of the largest size that can be
                      allocated in memory.
pByte_Array           Pointer to tByte_Array.
pShortInt             Pointer to ShortInt.
tShortInt_Array       Type of a ShortInt array of the largest size that can be
                      allocated in memory.
pShortInt_Array       Pointer to TShortInt_Array.
pWord                 Pointer to a Word.
tWord_Array           Type of a word array of the largest size that can be
                      allocated in memory.
pWord_Array           Pointer to tWord_Array.
pInteger              Pointer to an Integer.
tInteger_Array        Type of an integer array of the largest size that can be
                      allocated in memory.
pInteger_Array        Pointer to tInteger_Array.
pLongint              Pointer to Longint.
tLongint_Array        Type of a Longint array of the largest size that can be
                      allocated in memory.
pLongint_Array        Pointer to tLongint_Array.
pReal                 Pointer to a Real.
tReal_Array           Type of a Real array of the largest size that can be
                      allocated in memory.
pReal_Array           Pointer to a TReal_Array.
pSingle               Pointer to a Single.
tSingle_Array         Type of a Single array of the largest size that can be
                      allocated in memory.
pSingle_Array         Pointer to a TSingle_Array.
pDouble               Pointer to a Double.
tDouble_Array         Type of a Double array of the largest size that can be
                      allocated in memory.
pDouble_Array         Pointer to a TDouble_Array.
tExtended_Array       Type of an Extended array of the largest size that can be
                      allocated in memory.
pExtended_Array       Pointer to a TExtended_Array.
pComp                 Pointer to a Comp.
tComp_Array           Type of a Comp array of the largest size that can be
                      allocated in memory.
pComp_Array           Pointer to a tComp_Array.
pPointer              Pointer to a Pointer.
tPointer_Array        Type of a pointer array of the largest size that can be
                      allocated in memory.
pPointer_Array        Pointer to a tPointer_Array.
tPChar_Array          Type of a PChar array of the largest size that can be
                      allocated in memory.
pPChar_Array          Pointer to a tPChar_Array.
tChar_Array           Type of a Char array of the largest size that can be
                      allocated in memory.
pChar_Array           Pointer to a tChar_Array.
pFile                 Pointer to a File.
tFile_Array           Type of a file array of the largest size that can be
                      allocated in memory.
pFile_Array           Pointer to a tFile_Array.
pText                 Pointer to a Text (file).
tText_Array           Type of a text (file) array of the largest size that can be
                      allocated in memory.
pText_Array           Pointer to a tText_Array.
pString               Pointer to a string (in Delphi this is a synonym of
                      string).
AnsiChar              In Borland Pascal, synonym of Char.
TextFile              In Borland Pascal, synonym of text.
Real48                In Borland Pascal, synonym of Real.
pExtended             In Borland Pascal, a pointer to Extended ;
pByteArray            In Borland Pascal, synonym of pByte_Array.
pWordArray            In Borland Pascal, synonym of pWord_Array.
tString_Array         Type of a string array of the largest size that can be
                      allocated in memory.
pString_Array         Pointer to a tString_Array.
pSmall_String         Pointer to a Small_String.
tSmall_String_Array   Type of a small_string array of the largest size that can
                      be allocated in memory.
pSmall_String_Array   Pointer to a tSmall_String_Array.
pBoolean              Pointer to Boolean ;
tBoolean_Array        Type of a boolean array of the largest size that can
                      be allocated in memory.
pBoolean_Array        Pointer to a TBoolean_Array.
pByteBool             Pointer to a ByteBool/
tByteBool_Array       Type of a bytebool array of the largest size that can be
                      allocated in memory.
pByteBool_Array       Pointer to a TByteBool_Array.
pWordBool             Pointer to a WordBool.
tWordBool_Array       Type of a wordbool array of the largest size that can be
                      allocated in memory.
pWordBool_Array       Pointer to a TWordBool_Array.
pLongBool             Pointer to a LongBool.
tLongBool_Array       Type of a longbool array of the largest size that can be
                      allocated in memory.
pLongBool_Array       Pointer to a TLongBool_Array.
pReal48               Pointer to a Real48.
tReal48_Array         Type of a real48 array of the largest size that can be
                      allocated in memory.
pReal48_Array         Pointer to a tReal48_Array.

The following are unique to 32-bit Delphi:
Type                  Description
----                  -----------
pLongword             Pointer to Longword.
tLongword_Array       Type of a longword array of the largest size that can be
                      allocated in memory.
pLongword_Array       Pointer to a tLongword_Array.
pCardinal             Pointer to a Cardinal.
tCardinal_Array       Type of a cardinal array of the largest size that can be
                      allocated in memory.
pCardinal_Array       Pointer to a tCardinal_Array.
pInt64                Pointer to an Int64.
tInt64_Array          Type of an int64 array of the largest size that can be
                      allocated in memory.
pInt64_Array          Pointer to a tInt64_Array.
tCurrency_Array       Type of a currency array of the largest size that can be
                      allocated in memory.
pCurrency_Array       Pointer toa  tCurrency_Array.
tANSIString_Array     Type of an ANSIString array of the largest size that can
                      be allocated in memory.
pANSIString_Array     Pointer to a tANSIString_Array.
pWideChar             Pointer to a WideChar.
tWideChar_Array       Type of a widechar array of the largest size that can be
                      allocated in memory.
pWideChar_Array       Pointer to a tWideChar_Array.
tWideString_Array     Type of a widestring array of the largest size that can be
                      allocated in memory.
pWideString_Array     Pointer to a tWideString_Array.
tVariant_Array        Type of a variant array of the largest size that can be
                      allocated in memory.
pVariant_Array        Pointer to a tVariant_Array.
tOLEVariant_Array     Type of an OLEVariant array of the largest size that can
                      be allocated in memory.
pOLEVariant_Array     Pointer to a tOLEVariant_Array.


Strings

String functions and parameters in static classes are small strings (Borland
Pascal compatible).  Dynamic classes use Delphi large strings.  COM class
methods never use strings: all string functions or parameters used in the the
static and dynamic classes use PChars in the COM equivalents.  Furthermore, all
PChars passed into COM methods are never "held onto" by the method.  That is,
the PChar need only be valid during the call.  If the class needs to keep the
data, it must make a copy of it.  Finally, any PChar returned by a COM method is
only valid until the next call to that object.


Serialization

Serialization is the process of converting the contents of an object into a
stream of text.  Deserialization takes a serialized stream of text and sets up
an object from that.  The stream of text must meet certain criteria:
1. No byte can be outside of the range of 32 to 126, inclusive.  The only
   exceptions are 10 and 13, as described in the next point.
2. If the stream is longer than 80 bytes long, there must be ASCII 13 values to
   terminate each segment of 80, or less, bytes.  ASCII 10 is allowed, but
   ignored, after an ASCII 13.
3. The contents of the stream must consist of well-formed XML.
4. If the object's state includes another object, then that included object
   should be serialized and embedded within the parent object's serialization
   stream.


Persistance

Perisistance is the process of saving the state of an object in binary form.
The Load method is used to restore an object from a persisted binary form.  Note
that the contents of the binary form is entirely up to the object, and could be
equivalent to a serialization stream.


Dynamic Properties

Dynamic Properties are lists of named values which serve as run-time (dynamic)
properties that the user of a class can associate with an object.  Each property
in the list is a string name and TGeneric_Value pair.  TSDynamic_Properties and
TDynamic_Properties descend directly from the _Common base classes since the
base classes use them.  Dynamic Property values use Generic Values to store, and
return, various data types.  Property names are case insensitive.  The Dynamic
Property methods are:

        function Add( const Nam : string ; Value : PSGeneric_Value ) : longint ;

        Thie method adds a new property, returning the index.  It returns -1 if
        a property already exists by that name.


        procedure Clear ;

        This method deletes all properties.


        function Count : longint ;

        This method returns the count of currently defined properties.


        function Index_Of( const Nam : string ) : longint ;

        This method returns the index of the property with the specified name.
        It returns -1 if the named property doesn't exist.  The first property
        is index 0.


        function Get_Name( Index : longint ) : string ;

        This method retrieves string name of property with given index.  If
        index is invalid, returns a null string.


        function Get_Value( Index : longint ) : PSGeneric_Value ;

        This method returns the value for the property at the specified index.
        Returns nil if the index is invalid.


        procedure Set_Value( Index : longint ; Value : PSGeneric_Value ) ;

        This method sets the value for the specified index.  It does nothing if
        the index is invalid.



Generic Values

Generic Values are much like variants, but are more powerful.  They provide a
means of transferring any type of data, including type information on the data.
Further, they can be used to transfer type definitions.   Default simple generic
value objects can be obtained from the Object Factory, which uses the simple
generic data types from GenVal by default.

Any value can be considered to belong to one of the following data type
families (as defined by the TData_Type_Family enumeration):

Value            Meaning
-----            -------
DTF_Unknown      Variant
DTF_Undefined    Binary
DTF_Logical
DTF_Numeric
DTF_Character    Character/string
DTF_Pointer      pointer/method/procedure/function
DTF_Composite
DTF_Collection
DTF_User_Defined
DTF_Meta         Data type
DTF_Other        Anything not defined above


Every value also has a defined data type, as defined by TValue_Data_Type:


Value            Meaning
-----            -------
VDT_Empty        No data associated with the value
VDT_Null         Null value (not necessarily nil)
VDT_Boolean      True/False
VDT_Integer      2's Complement integer
VDT_Real         Number
VDT_String       0 or more characters
VDT_Char         Single-character
VDT_Pointer      Any kind of pointer value
VDT_Value        TGeneric_Value defining a type
VDT_Code         Function or procedure
VDT_Scalar       Enumerations
VDT_User_Defined
VDT_Unknown      Anything not defined above


TSGeneric_Value, TGeneric_Value, and TCOM_Generic_Value are the abstract class
definitions for generic values.  The GenVal implementations are
TSSimple_Generic_Value, TSimple_Generic_Value, and TCOM_Simple_Generic_Value.
The following defines the methods in the generic value classes:

Meta type information: These methods return information describing the data.

        function Family : TData_Type_Family ;

        Returns the family of this value.


        function Data_Type : TValue_Data_Type ;

        Returns the data type of this value.


        function User_Data_Type_Name : string ;

        For values of family DTF_User_Defined, this is the name of the data
        type.  Otherwise, this returns a null string.


        function Name : string ;

        Returns the name of this value, whether it is a variable, type, method,
        or parameter name.  This returns null for any other type of value.


        function Type_Information : TType_Information ;

        Returns a type information object for this value.


Type Information: These methods return information on the actual data.

        function Constant : boolean ;

        Returns True if the value is a constant rather than variable.  Constant
        values cannot be modified.


        function Size : longint ;

        Returns the size in bytes of the value, in bytes.  Note that if the size
        is not a multiple of 8 bits, this returns the number of bytes, rounding
        the number of bits up to the nearest byte.


        function Total_Size : longint ;

        Returns the size of all associated data, in bytes.  For instance, Size
        may return the size of an object but Total_Size also includes the size
        of any associated data.


        function Dereference : TGeneric_Value ;

        This returns nil except for pointers values, in which case it returns a
        value representing the dereferenced pointer.


Type Conversions: These methods handle conversions, promotions, casts, etc.

        function Can_Convert( Typ : TValue_Data_Type ) : boolean ;

        Returns True if value can be converted to the specified data type.


        function Convert( Class_Type : TGeneric_Value ; var Loss : boolean ) : TGeneric_Value ;

        Return a version of the value converted to the passed type
        specification.  Returns nil if the conversion cannot be done.  Loss is
        ignored when passed and is True on return if there was a loss of
        precision.


        procedure Simple_Cast( Typ : TValue_Data_Type ) ;

        This converts the value to the passed type.  This only works if
        Can_Convert returns tru for the specified type.


        procedure Cast( Typ : TGeneric_Value ) ;

        This converts the value to the type of the passed value.


Data access: These methods allow calling code to obtain and modify the actual
data of the value.  Note that constant values cannot be modified.  When
required, and possible, type conversion will happen.  For instance, requesting a
real version of an integer will work so long as the integer value is within the
range of the requested real.  Setting a value via one of these routines not only
sets the value, but also sets the data type appropriately.

        procedure Set_Null ;

        Sets the value to VDT_Null.


        procedure Get_Undefined( Buffer : pointer ; Len : longint ) ;

        Obtains a binary image of the data, placing it in the specified buffer,
        and reading Len bytes.  If Len is larger than the data size, only the
        number of bytes in the data is copied.


        procedure Set_Undefined( Buffer : pointer ; Len : longint ) ;

        Sets the value to VDT_Undefined, and copies Len bytes from the specified
        buffer into the value.


        function Get_Boolean : boolean ;

        Returns value as a boolean.


        procedure Set_Boolean( B : boolean ) ;

        Sets the value to the specified boolean value.


        function Get_ByteBool : bytebool ;

        Returns value as a 1-byte boolean.


        procedure Set_ByteBool( B : bytebool ) ;

        Sets the value to the specified 1-byte boolean. value


        function Get_WordBool : wordbool ;

        Returns value as a 2-byte boolean.


        procedure Set_WordBool( B : wordbool ) ;

        Sets the value to the specified 2-byte boolean value.


        function Get_LongBool : longbool ;

        Returns value as a 4-byte boolean.


        procedure Set_LongBool( B : longbool ) ;

        Sets the value to the specified 4-byte boolean value.


        function Get_Char : char ;

        Returns the value as a 1-byte character.


        procedure Set_Char( C : char ) ;

        Sets the value to the specified 1-byte character.


        function Get_String : string ;

        Returns the value as a string.


        procedure Set_String( const S : string ) ;

        Sets the value to the specified string value.


        function Get_PChar : PChar ;

        Returns the value as a PChar.


        procedure Set_PChar( P : PChar ) ;

        Sets the value to the specified PChar value.  Note that the value points
        to the PChar data - it is not copied.


        function Get_Integer8 : int8 ;

        Returns the value as a signed 8-bit integer.


        procedure Set_Integer8( I : int8 ) ;

        Sets the value to the specified signed 8-bit integer value.


        function Get_Integer16 : int16 ;

        Returns the value as a signed 16-bit integer.


        procedure Set_Integer16( I : int16 ) ;

        Sets the value to the specified signed 16-bit integer value.


        function Get_Integer32 : int32 ;

        Returns the value as a signed 32-bit integer.


        procedure Set_Integer32( I : int32 ) ;

        Sets the value to the specified signed 32-bit integer value.


        function Get_Integer64 : int64 ;

        Returns the value as a signed 64-bit integer.


        procedure Set_Integer64( I : int64 ) ;

        Sets the value to the specified signed 64-bit integer value.


        function Get_Unsigned_Integer8 : uint8 ;

        Returns the value as an unsigned 8-bit integer.


        procedure Set_Unsigned_Integer8( I : uint8 ) ;

        Sets the value to the specified unsigned 8-bit integer value.


        function Get_Unsigned_Integer16 : uint16 ;

        Returns the value as an unsigned 16-bit integer.


        procedure Set_Unsigned_Integer16( I : uint16 ) ;

        Sets the value to the specified unsigned 16-bit integer value.


        function Get_Unsigned_Integer32 : uint32 ;

        Returns the value as an unsigned 32-bit integer.


        procedure Set_Unsigned_Integer32( I : uint32 ) ;

        Sets the value to the specified unsigned 32-bit integer value.


        function Get_Single : single ;

        Returns the value as a single-precision (4-byte) floating-point value.


        procedure Set_Single( S : single ) ;

        Set the value to the passed single-precision (4-byte) floating-point
        value.


        function Get_Double : double ;

        Returns the value as a double-precision (8-byte) floating-point value.


        procedure Set_Double( D : double ) ;

        Set the value to the passed double-precision (8-byte) floating-point
        value.


        function Get_Extended : extended ;

        Returns the value as a extended-precision (10-byte) floating-point
        value.


        procedure Set_Extended( E : extended ) ;

        Set the value to the passed extended-precision (10-byte) floating-point
        value.


Properties: The following properties are for ease of use in Delphi:

property            read                          write
--------            ----                          -----
Bool                Get_Boolean                   Set_Boolean
Byte_Bool           Get_ByteBool                  Set_ByteBool
Word_Bool           Get_WordBool                  Set_WordBool
Long_Bool           Get_LongBool                  Set_LongBool
_Char               Get_Char                      Set_Char
_String             Get_String                    Set_String
_PChar              Get_PChar                     Set_PChar
Integer8            Get_Integer8                  Set_Integer8
Unsigned_Integer8   Get_Unsigned_Integer8         Set_Unsigned_Integer8
Integer16           Get_Integer16                 Set_Integer16
Unsigned_Integer16  Get_Unsigned_Integer16        Set_Unsigned_Integer16
Integer32           Get_Integer32                 Set_Integer32
Unsigned_Integer32  Get_Unsigned_Integer32        Set_Unsigned_Integer32
Integer64           Get_Integer64                 Set_Integer64
_Single             Get_Single                    Set_Single
_Double             Get_Double                    Set_Double
_Extended           Get_Extended                  Set_Extended


The Type_Information method returns an instance of the Type Information class,
which contains the following methods:

        function Is_Composite : boolean ;

        Returns True if an array/queue/list/stack of Data_Type.


        function Is_Collection : boolean ;

        Returns True if an object or record (structure).


        function Memory_Type : TMemory_Type ;

        Returns the type of memory in which this data resides.


        function Parameter : TGeneric_Parameter ;

        Returns nil if the value is not a parameter.  Otherwise parameter
        information is returned.


        function Numeric_Information : TGeneric_Number ;

        Returns nil if the value is not numeric.  Otherwise numeric information
        is returned.


        function Character_Information : TGeneric_Character ;

        Returns nil if the value is not character or string.  Otherwise
        character information is returned.


        function Composite_Information : TGeneric_Composite ;

        Returns nil if the value is not an object/record,  Otherwise information
        on the composite data is returned.


        function Collection_Information : TGeneric_Collection ;

        Returns nil if the value is not a composite (eg array).  Otherwise
        information on the collection is returned.


        function Method : TGeneric_Method ;

        Returns nil if the value is not a class method.  Otherwise information
        on the method is returned.


        function _Property : TProperty_Information ;

        Returns nil if the value is not a property.  Otherwise property
        information is returned.


        function Address : longint ;

        Returns the memory address of the value.  Returns 0 if undefined, type,
        or parameter.


        function Range_Limited : boolean ;

        Returns True if value is limited to a range of values.  This is always
        true for scalars.


        function Low_Range : TGeneric_Value ;

        Returns a value indicating the low range of this value.  Returns nil if
        not range limited.


        function High_Range : TGeneric_Value ;

        Returns a value indicating the high range of this value.  Returns nil if
        not range limited.


        function Value_Name( Value : longint ) : string ;

        Returns the name for given ordinal value.  Returns a null string if the
        value is not a scalar or if Value is out of range.



The Parameter method returns a Generic Parameter object for parameter types,
which has the following methods:

        function Typ : TGeneric_Value ;

        Returns the Type of the parameter.


        function Output : boolean ;

        Returns True if the purpose of parameter is for returning data, not
        receiving data.


        function Constant : boolean ;

        Returns True if the parameter is constant.


        function Mechanism : TCall_Mechanism

        Returns the call mechanism for the parameter:

        Value            Meaning
        -----            -------
        CM_By_Value      Pass by value.
        CM_By_Reference  Pass by reference.
        CM_By_Name       Pass by name (not supported by Delphi or Borland
                         Pascal).


The Numeric_Information method returns a Generic Number object for numeric data,
which has the following methods:

        function Fixed : boolean ;

        Returns True if integer or fixed length real.

        function Signed : boolean ;

        Returns True if the value is signed, false if unsigned.


        function Mantissa_Size : longint ;

        Returns the size of the mantissa, in bits.


        function Exponent_Size : longint ;

        Returns the size of the exponent, in bits, for floating-point types (0
        for non-floating).


        function Fractional_Size : longint ;

        Returns the size of the fractional mantissa, in bits, for fixed-point
        types (0 for non-fixed).


The Character_Information method returns a Generic Character object for textual
data, which has the following methods:

        function Max_Length : longint ;

        Returns the maximum allowable length, in bytes (same as Length except
        for dynamic-length strings).


        function Fixed : boolean ;

        Returns True if fixed length text.  Always True for a character.


        function Length : longint ;

        Returns the text length, in bytes.


        function Logical_Length : longint ;

        Returns the text length, in characters.



The Composite_Information method returns a Generic Composite object for
composite data, which has the following methods:

        function Ancestor( index : longint ) : TGeneric_Value ;

        Returns a description of the Indexth ancestor of this type.  See
        Ancestor_Count.


        function Ancestor_Count : longint ;

        Returns the number of ancestors for this type.  If there are no
        ancestors, 0 is returned.  > 1 is returned in cases of multiple
        inheritance.


        function Ancestor_Class( Index : longint ) : TMethod_Class ;

        Returns how the Indexth ancestor was inherited:

        Value            Comments
        -----            --------
        MC_Private
        MC_Protected
        MC_Public
        MC_Published     Not applicable in this case.


        function Count : longint ;

        Returns the number of items in this composite.  This is the number of
        fields in a record, elements in a structure, or the number of methods
        and instance data items in a class.


        function Get_Item( Index : longint ) : TGeneric_Value ;

        Returns information on the the Indexth item in this composite.


The Collection_Information method returns a Generic Collection object for
collection data, which has the following methods:

        function Fixed : boolean ;

        Returns False if the value is a dynamic collection, and True otherwise.
        For instance, a typical static array would return True.  A typical
        Stack would return False.


        function Sparse : boolean ;

        Returns True if sparse array.  Returns False if not an array.


        function Subscripts : longint ;

        Returns the number of subscripts in the collection.  For instance, a 2D
        matrix would return 2; a non-nested queue would return 1.


        function Low_Bound( Subscript : longint ) : TGeneric_Value ;

        Returns the lower bound of the specified subscript for the composite
        data.  For non-arrays, this is always 0.  If an invalid subscript is
        passed, the result is undefined.


        function High_Bound( Subscript : longint ) : TGeneric_Value ;

        Returns the upper bound of the specified subscript for the composite
        data.  For non-arrays, this is always the number of elements in the
        composite data, minus 1.  If an invalid subscript is passed, the result
        is undefined.


        function Get_Subscript( Address : longint ) : TGeneric_Value ;

        Returns value from composite, viewing it as a flat one-dimensional
        array.  Note that Row_Major is ignored for this method, as it interprets
        the passed address as if the array were ordered right-to-left.  For
        instance, in a 2-dimension array where both subscripts range from 0 to 1
        (inclusive) then the following shows which address values correspond to
        which array elements:

        Address    Element
        -------    -------
        0          [0, 0]
        1          [0, 1]
        2          [1, 0]
        3          [1, 1]

        Passing an invalid address returns a value of VDT_Null.


        function Row_Major : boolean ;

        Returns True if the subscripts are left-to-right major.  The result is
        undefined when Subscripts < 2.


The Method method returns a Generic Method object for method values, which has
the following methods:

        function Is_Abstract : boolean ;

        Returns True if the method is abstract (pure virtual).


        function Is_Constructor : boolean ;

        Returns True if the method is a constructor.


        function Is_Destructor : boolean ;

        Returns True if the method is a destructor.


        function Is_Virtual : boolean ;

        Returns True if the method is virtual.


        function Static : boolean ;

        Returns True if the method is a static class method.


        function C_Order : boolean ;

        Returns True if the method uses C calling convention parameter order.


        function Standard : boolean ;

        Returns True if the method uses standard (stack) parameter passing.


        function Execute( Parameters : TGeneric_Value ) : TGeneric_Value ;

        Execute the method.  Returns the result of the method.  If the method is
        a procedure, nil is returned.


        function Compile_Time : boolean ;

        Return True if the routine can be evaluated a compile-time.


        function Count : longint ;

        Returns the number of parameters (run-time).


        function Max_Count : longint ;

        Returns maximum potential number of parameters.


        function Parameter( Index : integer ) : TGeneric_Value ;

        Returns parameter for specified index.


        function Target : boolean ;

        Returns True if a target function.  Returns False if an object function.


        function Method_Class : TMethod_Class ;

        Returns the class of the method.


The _Property method returns a Property Information object for property values,
which has the following methods:

        function Getter : TGeneric_Value ;

        Returns the "getter" method for the property.


        function Setter : TGeneric_Value ;

        Returns the "setter" method for the property.


        function Default : boolean ;

        Returns True if the method is the default method.

        

Streams

Streams are collections of serial data.  The TStream and TSStream classes define
an interface to data streams.  Various descendant classes can be used to store
and load streams from strings, files, the heap, etc.  Each stream object keeps
a pointer into the data stream that can be set and queried.  The Stream methods
are:

        function At_End : boolean ;

        This method returns True if the data pointer is at the end of the
        stream.


        procedure Read( var Buffer ; var _Size : longint ) ;

        This method reads the specified number of bytes (_Size) from the stream.
        _Size is modified on return to be the actual number of bytes
        transferred.  The position is left after the last read byte.


        procedure Read_Line( var Buffer ; var _Size : longint ) ;

        This method reads one line of input, up to the specified size (_Size) of
        the buffer.  The line is assumed to end at an ASCII 13 code.  The ASCII
        13 code is not included in the returned data.  _Size is modified on
        return to be the actual bytes transferred.  The position is left after
        the last read byte.


        procedure Seek( Position : longint ) ;

        This method positions the data pointer to the specified byte (Position)
        within streamed data.  The first position is 0.  Thus, Seek( 0 ) will
        position to the beginning of the data stream.


        function Size : longint ;

        This method returns the size of stream data, in bytes.  -1 indicate that
        the size is unknown or larger than 2^31.


        procedure Write( var Buffer ; _Size : longint ) ;

        This method writes the specified buffer, of the specified size (_Size)
        in bytes, to the stream starting at the current position.  The position
        is left after the last written byte.


        procedure Write_Line( Buffer : PChar ) ;

        This method writes the specified null-terminated text to the stream.  An
        ASCII code 13 is appended to the text on output.  The position is left
        after the last written byte.


The Object Factory

The Object Factory is a class that is used to provide certain utility objects
(such as Dynamic Property objects) without the Pascal compiler having to know
the source of the objects.  Include ObjectFa.pas in your application to make use
of the default Object Factory object.  This will also include the default
Dynamic Property classes.

You may provide your own object factory by implementing a descendant of the
class from _ObjectF.pas.  Then replace the global Object_Factory variable (in
_ObjectF.pas) with an instance of your descendant.  Whenever an object needs
dynamic properties or generic values, it will call this object to request them.



Standard Objects

As mentioned earlier, TBase_Object and TBase_Delphi_Object provide an
implementation of the object model as defined in the _Common unit.  These
classes are found in the Common unit.  They add the following methods:

        procedure Free ;

        destructs the object and, if the object resides on the heap, frees it
        from the heap.


        procedure Set_Memory_Type( MT : TMemory_Type ) ;

        Sets the memory type of the object instance, as follows:

        Value        Meaning
        -----        -------
        MT_Unknown   Don't know
        MT_Heap      Allocated on heap - always true for Delphi objects
        MT_Data      Data space or "Global" data
        MT_Stack     Stack or "Local" data
        MT_Code      Code space or "executable" - never applies to objects


        function Get_Memory_Type : TMemory_Type ;

        Returns the type of memory where this object resides.  See
        Set_Memory_Type for a description of memory types.


        function Reference_Count : integer ;

        Returns a reference count that is incremented with each Attach and
        decremented with each Detach.



Layer 1 - The Application Model

The Subroutine Library Application Model layers additional functionality on the
Object Model layer to provide basic application support.  All but the most
simple code will benefit from using this layer.


Debugger Support

The DebugInt unit implements Debug Interfaces conforming to the Application
Foundation Debugging Interface.  These classes implement simple text items for
a larger debugging tree.  That is, they do not provide children, activation
support, or data modification.  These classes are TSText_Debugger and
TText_Debugger (Delphi only).  Instances of these classes are provided by the
unit functions Create_Text_Debugger (returns a PSText_Debugger ) and
Create_Delphi_Text_Debugger (TText_Debugger).

Further, this unit provides some wrappers so that various types of debug
interfaces can be mixed seamlessly in an application.  The Static_Debug_Wrapper
takes a TCOM_Debug_Interface instance and returns a PSDebug_Interface wrapper
for the COM object.  Likewise, the Delphi_Debug_Wrapper function takes a
PSDebug_Interface instance and returns a TDebug_Interface wrapper for the static
object.


Application Manager

The application manager is an object which provides common application-wide
support.  The TApplication_Manager class is defined in the _App unit.  Also, the
global Application_Manager variable is in the _App unit.  The App unit includes
an implementation of an application manager.  Including the App unit will set
the global variable.  The application manager contains the following methods:

Status: These methods are used to indicate application status.

        function Get_In_Shut_Down : boolean ;

        Returns True if the application is shutting down.  This can be set
        manually, but will be set automatically when the App unit finalizes (if
        it is included).


        procedure Set_In_Shut_Down( Value : boolean ) ;

        Sets the Shut_Down flag to the passed value.


        function Get_Halting : boolean ;

        Returns True if the application is halting.


        procedure Set_Halting( Value : boolean ) ;

        Sets the halting flag to the passed value.


Debugging: These methods provide debugging support.

        function Get_Debug_Manager : PSDebug_Manager ;

        Returns a global debug manager instance.


        procedure Set_Debug_Manager( Value : PSDebug_Manager ) ;

        Sets the global debug manager instance to the passed value.


        function Application_Debugger : PSDebug_Interface ;

        Returns a debugger for the application.


        function Debugger : PSDebug_Interface ;

        Returns a debugger for the application manager object.


        function Object_Manager : PSObject_Manager ;

        Returns the global object manager instance.


Idle processing: These methods support idle-time processing.  Note that these
methods are reserved for future use.

        procedure Do_Idle ;

        procedure Add_Idle_Delegation( Value : PSIdle_Consumer ) ;

        procedure Remove_Idle_Delegation( Value : PSIdle_Consumer ) ;


Other methods:

        function Get_Event_Logger : PSApplication_Event_Logger ;

        Returns the global event logger instance.


        procedure Set_Event_Logger( EV : PSApplication_Event_Logger ) ;

        Sets the global event logger to the passed value.


        procedure Fatal_Exception( const S : string ) ;

        Generates a fatal error.  In Delphi, it raises an exception.  In Borland
        Pascal, it writes to the console and halts.


        function Get_Heap : PSHeap ;

        Returns the global heap instance.


        procedure Set_Heap( Value : PSHeap ) ;

        Sets the global heap object to the passed value.


        function Get_Name : string ; virtual ;

        Returns the application name.


        procedure Set_Name( const Value : string ) ;

        Sets the application name.


        function Get_Version : string ; virtual ;

        Returns the full application version string including "V".


        procedure Set_Version( const Value : string ) ;

        Sets the full application version string.


Properties: The following properties are provided for convienence in Delphi
programs.

Property        Read                Write
--------        ----                -----
Debug_Manager   Get_Debug_Manager   Set_Debug_Manager
Event_Logger    Get_Event_Logger    Set_Event_Logger
Halting         Get_Halting         Set_Halting
Heap            Get_Heap            Set_Heap
In_Shut_Down    Get_In_Shut_Down    Set_In_Shut_Down
Name            Get_Name            Set_Name
Version         Get_Version         Set_Version
~~~


Stores, Managed Stores, and Heaps

A "store" is anything that stores data for later retrieval.  Unlike streams,
they are random-access.  A "managed store" is a store which manages the free
space within the heap.  This is also known as a "heap".  In this case, you must
first request an allocation of the store of the size required.  To releasse
allocated data, a deallocation is required.  THeap, TSHeap, and TCOM_Heap are
specific types of managed stores that wrap the Delphi/Pascal heaps.  All forms
of stores descend from the abstract base classes TSStore, TSStore64, TStore,
TStore64, TCOM_Store, and TCOM_Store64.
~~~


Operating System Interface

To provide an abstract interface to the operating system that the program runs
on, an Operating System Interface object is provided which wraps the Operating
System API and provides a consistent interface to different Operating Systems.
The global Operating System Interface instance can be requested from the OS
function in the O_S unit.  This returns a PSOperating_System which is of the
appropriate type.
~~~


File Interface
~~~


Appendix - Hierarchy

The following indicates the hierarchy of the Subroutine Library's contents.  The
lowest-level units are shown first, with higher-level units shown later.

Layer 0 : Object Model
======================
_Common  COMInter    _Types    _GenVal

_Propert  _ObjectF  _DebugIn    _Streams

Common    Typedefs


Layer 1 : Application Model
===========================
DebugInt

_AEL    _DebugMa    _ObjectM    _UEHDefs    ASCIIDef    OSWinDeb    CommonUt    CVT    Num1s    Collect    Compatib    _Cache    _FacMan    _APM

OS_DOS    OS_Windows    Cache    Collect    VCL_Std   AEL    _Stores    APM

Stores

MStores

Heaps    _App

O_S    App

Files


Layer 2 : Utilities
===================
ExtStore

