%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % The TYPINFO unit %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{The TYPINFO unit} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Constants, Types and variables \section{Constants, Types and variables} \subsection{Constants} The following constants are used in the implementation section of the unit. \begin{verbatim} BooleanIdents: array[Boolean] of String = ('False', 'True'); DotSep: String = '.'; \end{verbatim} The following constants determine the access method for the \var{Stored} identifier of a property as used in the \var{PropProcs} field of the \var{TPropInfo} record: \begin{verbatim} ptField = 0; ptStatic = 1; ptVirtual = 2; ptConst = 3; \end{verbatim} The following typed constants are used for easy selection of property types. \begin{verbatim} tkAny = [Low(TTypeKind)..High(TTypeKind)]; tkMethods = [tkMethod]; tkProperties = tkAny-tkMethods-[tkUnknown]; \end{verbatim} \subsection{types} The following pointer types are defined: \begin{verbatim} PShortString =^ShortString; PByte =^Byte; PWord =^Word; PLongint =^Longint; PBoolean =^Boolean; PSingle =^Single; PDouble =^Double; PExtended =^Extended; PComp =^Comp; PFixed16 =^Fixed16; Variant = Pointer; \end{verbatim} The \var{TTypeKind} determines the type of a property: \begin{verbatim} TTypeKind = (tkUnknown,tkInteger,tkChar,tkEnumeration, tkFloat,tkSet,tkMethod,tkSString,tkLString,tkAString, tkWString,tkVariant,tkArray,tkRecord,tkInterface, tkClass,tkObject,tkWChar,tkBool,tkInt64,tkQWord, tkDynArray,tkInterfaceRaw); tkString = tkSString; \end{verbatim} \var{tkString} is an alias that is introduced for Delphi compatibility. If the property is and ordinal type, then \var{TTOrdType} determines the size and sign of the ordinal type: \begin{verbatim} TTOrdType = (otSByte,otUByte,otSWord,otUWord,otSLong,otULong); \end{verbatim} The size of a float type is determined by \var{TFloatType}: \begin{verbatim} TFloatType = (ftSingle,ftDouble,ftExtended,ftComp,ftCurr, ftFixed16,ftFixed32); \end{verbatim} A method property (e.g. an event) can have one of several types: \begin{verbatim} TMethodKind = (mkProcedure,mkFunction,mkConstructor,mkDestructor, mkClassProcedure, mkClassFunction); \end{verbatim} The kind of parameter to a method is determined by \var{TParamFlags}: \begin{verbatim} TParamFlags = set of (pfVar,pfConst,pfArray,pfAddress,pfReference,pfOut); \end{verbatim} Interfaces are described further with \var{TntfFlags}: \begin{verbatim} TIntfFlags = set of (ifHasGuid,ifDispInterface,ifDispatch); \end{verbatim} The following defines a set of \var{TTypeKind}: \begin{verbatim} TTypeKinds = set of TTypeKind; \end{verbatim} The \var{TypeInfo} function returns a pointer to a \var{TTypeInfo} record: \begin{verbatim} TTypeInfo = record Kind : TTypeKind; Name : ShortString; end; PTypeInfo = ^TTypeInfo; PPTypeInfo = ^PTypeInfo; \end{verbatim} Note that the Name is stored with as much bytes as needed to store the name, it is not padded to 255 characters. The type data immediatly follows the \var{TTypeInfo} record as a \var{TTypeData} record: \begin{verbatim} PTypeData = ^TTypeData; TTypeData = packed record case TTypeKind of tkUnKnown,tkLString,tkWString,tkAString,tkVariant: (); tkInteger,tkChar,tkEnumeration,tkWChar: (OrdType : TTOrdType; case TTypeKind of tkInteger,tkChar,tkEnumeration,tkBool,tkWChar : ( MinValue,MaxValue : Longint; case TTypeKind of tkEnumeration: ( BaseType : PTypeInfo; NameList : ShortString ) ); tkSet: ( CompType : PTypeInfo ) ); tkFloat: ( FloatType : TFloatType ); tkSString: (MaxLength : Byte); tkClass: (ClassType : TClass; ParentInfo : PTypeInfo; PropCount : SmallInt; UnitName : ShortString ); tkMethod: (MethodKind : TMethodKind; ParamCount : Byte; ParamList : array[0..1023] of Char {in reality ParamList is a array[1..ParamCount] of: record Flags : TParamFlags; ParamName : ShortString; TypeName : ShortString; end; followed by ResultType : ShortString} ); tkInt64: (MinInt64Value, MaxInt64Value: Int64); tkQWord: (MinQWordValue, MaxQWordValue: QWord); tkInterface: (); end; \end{verbatim} If the typeinfo kind is \var{tkClass}, then the property information follows the \var{UnitName} string, as an array of \var{TPropInfo} records. The \var{TPropData} record is not used, but is provided for completeness. \begin{verbatim} TPropData = packed record PropCount : Word; PropList : record end; end; \end{verbatim} The \var{TPropInfo} record describes one published property of a class: \begin{verbatim} PPropInfo = ^TPropInfo; TPropInfo = packed record PropType : PTypeInfo; GetProc : Pointer; SetProc : Pointer; StoredProc : Pointer; Index : Integer; Default : Longint; NameIndex : SmallInt; PropProcs : Byte; Name : ShortString; end; \end{verbatim} The \var{Name} field is stored not with 255 characters, but with just as many characters as required to store the name. \begin{verbatim} TProcInfoProc = procedure(PropInfo : PPropInfo) of object; \end{verbatim} The following pointer and array types are used for typecasts: \begin{verbatim} PPropList = ^TPropList; TPropList = array[0..65535] of PPropInfo; \end{verbatim} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Functions and procedures \section{Functions and Procedures} \begin{function}{GetTypeData} \Declaration Function GetTypeData(TypeInfo : PTypeInfo) : PTypeData; \Description \var{GetTypeData} returns a pointer to the \var{TTypeData} record that follows after the \var{TTypeInfo} record pointed to by \var{TypeInfo}. It essentially skips the \var{Kind} and \var{Name} fields in the \var{TTypeInfo} record. \Errors None. \SeeAlso \end{function} \begin{function}{GetPropInfo} \Declaration function GetPropInfo(TypeInfo: PTypeInfo; const PropName: string) : PPropInfo; \Description \var{GetPropInfo} returns a pointer to the \var{TPropInfo} record for a the \var{PropName} property of a class that has \var{TypeInfo} as class info. \Errors If the property \var{PropName} does not exist, \var{Nil} is returned. \SeeAlso \seep{GetPropInfos},\seef{GetPropList} \end{function} \begin{procedure}{GetPropInfos} \Declaration Procedure GetPropInfos(TypeInfo: PTypeInfo;PropList: PPropList); \Description \var{GetPropInfos} stores pointers to the property information of all published properties of a class with class info \var{TypeInfo} in the list pointed to by \var{Proplist}. The \var{PropList} pointer must point to a memory location that contains enough space to hold all properties of the class and its parent classes. \Errors No checks are done to see whether \var{PropList} points to a memory area that is big enough to hold all pointers. \SeeAlso \seef{GetPropInfo},\seef{GetPropList} \end{procedure} \begin{function}{GetPropList} \Declaration Function GetPropList(TypeInfo : PTypeInfo; TypeKinds : TTypeKinds; PropList : PPropList) : Integer; \Description \var{GetPropList} stores pointers to property information of the class with class info \var{TypeInfo} for properties of kind \var{TypeKinds} in the list pointed to by \var{Proplist}. \var{PropList} must contain enough space to hold all properties. The function returns the number of pointers that matched the criteria and were stored in \var{PropList}. \Errors No checks are done to see whether \var{PropList} points to a memory area that is big enough to hold all pointers. \SeeAlso \seep{GetPropInfos}, \seef{GetPropInfo} \end{function} \begin{function}{IsStoredProp} \Declaration Function IsStoredProp(Instance : TObject;PropInfo : PPropInfo) : Boolean; \Description \var{IsStoredProp} returns \var{True} if the \var{Stored} modifier evaluates to \var{True} for the property described by \var{PropInfo} for object \var{Instance}. It returns \var{False} otherwise. If the function returns \var{True}, this indicates that the property should be written when streaming the object \var{Instance}. If there was no \var{stored} modifier in the declaration of the property, \var{True} will be returned. \Errors No checking is done whether \var{Instance} is non-nil, or whether \var{PropInfo} describes a valid property of \var{Instance}. \SeeAlso \end{function} \begin{function}{GetOrdProp} \Declaration Function GetOrdProp(Instance : TObject;PropInfo : PPropInfo) : Longint; \Description \var{GetOrdProp} returns the value of the ordinal property described by \var{PropInfo} for the object \var{Instance}. The value is returned as a longint, which should be typecasted to the needed type. Ordinal properties that can be retrieved include: \begin{description} \item[Integers and subranges of integers] The value of the integer will be returned. \item[Enumerated types and subranges of enumerated types] The ordinal value of the enumerated type will be returned. \item[Sets] If the base type of the set has less than 31 possible values. If a bit is set in the return value, then the corresponding element of the base ordinal class of the set type must be included in the set. \end{description} \Errors No checking is done whether \var{Instance} is non-nil, or whether \var{PropInfo} describes a valid ordinal property of \var{Instance} \SeeAlso \seep{SetOrdProp}, \seef{GetStrProp}, \seef{GetFloatProp}, \seef{GetInt64Prop},\seef{GetMethodProp} \end{function} \begin{procedure}{SetOrdProp} \Declaration Procedure SetOrdProp(Instance : TObject;PropInfo : PPropInfo; Value : Longint); \Description \var{SetOrdProp} assigns \var{Value} to the the ordinal property described by \var{PropInfo} for the object \var{Instance}. Ordinal properties that can be set include: \begin{description} \item[Integers and subranges of integers] The actual value of the integer must be passed. \item[Enumerated types and subranges of enumerated types] The ordinal value of the enumerated type must be passed. \item[Subrange types] of integers or enumerated types. Here the ordinal value must be passed. \item[Sets] If the base type of the set has less than 31 possible values. For each possible value; the corresponding bit of \var{Value} must be set. \end{description} \Errors No checking is done whether \var{Instance} is non-nil, or whether \var{PropInfo} describes a valid ordinal property of \var{Instance}. No range checking is performed. \SeeAlso \seef{GetOrdProp}, \seep{SetStrProp}, \seep{SetFloatProp}, \seep{SetInt64Prop},\seep{SetMethodProp} \end{procedure} \begin{function}{GetStrProp} \Declaration Function GetStrProp(Instance : TObject;PropInfo : PPropInfo) : Ansistring; \Description \var{GetStrProp} returns the value of the string property described by \var{PropInfo} for object \var{Instance}. \Errors No checking is done whether \var{Instance} is non-nil, or whether \var{PropInfo} describes a valid string property of \var{Instance}. \SeeAlso \seep{SetStrProp}, \seef{GetOrdProp}, \seef{GetFloatProp}, \seef{GetInt64Prop},\seef{GetMethodProp} \end{function} \begin{procedure}{SetStrProp} \Declaration procedure SetStrProp(Instance : TObject;PropInfo : PPropInfo; const Value : Ansistring); \Description \var{GetStrProp} assigns \var{Value} to the string property described by \var{PropInfo} for object \var{Instance}. \Errors No checking is done whether \var{Instance} is non-nil, or whether \var{PropInfo} describes a valid string property of \var{Instance}. \SeeAlso \seef{GetStrProp}, \seep{SetOrdProp}, \seep{SetFloatProp}, \seep{SetInt64Prop},\seep{SetMethodProp} \end{procedure} \begin{function}{GetFloatProp} \Declaration Function GetFloatProp(Instance : TObject;PropInfo : PPropInfo) : Extended; \Description \var{GetFloatProp} returns the value of the float property described by \var{PropInfo} for the object \var{Instance}. All float types are converted to extended. \Errors No checking is done whether \var{Instance} is non-nil, or whether \var{PropInfo} describes a valid float property of \var{Instance}. \SeeAlso \seep{SetFloatProp}, \seef{GetOrdProp}, \seef{GetStrProp}, \seef{GetInt64Prop},\seef{GetMethodProp} \end{function} \begin{procedure}{SetFloatProp} \Declaration Procedure SetFloatProp(Instance : TObject; PropInfo : PPropInfo; Value : Extended); \Description \var{SetFloatProp} assigns \var{Value} to the property described by \var{PropInfo} for the object \var{Instance}. \Errors No checking is done whether \var{Instance} is non-nil, or whether \var{PropInfo} describes a valid float property of \var{Instance}. \SeeAlso \seef{GetFloatProp}, \seep{SetOrdProp}, \seep{SetStrProp}, \seep{SetInt64Prop},\seep{SetMethodProp} \end{procedure} \begin{function}{GetVariantProp} \Declaration Function GetVariantProp(Instance : TObject;PropInfo : PPropInfo): Variant; \Description Not yet implemented. Provided for Delphi compatibility only. \Errors \SeeAlso \end{function} \begin{procedure}{SetVariantProp} \Declaration Procedure SetVariantProp(Instance : TObject; PropInfo : PPropInfo; Const Value: Variant); \Description Not yet implemented. Provided for Delphi compatibility only. \Errors \SeeAlso \end{procedure} \begin{function}{GetMethodProp} \Declaration Function GetMethodProp(Instance : TObject;PropInfo : PPropInfo) : TMethod; \Description \var{GetMethodProp} returns the method the property described by \var{PropInfo} for object \var{Instance}. The return type \var{TMethod} is defined in the \file{SysUtils} unit as: \begin{verbatim} TMethod = packed record Code, Data: Pointer; end; \end{verbatim} \var{Data} points to the instance of the class with the method \var{Code}. \Errors No checking is done whether \var{Instance} is non-nil, or whether \var{PropInfo} describes a valid method property of \var{Instance}. \SeeAlso \seep{SetMethodProp}, \seef{GetOrdProp}, \seef{GetStrProp}, \seef{GetFloatProp}, \seef{GetInt64Prop} \end{function} \begin{procedure}{SetMethodProp} \Declaration Procedure SetMethodProp(Instance : TObject;PropInfo : PPropInfo; const Value : TMethod); \Description \var{SetMethodProp} assigns \var{Value} to the method the property described by \var{PropInfo} for object \var{Instance}. The type \var{TMethod} of the \var{Value} parameter is defined in the \file{SysUtils} unit as: \begin{verbatim} TMethod = packed record Code, Data: Pointer; end; \end{verbatim} \var{Data} should point to the instance of the class with the method \var{Code}. \Errors No checking is done whether \var{Instance} is non-nil, or whether \var{PropInfo} describes a valid method property of \var{Instance}. \SeeAlso \seef{GetMethodProp}, \seep{SetOrdProp}, \seep{SetStrProp}, \seep{SetFloatProp}, \seep{SetInt64Prop} \end{procedure} \begin{function}{GetInt64Prop} \Declaration Function GetInt64Prop(Instance: TObject; PropInfo: PPropInfo): Int64; \Description \var{GetInt64Prop} returns the value of the property of type \var{Int64} that is described by \var{PropInfo} for the object \var{Instance}. \Errors No checking is done whether \var{Instance} is non-nil, or whether \var{PropInfo} describes a valid \var{Int64} property of \var{Instance}. \SeeAlso \seep{SetInt64Prop}, \seef{GetOrdProp}, \seef{GetStrProp}, \seef{GetFloatProp}, \seef{GetMethodProp} \end{function} \begin{procedure}{SetInt64Prop} \Declaration Procedure SetInt64Prop(Instance: TObject; PropInfo: PPropInfo; const Value: Int64); \Description \var{SetInt64Prop} assigns \var{Value} to the property of type \var{Int64} that is described by \var{PropInfo} for the object \var{Instance}. \Errors No checking is done whether \var{Instance} is non-nil, or whether \var{PropInfo} describes a valid \var{Int64} property of \var{Instance}. \SeeAlso \seef{GetInt64Prop}, \seef{GetMethodProp}, \seep{SetOrdProp}, \seep{SetStrProp}, \seep{SetFloatProp} \end{procedure} \begin{function}{GetEnumName} \Declaration Function GetEnumName(TypeInfo : PTypeInfo;Value : Integer) : string; \Description \var{GetEnumName} scans the type information for the enumeration type desribed by \var{TypeInfo} and returns the name of the enumeration constant for the element with ordinal value equal to \var{Value}. If \var{Value} is out of range, the first element of the enumeration type is returned. The result is lowercased, but this may change in the future. This can be used in combination with \var{GetOrdProp} to stream a property of an enumerated type. \Errors No check is done whether \var{TypeInfo} points to the type information for an enumerated type. \SeeAlso \seef{GetOrdProp}, \seef{GetEnumValue} \end{function} \begin{function}{GetEnumValue} \Declaration Function GetEnumValue(TypeInfo : PTypeInfo;const Name : string) : Integer; \Description \var{GetEnumValue} scans the type information for the enumeration type described by \var{TypeInfor} and returns the ordinal value for the element in the enumerated type that has identifier \var{Name}. The identifier is searched in a case-insensitive manner. This can be used to set the value of enumerated properties from a stream. \Errors If \var{Name} is not found in the list of enumerated values, then -1 is returned. No check is done whether \var{TypeInfo} points to the type information for an enumerated type. \SeeAlso \seef{GetEnumName}, \seep{SetOrdProp} \end{function}