
Purpose: Framework Core Low-Level Cross-Compiler RTTI Definitions
- this unit is a part of the Open Source Synopse mORMot framework 2, licensed under a MPL/GPL/LGPL three license - see LICENSE.md
| Unit Name | Description | |
|---|---|---|
| mormot.core.base | Framework Core Shared Types and RTL-like Functions | |
| mormot.core.os | Framework Core Low-Level Wrappers to the Operating-System API | |
| mormot.core.text | Framework Core Low-Level Text Processing | |
| mormot.core.unicode | Framework Core Low-Level Unicode UTF-8 UTF-16 Ansi Conversion |
| Objects | Description | |
|---|---|---|
| ERttiException | The kind of Exception raised by this unit | |
| PropWrap | Used to map a TPropInfo.GetProc/SetProc and retrieve its kind | |
| TArrayInfo | RkArray RTTI not defined in Delphi 7/2007 TTypeData | |
| TObjectWithCustomCreate | Abstract parent class with published properties and a virtual constructor | |
| TObjectWithID | Root class of an object with a 64-bit ID primary key | |
| TPropData | PPropData not defined in Delphi 7/2007 TypInfo | |
| TPublishedMethodInfo | Information about one method, as returned by GetPublishedMethods | |
| TRecordInfo | RkRecord RTTI is not defined in Delphi 7/2007 TTypeData | |
| TRttiCache | Convenient wrapper about PRttiInfo content and its more precise information | |
| TRttiClass | A wrapper to class type information, as defined by the compiler RTTI | |
| TRttiCustom | Allow to customize the process of a given TypeInfo/PRttiInfo | |
| TRttiCustomList | Maintain a thread-safe list of PRttiInfo/TRttiCustom/TRttiJson registration | |
| TRttiCustomListPairs | Efficient PRttiInfo/TRttiCustom pairs for TRttiCustomList hash table | |
| TRttiCustomProp | Store information about one property/field of a given TypeInfo/PRttIinfo | |
| TRttiCustomProps | Store information about all properties/fields of a given TypeInfo/PRttIinfo | |
| TRttiEnumType | A wrapper to enumeration type information, as defined by the compiler RTTI and returned by PRttiInfo.EnumBaseType/SetEnumType | |
| TRttiInfo | Main entry-point wrapper to access RTTI for a given pascal type | |
| TRttiInterface | Store IInvokable methods information | |
| TRttiInterfaceTypeData | A wrapper to interface type information, as defined by the the compiler RTTI | |
| TRttiMap | Customizable field mapping between classes and records | |
| TRttiMethod | Store IInvokable method information | |
| TRttiProp | A wrapper containing a RTTI class property definition | |
| TRttiProps | A wrapper to published properties of a class, as defined by compiler RTTI | |
| TRttiRecordAllField | Enhanced RTTI of a record/object type definition | |
| TRttiRecordField | RTTI of a record/object type definition (managed) field | |
| TRttiRecordManagedFields | Record RTTI as returned by TRttiInfo.RecordManagedFields | |
| TRttiVarData | Variant-like value as returned by TRttiCustomProp.GetRttiVarData |
ERttiException = class(ESynException)
The kind of Exception raised by this unit
TRttiProps = object(TObject)
A wrapper to published properties of a class, as defined by compiler RTTI
- access properties for only a given class level, not inherited properties
- start enumeration by getting a PRttiProps with PRttiInfo.RttiProps(), then use P := PropList to get the first PRttiProp, and iterate with P^.Next
- this enumeration is very fast and doesn't require any temporary memory, as in the TypInfo.GetPropInfos() PPropList usage
- for TOrm, you should better use the Properties.Fields[] array, which is faster and contains the properties published in parent classes
function FieldProp(const PropName: ShortString): PRttiProp;
Retrieve a Field property RTTI information from a Property Name
function PropCount: integer;
Number of published properties in this object
function PropList: PRttiProp;
Point to a TPropInfo packed array
- layout is as such, with variable TPropInfo storage size:
PropList: array[1..PropCount] of TPropInfo
- use TPropInfo.Next to get the next one:
P := PropList; for i := 1 to PropCount do begin // ... do something with P P := P^.Next; end;
TRttiClass = object(TObject)
A wrapper to class type information, as defined by the compiler RTTI
- get a PRttiClass with PRttiInfo.RttiClass() or GetRttiClass()
function InheritsFrom(AClass: TClass): boolean;
Fast and easy find if this class inherits from a specific class type
- you should rather consider using TRttiInfo.InheritsFrom directly
function ParentInfo: PRttiInfo;
The parent class type information
function PropCount: integer;
The number of published properties of this class and all parents
- use RttiProps if you want to properties only published in this class
function RttiClass: TClass;
The class type
function RttiProps: PRttiProps;
Get the information about the published properties of this class
- stored after UnitName memory
function UnitName: PShortString;
The name (without .pas extension) of the unit were the class was defined
- then the PRttiProps information follows: use the method RttiProps to retrieve its address
TRttiEnumType = object(TObject)
A wrapper to enumeration type information, as defined by the compiler RTTI and returned by PRttiInfo.EnumBaseType/SetEnumType
- we use this to store the enumeration values as integer, but easily provide a text equivalent, translated if necessary, from the enumeration type definition itself
function GetCaption(const Value): string;
Get the caption text corresponding to a enumeration name
- return the first one if Value is invalid (>MaxValue)
- Value will be converted to the matching ordinal value (byte or word)
function GetCaptionStrings(UsedValuesBits: pointer = nil): string;
Get all caption names, ready to be display, as lines separated by #13#10
- return "string" type, i.e. UnicodeString for Delphi 2009+
- if UsedValuesBits is not nil, only the corresponding bits set are added
function GetEnumName(const Value): PShortString;
Get the corresponding enumeration name
- return the first one if Value is invalid (>MaxValue)
- Value will be converted to the matching ordinal value (byte or word)
function GetEnumNameAllAsJsonArray(TrimLeftLowerCase: boolean; UnCamelCased: boolean = false): RawUtf8;
Get all enumeration names as a JSON array of strings
function GetEnumNameOrd(Value: cardinal): PShortString;
Get the corresponding enumeration name
- return a void '' ShortString if Value is invalid (>MaxValue)
function GetEnumNameTrimed(const Value): RawUtf8;
Get the corresponding enumeration name, without the first lowercase chars (otDone -> 'Done')
- Value will be converted to the matching ordinal value (byte or word)
function GetEnumNameTrimedValue(Value: PUtf8Char; ValueLen: integer = 0): integer; overload;
Get the corresponding enumeration ordinal value, from its name without its first lowercase chars ('Done' will find otDone e.g.)
- return -1 if not found, or if RTTI's MinValue is not 0
function GetEnumNameTrimedValue(const EnumName: ShortString): integer; overload;
Get the corresponding enumeration ordinal value, from its name without its first lowercase chars ('Done' will find otDone e.g.)
- return -1 if not found, or if RTTI's MinValue is not 0
function GetEnumNameValue(const EnumName: ShortString): integer; overload;
Get the corresponding enumeration ordinal value, from its name
- if EnumName does start with lowercases 'a'..'z', they will be searched: e.g. GetEnumNameValue('sllWarning') will find sllWarning item
- if Value does not start with lowercases 'a'..'z', they will be ignored: e.g. GetEnumNameValue('Warning') will find sllWarning item
- return -1 if not found (don't use directly this value to avoid any GPF)
function GetEnumNameValue(Value: PUtf8Char): integer; overload;
Get the corresponding enumeration ordinal value, from its name
- if Value does start with lowercases 'a'..'z', they will be searched: e.g. GetEnumNameValue('sllWarning') will find sllWarning item
- if Value does not start with lowercases 'a'..'z', they will be ignored: e.g. GetEnumNameValue('Warning') will find sllWarning item
- return -1 if not found (don't use directly this value to avoid any GPF)
function GetEnumNameValue(Value: PUtf8Char; ValueLen: integer; AlsoTrimLowerCase: boolean = true): integer; overload;
Get the corresponding enumeration ordinal value, from its name
- if Value does start with lowercases 'a'..'z', they will be searched: e.g. GetEnumNameValue('sllWarning') will find sllWarning item
- if AlsoTrimLowerCase is TRUE, and EnumName does not start with lowercases 'a'..'z', they will be ignored: e.g. GetEnumNameValue('Warning') will find sllWarning item
- return -1 if not found, or if RTTI's MinValue is not 0
function GetEnumNameValueTrimmed(Value: PUtf8Char; ValueLen: integer; CaseSensitive: boolean): integer;
Get the corresponding enumeration ordinal value, from its trimmed name
function GetSetName(const value; trimmed: boolean = false; const sep: RawUtf8 = ','): RawUtf8;
Get the enumeration names corresponding to a set value as CSV
function GetSetNameJsonArray(Value: cardinal; SepChar: AnsiChar = ','; FullSetsAsStar: boolean = false): RawUtf8; overload;
Get the enumeration names corresponding to a set value as JSON array
function MaxValue: PtrInt;
Same as ord(high(type)): not the enumeration count, but the highest index
function MinValue: PtrInt;
First value of enumeration type, typicaly 0
- may be < 0 e.g. for boolean
function NameList: PShortString;
A concatenation of shortstrings, containing the enumeration names
- those shortstrings are not aligned whatsoever (even if FPC_REQUIRES_PROPER_ALIGNMENT is set)
function RttiOrd: TRttiOrd;
Specify ordinal storage size and sign
- is prefered to MaxValue to identify the number of stored bytes
function SizeInStorageAsEnum: integer;
Compute how many bytes this type will use to be stored as a enumerate
function SizeInStorageAsSet: integer;
Compute how many bytes (1, 2, 4) this type will use to be stored as a set
- consider using TRttiInfo.SetEnumSize if ISFPC32 conditional is defined
procedure AddCaptionStrings(Strings: TStrings; UsedValuesBits: pointer = nil);
Add caption names, ready to be display, to a TStrings class
- add pointer(ord(element)) as Objects[] value
- if UsedValuesBits is not nil, only the corresponding bits set are added
- can be used e.g. to populate a combo box as such:
PTypeInfo(TypeInfo(TMyEnum))^.EnumBaseType^.AddCaptionStrings(ComboBox.Items);
procedure GetEnumNameAll(out result: RawUtf8; const Prefix: RawUtf8 = ''; quotedValues: boolean = false; const Suffix: RawUtf8 = ''; trimedValues: boolean = false; unCamelCased: boolean = false); overload;
Retrieve all element names as CSV, with optional quotes
procedure GetEnumNameAll(var result: TRawUtf8DynArray; TrimLeftLowerCase: boolean); overload;
Retrieve all element names as a dynamic array of RawUtf8
- names could be optionally trimmed left from their initial lower chars
procedure GetEnumNameTrimedAll(var result: RawUtf8; const Prefix: RawUtf8 = ''; quotedValues: boolean = false; const Suffix: RawUtf8 = '');
Retrieve all trimed element names as CSV
procedure GetSetNameJsonArray(W: TTextWriter; Value: cardinal; SepChar: AnsiChar = ','; QuoteChar: AnsiChar = #0; FullSetsAsStar: boolean = false; ForceTrim: boolean = false); overload;
Write the enumeration names corresponding to a set value as a JSON array
procedure SetEnumFromOrdinal(out Value; Ordinal: PtrUInt);
Store an enumeration value from its ordinal representation
TRttiRecordField = record
RTTI of a record/object type definition (managed) field
- defined here since this structure is not available in oldest Delphi's TypInfo.pas
- maps TRecordElement in FPC rtti.inc or TManagedField in TypInfo
Offset: PtrUInt;
Where this managed field starts in the record memory layout
TypeInfoRef: PPRttiInfo;
The RTTI of this managed field
TRttiInterfaceTypeData = object(TObject)
A wrapper to interface type information, as defined by the the compiler RTTI
function IntfFlags: TRttiIntfFlags;
Interface abilities - not inlined to avoid random trouble on FPC trunk
function IntfGuid: PGuid;
Interface 128-bit Guid
function IntfParent: PRttiInfo;
Ancestor interface type
function IntfUnit: PShortString;
Where the interface has been defined
TRttiRecordManagedFields = record
Record RTTI as returned by TRttiInfo.RecordManagedFields
Count: PtrInt;
How many managed Fields[] are defined in this record
Fields: PRttiRecordField;
Points to the first field RTTI
- use inc(Fields) to go to the next one
Size: PtrInt;
The record size in bytes
TRttiRecordAllField = record
Enhanced RTTI of a record/object type definition
- as returned by TRttiInfo.RecordAllFields on Delphi 2010+
Name: PShortString;
The field property name
Offset: PtrUInt;
The field offset in the record
TypeInfo: PRttiInfo;
The field RTTI definition
TRttiCache = record
Convenient wrapper about PRttiInfo content and its more precise information
- is cached within TRttiCustom instances for more efficient process
BinarySize: byte;
If > 0, this type should be serialized as hexadecimal string
CodePage: cardinal;
From TypeInfo() on older Delphi with no CP RTTI
Engine: TSynAnsiConvert
RawBlob=CP_RAWBYTESTRING not CP_RAWBLOB
Flags: TRttiCacheFlags;
Quick identification of specific types, e.g. rkOrdinalTypes
Info: PRttiInfo;
The associated RTTI TypeInfo()
InterfaceGuid: PGuid;
= TRttiCustom of the rkInterface
ItemInfoRaw: PRttiInfo;
= nil for unmanaged types
ItemSize: integer;
From RTTI, likely <> nil for unmanaged types
Kind: TRttiKind;
RttiFloat: TRttiFloat;
Type-specific information
RttiOrd: TRttiOrd;
For rkHasRttiOrdTypes/rcfHasRttiOrd, equals Info^.RttiOrd
RttiVarDataVType: word;
Pre-computed TRttiVarData.VType for TRttiCustomProp.GetRttiVarData
- rkEnumeration,rkSet,rkDynArray,rkClass,rkInterface,rkRecord,rkArray are identified as varAny with TVarData.VAny pointing to the actual value, and will be handled as expected by TJsonWriter.AddRttiVarData
SerializableInterface: pointer;
RkArray only
SerializableInterfaceEntryOffset: integer;
Size: integer;
The size in bytes of a value of this type - equals Info^.RttiSize
VarDataVType: word;
Corresponding TVarData.VType
- in respect to RttiVarDataVType, rkEnumeration and rkSet are varInt64 since we don't need the RTTI information as for TRttiVarData
TRttiInfo = object(TObject)
Main entry-point wrapper to access RTTI for a given pascal type
- as returned by the TypeInfo() low-level compiler function
- other RTTI objects can be computed from a pointer to this structure
- user types defined as an alias don't have this type information:
type TNewType = TOldType;
here TypeInfo(TNewType) = TypeInfo(TOldType)
- user types defined as new types have this type information:
type TNewType = type TOldType;
here TypeInfo(TNewType) <> TypeInfo(TOldType)
Kind: TRttiKind;
The value type family
- not defined as an inlined function, since first field is always aligned
RawName: ShortString;
The declared name of the type ('String','Word','RawUnicode'...)
- won't adjust internal/cardinal names on FPC as with Name method
function AnsiStringCodePage: integer;
Recognize most used string types, returning their code page
- will return the exact code page on FPC and since Delphi 2009, from RTTI
- for non Unicode versions of Delphi, will recognize WinAnsiString as CP_WINANSI, RawUnicode as CP_UTF16, RawByteString/RawBlob as CP_RAWBYTESTRING, AnsiString as CP_ACP=0, and any other type as RawUtf8
- it will also recognize RawBlob as the fake CP_RAWBLOB codepage
function ArrayItemType(out aDataCount, aDataSize: PtrInt): PRttiInfo;
For rkArray: get the static array type information of the stored item
- same as ArrayItemTypeExtended() but, always returns nil if the array type is unmanaged (i.e. like old Delphi)
- used e.g. for static array binary-level process in mormot.core.data
function ArrayItemTypeExtended(out aDataCount, aDataSize: PtrInt): PRttiInfo;
For rkArray: get the static array type information of the stored item
- may returns nil if the array type is unmanaged on old Delphi revisions
- aDataSize is the size in bytes of all aDataCount static items (not the size of each item)
- caller should ensure the type is indeed a static array
function ArraySize: PtrInt;
For rkArray: get the size in bytes of all the static array items
- caller should ensure the type is indeed a static array
function ClassFieldCount(onlyWithoutGetter: boolean): integer;
For rkClass: return the number of published properties in this class
- you can count the plain fields without any getter function, if you do need only the published properties corresponding to some value actually stored, and ignore e.g. any textual conversion
function DynArrayItemSize: PtrInt;
For rkDynArray: get the dynamic array size (in bytes) of the stored item
function DynArrayItemType(out aDataSize: PtrInt): PRttiInfo; overload;
For rkDynArray: get the dynamic array type information of the stored item
- returns nil if the item has no managed field
- this overloaded method will also return the item size in bytes
- caller should ensure the type is indeed a dynamic array
function DynArrayItemType: PRttiInfo; overload;
For rkDynArray: get the dynamic array standard RTTI of the stored item
- returns nil if the item has no managed field
- caller should ensure the type is indeed a dynamic array
function DynArrayItemTypeExtended: PRttiInfo;
For rkDynArray: get the dynamic array deep RTTI of the stored item
- works for both managed and unmanaged types, on FPC and Delphi 2010+
- caller should ensure the type is indeed a dynamic array
function EnumBaseType: PRttiEnumType; overload;
For rkEnumeration: get the enumeration type information
function EnumBaseType(out NameList: PShortString; out Min, Max: integer): PRttiEnumType; overload;
For rkEnumeration: get the enumeration values information
function InheritsFrom(AClass: TClass): boolean;
For rkClass: fast and easy check if a class inherits from this RTTI
function InterfaceAncestor: PRttiInfo;
For rkInterface: get the ancestor/parent of a given interface type information
- returns nil if this type has no parent
function InterfaceGuid: PGuid;
For rkInterface: get the TGuid of a given interface type information
- returns nil if this type is not an interface
function InterfaceImplements(const AGuid: TGuid): boolean;
For rkInterface: check if this type (or ancestor) implements a TGuid
function InterfaceType: PRttiInterfaceTypeData;
For rkInterface: get the interface type information
function InterfaceUnitName: PShortString;
For rkInterface: get the unit name of a given interface type information
- returns '' if this type is not an interface
function IsBoolean: boolean;
Return TRUE if the property is a boolean field
function IsCurrency: boolean;
Return TRUE if the property is a currency field
function IsDate: boolean;
Return TRUE if the property is a TDateTime/TDateTimeMS/TDate
function IsManaged: boolean;
Check if this type is a managed type, or has any managed field
- will also check for the nested fields e.g. for rkRecordTypes
function IsQWord: boolean;
Return TRUE if the property is an unsigned 64-bit field (QWord/UInt64)
function IsRawBlob: boolean;
Return true if this property is a BLOB (RawBlob)
function Name: PShortString;
The declared name of the type ('String','Word','RawUnicode'...)
- will return '' if @self is nil
- on FPC, will adjust 'integer'/'cardinal' from 'longint'/'longword' RTTI
- on Delphi and FPC, will adjust weak RawUtf8 = UTF8String as 'RawUtf8'
function RecordAllFields(out RecSize: PtrInt): TRttiRecordAllFields;
For rkRecordTypes: retrieve enhanced RTTI information about all fields of this record, for JSON serialization without text definition
- this information is currently only available since Delphi 2010
- if any field has no RTTI (e.g. a static array of unmanaged type), then it will ignore this uncomplete, therefore non-useful RTTI
- in practice, it may be a good habit to always define the records used within the SOA (e.g. as DTOs) calling RegisterFromText, and don't rely on this RTTI, since it will be more cross-platform, and more customizable
function RecordManagedFieldsCount: integer;
For rkRecordTypes: check if this record as any managed fields
function RecordSize: PtrInt;
For rkRecordTypes: get the record size
- returns 0 if the type is not a record/object
function RttiClass: PRttiClass;
For rkClass: get the class type information
function RttiFloat: TRttiFloat;
For rkFloat: get the storage size and precision
- will also properly detect our currency internal type as rfCurr
function RttiNonVoidClass: PRttiClass;
For rkClass: get the class type information
function RttiOrd: TRttiOrd;
For ordinal types, get the storage size and sign
function RttiSize: PtrInt;
Compute in how many bytes this type is stored
- will use Kind (and RttiOrd/RttiFloat) to return the exact value
function SetEnumSize: PtrInt;
For rkSet: in how many bytes this type is stored
- is very efficient on latest FPC only - i.e. ifdef ISFPC32
function SetEnumType: PRttiEnumType; overload;
For rkSet: get the type information of its associated enumeration
function SetEnumType(out NameList: PShortString; out Min, Max: integer): PRttiEnumType; overload;
For rkSet: get the associated enumeration values information
procedure Clear(Data: pointer);
Efficiently finalize any (managed) type value
- do nothing for unmanaged types (e.g. integer)
- if you are sure that your type is managed, you may call directly
RTTI_FINALIZE[Info^.Kind](Data, Info);
procedure ComputeCache(var Cache: TRttiCache);
Compute extended information about this RTTI type
procedure Copy(Dest, Source: pointer);
Efficiently copy any (managed) type value
- do nothing for unmanaged types (e.g. integer)
- if you are sure that your type is managed, you may call directly
RTTI_MANAGEDCOPY[Info^.Kind](Dest, Source, Info);
procedure InterfaceAncestors(out Ancestors: PRttiInfoDynArray; OnlyImplementedBy: TInterfacedObjectClass; out AncestorsImplementedEntry: TPointerDynArray);
For rkInterface: get all ancestors/parents of a given interface type information
- only ancestors with an associated TGuid will be added
- if OnlyImplementedBy is not nil, only the interface explicitly implemented by this class will be added, and AncestorsImplementedEntry[] will contain the corresponding PInterfaceEntry values
procedure RecordManagedFields(out Fields: TRttiRecordManagedFields);
For rkRecordTypes: retrieve RTTI information about all managed fields of this record
- non managed fields (e.g. integers, double...) are not listed here
- also includes the total record size in bytes
- caller should ensure the type is indeed a record/object
- note: if FPC_OLDRTTI is defined, unmanaged fields are included
procedure StringToUtf8(Data: pointer; var Value: RawUtf8);
Retrieve rkLString, rkSString, rkUString, rkWString, rkChar, rkWChar values as RawUtf8, from a pointer to its memory storage
- makes heap allocations and encoding conversion, so may be slow
TRttiProp = object(TObject)
A wrapper containing a RTTI class property definition
- used for direct Delphi / UTF-8 SQL type mapping/conversion
- doesn't depend on RTL's TypInfo unit, to enhance cross-compiler support
function Default: integer;
Contains the default value for an ordinal or set property
- NO_DEFAULT=$80000000 indicates none was defined in source code
- see also TPropInfo.DefaultOr0
function DefaultOr0: integer;
Return the Default RTTI value defined for this property, or 0 if not set
function FieldSize: PtrInt;
Compute in how many bytes this property is stored
function GetAsString(Instance: TObject): RawUtf8; overload;
Retrieve rkLString, rkSString, rkUString, rkWString, rkChar, rkWChar as RawUtf8
- just a wrapper around the overloaded GetAsString() function
function GetAsString(Instance: TObject; var Value: RawUtf8): boolean; overload;
Retrieve rkLString, rkSString, rkUString, rkWString, rkChar, rkWChar as RawUtf8
- this would make heap allocations and encoding conversion, so may be slow
function GetDoubleProp(Instance: TObject): double;
Raw retrieval of rkFloat/double
function GetDoubleValue(Instance: TObject): double;
Low-level getter of the floating-point property value of a given instance
- this method will check if the corresponding property is floating-point
- return 0 on any error
function GetDynArrayPropGetter(Instance: TObject): pointer;
Raw retrieval of rkDynArray getter as a pointer
- caller should then release the instance using e.g. FastDynArrayClear()
- do nothing if the property is a field with no getter
function GetFieldAddr(Instance: TObject): pointer;
Low-level getter of the field value memory pointer
- return NIL if both getter and setter are methods
function GetFloatProp(Instance: TObject): double;
Raw retrieval of rkFloat - with conversion to 64-bit double
- use instead GetDoubleProp if you know the property is a rkFloat/double
function GetInt64Prop(Instance: TObject): Int64;
Raw retrieval of rkInt64, rkQWord
- rather call GetInt64Value
function GetInt64Value(Instance: TObject): Int64;
Low-level getter of the ordinal property value of a given instance
- this method will check if the corresponding property is ordinal
- ordinal properties smaller than rkInt64 will return an Int64-converted value (e.g. rkInteger)
- return 0 on any error
function GetObjProp(Instance: TObject): TObject;
Raw retrieval of rkClass
function GetOrdProp(Instance: TObject): Int64;
Raw retrieval of rkInteger,rkEnumeration,rkSet,rkChar,rkWChar,rkBool
- rather call GetOrdValue/GetInt64Value
- returns an Int64 to properly support cardinal values
function GetOrdValue(Instance: TObject): Int64;
Low-level getter of the ordinal property value of a given instance
- this method will check if the corresponding property is ordinal
- returns an Int64 to properly support cardinal values
- return -1 on any error
function Getter(Instance: TObject; Call: PMethod): TRttiPropCall;
Raw retrieval of the property read access definition
- note: 'var Call' generated incorrect code on Delphi XE4 -> use PMethod
function GetterAddr(Instance: pointer): pointer;
Returns the low-level field read address, if GetterIsField is TRUE
function GetterCall: TRttiPropCall;
Returns how a property should be retrieved
- no "read" attribute specified will return rpcField if "write" is a direct field access - just like any Get*() method would do
function GetterIsField: boolean;
Return TRUE if the property has no getter but direct field read
- returns FALSE if no "read" attribute was specified: use GetterCall if you want to mimic how Get*() methods could use the "write" field
function GetValueText(Instance: TObject): RawUtf8;
Get a property value into text
- handle all kind of fields, e.g. converting ordinal or floats into text
function Index: integer;
Contains the index value of an indexed class data property
- outside SQLite3, this can be used to define a VARCHAR() length value for the textual field definition (sftUtf8Text/sftAnsiText); e.g. the following will create a NAME VARCHAR(40) field:
Name: RawUtf8 index 40 read fName write fName;
- is used by a dynamic array property for fast usage of the TOrm.DynArray(DynArrayFieldIndex) method
function IsRawBlob: boolean;
Return true if this property is a BLOB (RawBlob)
function IsStored(Instance: TObject): boolean;
Return the "stored true/false/method/field" value for a class property
- not used internally: for backward compatibility only
function IsStoredGetter(Instance: TObject): boolean;
Raw retrieval of the 'stored' flag using getter
- called by IsStored or for TRttiPropStored = rpsGetter
function IsStoredKind: TRttiPropStored;
Returns rpsTrue/rpsFalse if was marked as "stored true/false" or rpsGetter if IsStoredGetter(Instance) is to be called at runtime
function Name: PShortString;
The property Name, directly returned from RTTI
function NameIndex: integer;
Index of the property in the current inherited class definition
- first name index at a given class level is 0
- index is reset to 0 at every inherited class level
function NameUtf8: RawUtf8;
The property Name, converted as a RawUtf8
function Next: PRttiProp;
Get the next property information
- no range check: use RttiProps()^.PropCount to determine the properties count
- get the first PRttiProp with RttiProps()^.PropList
function SetAsString(Instance: TObject; const Value: RawUtf8): boolean;
Set rkLString, rkSString, rkUString, rkWString, rkChar, rkWChar from a RawUtf8 value
- this would make heap allocations and encoding conversion, so may be slow
function Setter(Instance: TObject; Call: PMethod): TRttiPropCall;
Raw retrieval of the property access definition
function SetterAddr(Instance: pointer): pointer;
Returns the low-level field write address, if SetterIsField is TRUE
function SetterCall: TRttiPropCall;
Returns how a property should be set
- no "write" attribute specified will return rpcField if "read" is a direct field access - just like any Set*() method would do
function SetterIsField: boolean;
Return TRUE if the property has no setter but direct field write
- returns FALSE if no "write" attribute is specified: use SetterCall if you want to mimic how Set*() methods could use the "read" field
function SetValue(Instance: TObject; const Value: variant): boolean;
Set a property value from a variant value
- to be called when a setter is involved - not very fast, but safe
function SetValueText(Instance: TObject; const Value: RawUtf8): boolean;
Set a property value from a text value
- handle simple kind of fields, e.g. converting from text into ordinals or floats, and also enumerates or sets; but won't support complex types like class instances, dynamic arrays or variants
function TypeInfo: PRttiInfo;
The type information of this property
- will de-reference the PropType pointer on Delphi and newer FPC compilers
function WriteIsDefined: boolean;
Return TRUE if the property has a write setter or direct field
procedure CopyLongStrProp(Source, Dest: TObject);
Raw copy of rkLString
procedure GetCurrencyProp(Instance: TObject; var Value: currency);
Raw retrieval of rkFloat/currency
- use instead GetCurrencyValue
procedure GetCurrencyValue(Instance: TObject; var Value: currency);
Low-level getter of the currency property value of a given instance
- this method will check if the corresponding property is exactly currency
- return 0 on any error
procedure GetLongStrProp(Instance: TObject; var Value: RawByteString);
Raw retrieval of rkLString
procedure GetRawByteStringValue(Instance: TObject; var Value: RawByteString);
Low-level getter of the long string property content of a given instance
- just a wrapper around low-level GetLongStrProp() function
- call GetLongStrValue() method if you want a conversion into RawUtf8
- will work only for Kind=rkLString
procedure GetShortStrProp(Instance: TObject; var Value: RawUtf8);
Raw retrieval of rkString into an Ansi7String
procedure GetVariantProp(Instance: TObject; var Result: Variant; SetByRef: boolean);
Raw retrieval of rkVariant
- will use varByRef from the field address if SetByRef is true
procedure GetWideStrProp(Instance: TObject; var Value: WideString);
Raw retrieval of rkWString
procedure SetCurrencyProp(Instance: TObject; const Value: currency);
Raw assignment of rkFloat/currency
procedure SetDoubleProp(Instance: TObject; Value: Double);
Raw assignment of rkFloat/double
procedure SetDoubleValue(Instance: TObject; const Value: double);
Low-level setter of the floating-point property value of a given instance
- this method will check if the corresponding property is floating-point
procedure SetFloatProp(Instance: TObject; Value: TSynExtended);
Raw assignment of rkFloat
- use instead SetDoubleProp if you know the property is a rkFloat/double
procedure SetInt64Prop(Instance: TObject; const Value: Int64);
Raw assignment of rkInt64, rkQWord
- rather call SetInt64Value
procedure SetInt64Value(Instance: TObject; Value: Int64);
Low-level setter of the ordinal property value of a given instance
- this method will check if the corresponding property is ordinal
procedure SetLongStrProp(Instance: TObject; const Value: RawByteString);
Raw assignment of rkLString
procedure SetOrdProp(Instance: TObject; Value: PtrInt);
Raw assignment of rkInteger,rkEnumeration,rkSet,rkChar,rkWChar,rkBool
- rather call SetOrdValue/SetInt64Value
procedure SetOrdValue(Instance: TObject; Value: PtrInt);
Low-level setter of the ordinal property value of a given instance
- this method will check if the corresponding property is ordinal
procedure SetVariantProp(Instance: TObject; const Value: Variant);
Raw assignment of rkVariant
procedure SetWideStrProp(Instance: TObject; const Value: WideString);
Raw assignment of rkWString
PropWrap = packed record
Used to map a TPropInfo.GetProc/SetProc and retrieve its kind
- defined here for proper Delphi inlining
Kind: byte;
=$ff for a ptField address, or =$fe for a ptVirtual method
TPropData = packed record
PPropData not defined in Delphi 7/2007 TypInfo
- defined here for proper Delphi inlining
TRecordInfo = packed record
RkRecord RTTI is not defined in Delphi 7/2007 TTypeData
- defined here for proper Delphi inlining
TArrayInfo = packed record
RkArray RTTI not defined in Delphi 7/2007 TTypeData
- defined here for proper Delphi inlining
TPublishedMethodInfo = record
Information about one method, as returned by GetPublishedMethods
Method: TMethod;
A callback to the method, for the given class instance
Name: RawUtf8;
The method name
TRttiMethod = record
Store IInvokable method information
Args: array of TRttiMethodArg;
The method arguments
HierarchyLevel: integer;
0 for the root interface, >0 for inherited interfaces
IsFunction: boolean;
If this method is a function, i.e. expects a result
Name: RawUtf8;
The method name, e.g. 'Add' for ICalculator.Add
TRttiInterface = record
Store IInvokable methods information
Guid: TGuid;
The associated GUID of this interface
Methods: array of TRttiMethod;
The interface methods
Name: RawUtf8;
The interface name, e.g. 'ICalculator'
UnitName: RawUtf8;
The unit where the interface was defined
TRttiVarData = packed record
Variant-like value as returned by TRttiCustomProp.GetRttiVarData
- used internally by TRttiCustomProp.AddValueJson/CompareValueComplex (handled in TJsonWriter.AddVariant/AddRttiVarData methods)
- simple values (integers, floats, strings or variant) are set into Data
- rkEnumeration, rkSet, rkDynArray, rkClass, rkInterface, rkRecord and rkObject are stored as varAny/PropValue pointer to the field value (for GetRttiVarDataDirect) or Instance (for GetRttiVarDataGetter if PropValueIsInstance is true), and Prop to the corresponding property RTTI
- varAny is NON-STANDARD, so should NOT be used as a plain variant, e.g. calling Prop.SetValueVariant(RVD.Data) or transtyping variant(RVD)
- use TSynVarData if you want a TVarData exact wrapper with 32-bit VType
- for varAny, Prop contains additional RTTI and NeedsClear should be checked:
if RVD.NeedsClear then VarClearProc(RVD.Data);
Data: TVarData
Maps DataType + NeedsClear + PropValueIsInstance
NeedsClear: boolean;
Matches TVarData.VType
Prop: PRttiCustomProp;
Assert(@PropValue=@VAny) is done in initialization section below
TRttiCustomProp = object(TObject)
Store information about one property/field of a given TypeInfo/PRttIinfo
- used by both rkClass for published properties, and rkRecord/rkObject for nested fields
Name: RawUtf8;
Contains Prop^.Name or a customized field/property name
- equals '' if Props.NameChange() was set to New='', meaning this field should not be part of the serialized JSON object
OffsetGet: PtrInt;
Read field/property offset in the record/class instance memory
- equals -1 if Prop has a getter
OffsetSet: PtrInt;
Write field/property offset in the record/class instance memory
- equals -1 if Prop has a setter
OrdinalDefault: integer;
Equals NO_DEFAULT or the default integer value of this property
Prop: PRttiProp;
Store standard RTTI of this published property
- equals nil for rkRecord/rkObject nested field
Stored: TRttiPropStored;
Reflect the "stored" property attribute as defined in the source
Value: TRttiCustom;
Contains standard TypeInfo/PRttiInfo of this field/property
- for instance, Value.Size contains its memory size in bytes
function CompareValue(Data, Other: pointer; const OtherRtti: TRttiCustomProp; CaseInsensitive: boolean): integer;
Compare two properties values with proper getter method call
- is likely to call Value.ValueCompare() which requires mormot.core.json
function NameMatch(P: PUtf8Char; Len: PtrInt): boolean;
Case-insensitive compare the supplied name/len with the Name property
function SetValueText(Data: pointer; const Text: RawUtf8): boolean;
Set a field value from its UTF-8 text
- will convert the Text into proper ordinal or float if needed
- also implemented for Prop = nil (i.e. rkRecord/rkObject nested field)
- use Prop^.SetValueText() if you want to support enumerates and sets
function ValueIsDefault(Data: pointer): boolean;
Check if the Value equals the default property set in source code
- caller should have checked that PropDefault <> NO_DEFAULT
function ValueIsVoid(Data: pointer): boolean;
Check if the Value is void (0 / '' / null)
- less restrictive function than VarIsVoid() from mormot.core.variants
procedure AddValueJson(W: TTextWriter; Data: pointer; Options: TTextWriterWriteObjectOptions; K: TTextWriterKind = twNone);
Append the field value as JSON with proper getter method call
- wrap GetRttiVarData() + AddVariant() over a temp TRttiVarData
procedure ClearValue(Data: pointer; FreeAndNilNestedObjects: boolean);
Low-level initialization of one property value
procedure CopyValue(Dest, Source: PAnsiChar; DestRtti: PRttiCustomProp);
Low-level copy of two properties values
procedure GetValueJson(Data: pointer; out Result: RawUtf8);
A wrapper calling AddValueJson()
procedure GetValueVariant(Data: pointer; out Dest: TVarData; Options: pointer = nil);
Retrieve any field value as a variant instance
- will generate a stand-alone variant value, not an internal TRttiVarData
- complex values can be returned as TDocVariant after JSON conversion, using e.g. @JSON_[mFastFloat] as optional Options parameter
procedure SetValueVariant(Data: pointer; var Source: TVarData);
Set a field value to a given variant content
- use a temporary text conversion for a record field (Prop=nil)
- Source is eventually cleared via VarClearProc()
- typical usage is from GetValueVariant() output
- do not use the output of GetRttiVarData() as Source
TRttiCustomProps = object(TObject)
Store information about all properties/fields of a given TypeInfo/PRttIinfo
- includes parent properties when filled by AddFromClass(IncludeParents=true)
Count: integer;
How many properties/fields are in List[]
CountNonVoid: integer;
How many properties/fields with Name <> '' are in List[]
List: TRttiCustomPropDynArray;
One List[] item per property/field
Managed: PRttiCustomPropDynArray;
Points to List[] items which are managed
NamesAsJsonArray: RawUtf8;
Contains List[].Name as a JSON array including a trailing ,
- as used by _JS_DynArray() for efficient twoNonExpandedArrays generation
NotInheritedIndex: integer;
List[NotInheritedIndex]..List[Count-1] store the last level of properties
Size: integer;
Total size, in bytes, of all properties/fields
- equals the sum of List[].Value.Size
function AdjustAfterAdded: TRttiCustomFlags;
Called once List[] and Size have been defined
- compute the Managed[] internal list and return the matching flags
function Find(PropName: PUtf8Char; PropNameLen: PtrInt): PRttiCustomProp; overload;
Locate a property/field by name
- just redirect to FindCustomProp() low-level function
function Find(const PropName: RawUtf8): PRttiCustomProp; overload;
Locate a property/field by name
- just redirect to FindCustomProp() low-level function
function FindIndex(const PropName: RawUtf8): PtrInt; overload;
Locate a property/field index by name
function FindIndex(PropName: PUtf8Char; PropNameLen: PtrInt): PtrInt; overload;
Locate a property/field index by name
function FromTextPrepare(const PropName: RawUtf8): integer;
Prepare List[result].Name from TRttiCustom.SetPropsFromText
function NameChange(const Old, New: RawUtf8): PRttiCustomProp;
Customize a property/field name
- New is expected to be only plain pascal identifier, i.e. A-Z a-z 0-9 and _ characters, up to 63 in length
- if New equals '', this published property will be excluded from the JSON serialized object
procedure AsText(out Result: RawUtf8; IncludePropType: boolean; const Prefix, Suffix: RawUtf8);
Retrieve all List[] items as text
procedure CopyProperties(Dest, Source: PAnsiChar);
Copy the properties of a rkClass instance
- called e.g. when no RTTI is available, i.e. text serialization
- will copy all published properties one-by-one
procedure CopyRecord(Dest, Source: PAnsiChar);
Copy the fields of a rkRecordTypes instance
- called e.g. when no RTTI is available, i.e. text serialization
- will move() all bytes between managed fields
procedure FinalizeAndClearPublishedProperties(Instance: TObject);
Finalize and fill with zero all properties of this class instance
- it will individually fill the properties, not the whole memory as TRttiCustom.FinalizeAndClear would on a record
procedure FinalizeManaged(Data: PAnsiChar);
Finalize the managed properties of this instance
- called e.g. when no RTTI is available, i.e. text serialization
procedure InternalAdd(Info: PRttiInfo; Offset: PtrInt; const PropName: RawUtf8; AddFirst: boolean = false);
Manual adding of a property/field definition
- append as last field, unless AddFirst is set to true
procedure InternalAddFromClass(ClassInfo: PRttiInfo; IncludeParents: boolean);
Register the published properties of a given class
- is called recursively if IncludeParents is true
procedure InternalClear;
Reset all properties
procedure NameChanges(const Old, New: array of RawUtf8);
Customize property/field name, specified as old/new pairs
- will first restore all field names from RTTI, then each Old[] field name will be replaced by the corresponding New[] name
- so setting both Old=New=[] just set back the default names from RTTI
- New[] is expected to be only plain pascal identifier, i.e. A-Z a-z 0-9 and _ characters, up to 63 in length
- if any New[] equals '', this published property will be excluded from the JSON serialized object
- Rtti.ByClass[TMyClass].Props.NameChanges() replaces deprecated TJsonSerializer.RegisterCustomSerializerFieldNames(TMyClass, ...)
procedure SetFromRecordExtendedRtti(RecordInfo: PRttiInfo);
Register the properties specified from extended RTTI (Delphi 2010+ only)
- do nothing on FPC or Delphi 2009 and older
TRttiCustom = class(TObject)
Allow to customize the process of a given TypeInfo/PRttiInfo
- a global list of TRttiCustom instances mapping TypeInfo() is maintained in Rtti: TRttiCustomList
- never instantiate this class directly, but call RttiCustom methods
constructor CreateFromText(const RttiDefinition: RawUtf8);
Initialize abstract custom serialization for a given record
- not registered in the main TRttiCustomList: caller should free it
- in practice, is used only by test.core.data.pas regression tests
destructor Destroy; override;
Finalize this instance
function ClassNewInstance: pointer;
Create a new TObject instance of this rkClass
- not implemented here (raise an ERttiException) but in TRttiJson, so that mormot.core.rtti has no dependency to TSynPersistent and such
function ComputeFakeObjArrayRtti(aItemClass: TClass): TBytes;
Create a fake TRttiCustom clone with an overloaded ArrayRtti/ObjArrayClass
function GetPrivateSlot(aClass: TClass): pointer;
Retrieve an instance of a given class per RTTI
- previously registered by SetPrivateSlot
function HasClassNewInstance: boolean;
Check if this type has ClassNewInstance information
function PropFindByPath(var Data: pointer; FullName: PUtf8Char; PathDelim: AnsiChar = '.'): PRttiCustomProp;
Recursively search for 'one.two.three' nested properties
- returns nil if not found
- returns the property information and let Data point to its associated rkClass or rkRecord/rkObject owner
function SetPrivateSlot(aObject: TObject): pointer;
Register once an instance of a given class per RTTI
- thread-safe returns aObject, or an existing object (freeing aObject)
- just like PrivateSlot property, but for as many class as needed
function ValueByPath(var Data: pointer; Path: PUtf8Char; var Temp: TVarData; PathDelim: AnsiChar = '.'): TRttiCustom; virtual;
Lookup a value by a path name e.g. 'one.two.three' nested values
- for a record/class, will search for a property name
- for a TDocVariant/TBsonVariant, calls TSynInvokeableVariantType.IntGet
- for an enumeration or set, will return true/false about the enum name
- for a string, Data^ will be compared to the name
- implemented in TRttiJson for proper knowledge of our variants
function ValueCompare(Data, Other: pointer; CaseInsensitive: boolean): integer; virtual;
{$ifdef HASINLINE}inline;{$endif} compare two stored values of this type
- not implemented in this class (raise an ERttiException) but in TRttiJson, so that it will use mormot.core.data comparison
function ValueIsVoid(Data: PAnsiChar): boolean;
Return TRUE if the Value is 0 / nil / '' / null
- less restrictive function than VarIsVoid() from mormot.core.variants
function ValueIterate(Data: pointer; Index: PtrUInt; out ResultRtti: TRttiCustom): pointer; virtual;
Iterate over one sub-item of a given value
- returns nil if the value is not iterable or Index is out of range
- returns a pointer to the value, rkClass/rkLString kinds being already resolved (as the TList/TSynList/TRawUtf8List items are returned), so you can directly trans-type the result to TObject() or RawUtf8()
- ResultRtti holds the type of the resolved result pointer
- note that TStrings values are not supported, because they require a temporary string variable for their getter method
- implemented in TRttiJson for proper knowledge of TSynList/TRawUtf8List
function ValueIterateCount(Data: pointer): integer; virtual;
How many iterations could be done one a given value
- returns -1 if the value is not iterable, or length(DynArray) or TRawUtf8List.Count or TList.Count or TSynList.Count
- implemented in TRttiJson for proper knowledge of TSynList/TRawUtf8List
function ValueSetText(Data: pointer; const Text: RawUtf8): boolean;
Set a property value from a text value
- handle most kind of fields, e.g. converting from text into ordinal or floats
function ValueToVariant(Data: pointer; out Dest: TVarData; Options: pointer = nil): PtrInt; virtual;
Fill a variant with a stored value of this type
- not implemented in this class (raise an ERttiException) but in TRttiJson, so that it will use mormot.core.variants process
- complex values can be returned as TDocVariant after JSON conversion, using e.g. @JSON_[mFast] as optional Options parameter
- returns the size of the Data in bytes, i.e. Cache.ItemSize
procedure FromRtti(aInfo: PRttiInfo); virtual;
Initialize the customizer class from known RTTI
- is called just after Create
procedure PropsClear;
Reset all stored Props[] and associated flags
procedure SetClassNewInstance(FactoryMethod: TRttiCustomNewInstance);
Allow low-level customization of the fNewInstance pointer
procedure ValueCopy(Dest, Source: pointer);
Efficiently copy of a stored value of this type
- same behavior as Dest := Source for all types
procedure ValueFinalize(Data: pointer);
Efficiently finalize a stored value of this type
- if rcfObjArray is defined in Flags, will release all nested TObject
procedure ValueFinalizeAndClear(Data: pointer);
Efficiently finalize a stored value of this type, and fill it with zeros
- if rcfObjArray is defined in Flags, will release all nested TObject
procedure ValueRandom(Data: pointer);
Fill a value from random - including strings and nested types
procedure ValueWriteText(Data: pointer; W: TTextWriter; HtmlEscape: boolean); virtual;
Serialize a value into (HTML) text
- implemented in TRttiJson for proper knowledge of complex types
- warning: supplied W instance should be a TJsonWriter
property ArrayFirstField: TRttiParserType read fArrayFirstField;
Best guess of first field type for a rkDynArray
- equals ArrayRtti.Parser if ArrayRtti.Kind is not rkRecordTypes
property ArrayFirstFieldSort: TRttiParserType read fArrayFirstFieldSort;
Best guess of first field type for a rkDynArray
- equals ArrayFirstField or an ordinal type matching the enum/set type
property ArrayRtti: TRttiCustom read fArrayRtti;
Shortcut to the TRttiCustom of the item of a (dynamic) array
- only set for rkArray and rkDynArray
- may be set also for unmanaged types - use Cache.ItemInfo if you want the raw PRttiInfo TypeInfo() pointer for rkManagedTypes only
property BinarySize: byte read fCache.BinarySize;
Store the number of bytes for hexadecimal serialization for rcfBinary
- used when rcfBinary is defined in Flags; equals 0 if disabled (default)
property Cache: TRttiCache read fCache;
Direct access to the ready-to-use RTTI
property CollectionItem: TCollectionItemClass read fCollectionItem;
Store the Item class for a given TCollection
- as previously registered by Rtti.RegisterCollection()
property Copy: TRttiCopier read fCopy;
Redirect to the low-level value copy - use rather ValueCopy()
property CopyObject: TRttiClassCopier read fCopyObject write fCopyObject;
Redirect to the low-level class instance copy
- nil by default, to use Props.CopyProperties()
- is overwritten e.g. by TOrm.RttiCustomSetParser
property Flags: TRttiCustomFlags read fFlags write fFlags;
Define specific behavior for this type
property Info: PRttiInfo read fCache.Info;
Direct access to the low-level RTTI TypeInfo() pointer, from Rtti property
property JsonLoad: pointer read fJsonLoad write fJsonLoad;
Opaque TRttiJsonLoad callback used by mormot.core.json.pas
property JsonReader: TMethod read fJsonReader write fJsonReader;
Opaque TOnRttiJsonRead callback used by mormot.core.json.pas
property JsonSave: pointer read fJsonSave write fJsonSave;
Opaque TRttiJsonSave callback used by mormot.core.json.pas
property JsonWriter: TMethod read fJsonWriter write fJsonWriter;
Opaque TOnRttiJsonWrite callback used by mormot.core.json.pas
property Kind: TRttiKind read fCache.Kind;
Low-level RTTI kind, taken from Rtti property
property Name: RawUtf8 read fName;
The known type name
- may be an hexadecimal value of self, if rcfWithoutRtti is in Flags
property ObjArrayClass: TClass read fObjArrayClass;
Store the class of a T*ObjArray dynamic array
- shortcut to ArrayRtti.Info.RttiClass.RttiClass
- used when rcfObjArray is defined in Flags
property Parser: TRttiParserType read fParser;
property ParserComplex: TRttiParserComplexType read fParserComplex;
High-level Parser Complex kind
property PrivateSlot: pointer read fPrivateSlot write fPrivateSlot;
Opaque private instance used by mormot.orm.base.pas or mormot.core.log.pas
- stores e.g. the TOrmProperties ORM information of a TOrm, or the TSynLogFamily of a TSynLog instance
- is owned, as TObject, by this TRttiCustom
- assignment is usually protected by the Rtti.RegisterSafe
property Props: TRttiCustomProps read fProps;
Store information about the properties/fields of this type
- only set for rkClass and rkRecord/rkObject
property Size: integer read fCache.Size;
Direct access to the low-level size in bytes used to store a value of this type, as taken from Rtti property
- warning: for rkArray/rkDynArray, equals SizeOf(pointer), not the item size, which is hold in Cache.ItemSize
property ValueClass: TClass read fValueClass;
Store the class of this type, i.e. contains Cache.Info.RttiClass.RttiClass
property ValueRtlClass: TRttiValueClass read fValueRtlClass;
Identify most common RTL inherited classes for special handling
- recognize TCollection TStrings TObjectList TList parents
- TRttiValueClass enumerate is faster than InheritsFrom() call
TRttiCustomListPairs = record
Efficient PRttiInfo/TRttiCustom pairs for TRttiCustomList hash table
- as stored in TRttiCustomList.fHashTable[RK_TOSLOT[TRttiKind]]
- contains hash tables by TypeInfo() and by case-insensitive name
HashInfo: array[0..RTTIHASH_MAX] of TPointerDynArray;
CPU L1 cache efficient PRttiInfo/TRttiCustom pairs hashed by PRttiInfo
HashName: array[0..RTTIHASH_MAX] of TPointerDynArray;
CPU L1 cache efficient PRttiInfo/TRttiCustom pairs hashed by Name
LastHash: array[0..RTTIHASH_MAX] of TRttiCustom;
Thread-safe speedup search by PRttiInfo e.g. from a loop
LastInfo: TRttiCustom;
Thread-safe speedup search by PRttiInfo e.g. from a loop
LastName: TRttiCustom;
Speedup search by name e.g. from a loop
Safe: TRWLightLock;
Efficient HashInfo/HashName[] pairs thread-safety during Find/AddToPairs
TRttiCustomList = class(TObject)
Maintain a thread-safe list of PRttiInfo/TRttiCustom/TRttiJson registration
Count: integer;
Ensure Count=0 how many TRttiCustom instances have been registered
Counts: array[TRttiKind] of integer;
How many TRttiCustom instances have been registered for a given type
- we include rkUnknown for safety
RegisterSafe: TOSLock;
A global lock shared for high-level RTTI registration process
- is used e.g. to protect DoRegister() or TRttiCustom.PrivateSlot
- should be a reentrant lock, even if seldom called
constructor Create;
Initialize the RTTI list
destructor Destroy; override;
Finalize the RTTI list
function DoRegister(ObjectClass: TClass): TRttiCustom; overload;
Low-level registration function called from RegisterClass()
- is sometimes called after manual vmtAutoTable slot lookup
function FindByArrayRtti(ElemInfo: PRttiInfo): TRttiCustom;
Manual search of any matching TRttiCustom.ArrayRtti type
- currently not called: IList<T> and IKeyValue<T> just use TypeInfo(T)
class function FindClass(ObjectClass: TClass): TRttiCustom;
Efficient search of TRttiCustom from a given TObject class
- returns nil if Info is not known
- will use the ObjectClass vmtAutoTable slot for very fast O(1) lookup, or use our "hash table of the poor" (tm) if NOPATCHVMT conditional is set
function FindName(const Name: ShortString; Kinds: TRttiKinds = []): TRttiCustom; overload;
Efficient search of TRttiCustom from a given type name
function FindName(Name: PUtf8Char; NameLen: PtrInt; Kind: TRttiKind): TRttiCustom; overload;
Efficient search of TRttiCustom from a given type name
function FindName(Name: PUtf8Char; NameLen: PtrInt; Kinds: TRttiKinds = []): TRttiCustom; overload;
Efficient search of TRttiCustom from a given type name
function FindType(Info: PRttiInfo): TRttiCustom;
Efficient search of TRttiCustom from a given RTTI TypeInfo()
- returns nil if Info is not known
- call RegisterType() if you want to initialize the type via its RTTI
- not inlined since less efficient code is generated
function RegisterAutoCreateFieldsClass(ObjectClass: TClass): TRttiCustom;
Register a given class type, using its RTTI, to auto-create/free its class and dynamic array published fields
function RegisterBinaryType(Info: PRttiInfo; BinarySize: integer = 0): TRttiCustom;
Register one RTTI TypeInfo() to be serialized as hexadecimal
- data will be serialized as BinToHexDisplayLower() JSON hexadecimal string, using BinarySize bytes of the value, i.e. BinarySize*2 hexa chars
- you can truncate the original data size (e.g. if all bits of an integer are not used) by specifying the aFieldSize optional parameter
- will also ensure that those types will be recognized by text definition
- leave BinarySize=0 to write all bytes as hexadecimal
- set BinarySize=-1 to unregister the binary serialization for the type
- not thread-safe: should be called once from the main thread, at startup, e.g. in the initialization section of your types definition unit
- match mORMot 1.18 TTextWriter.RegisterCustomJSONSerializerFromTextBinaryType
function RegisterClass(aObject: TObject): TRttiCustom; overload;
Register a given class type, using its RTTI
- returns existing or new TRttiCustom
- please call RegisterCollection for TCollection
function RegisterClass(ObjectClass: TClass): TRttiCustom; overload;
Register a given class type, using its RTTI
- returns existing or new TRttiCustom
- please call RegisterCollection for TCollection
function RegisterCollection(Collection: TCollectionClass; CollectionItem: TCollectionItemClass): TRttiCustom;
Define how a given TCollectionClass should instantiate its items
- we need to know the CollectionItem to propertly initialize a TCollection
- not thread-safe: should be called once from the main thread, at startup, e.g. in the initialization section of your collection definition unit
function RegisterFromText(DynArrayOrRecord: PRttiInfo; const RttiDefinition: RawUtf8): TRttiCustom; overload;
Register TypeInfo() custom serialization for a given dynamic array or record
- DynArrayOrRecord should be valid TypeInfo() - use overloaded RegisterFromText(TypeName) if the record has no TypeInfo()
- the RTTI information will here be defined as plain text
- since Delphi 2010, you can call directly RegisterType()
- the record where the data will be stored should be defined as PACKED:
type TMyRecord = packed record A,B,C: integer; D: RawUtf8; E: record; // or array of record/integer/string/... E1,E2: double; end; end;
- call this method with RttiDefinition='' to return back to the default serialization, i.e. binary + Base64 or Delphi 2010+ extended RTTI
- RTTI textual information shall be supplied as text, with the same format as any pascal record:
'A,B,C: integer; D: RawUtf8; E: record E1,E2: double;' 'A,B,C: integer; D: RawUtf8; E: array of record E1,E2: double;' 'A,B,C: integer; D: RawUtf8; E: array of SynUnicode; F: array of TGuid'
or a shorter alternative syntax for records and arrays:
'A,B,C: integer; D: RawUtf8; E: {E1,E2: double}'
'A,B,C: integer; D: RawUtf8; E: [E1,E2: double]'in fact ; could be ignored:
'A,B,C:integer D:RawUtf8 E:{E1,E2:double}'
'A,B,C:integer D:RawUtf8 E:[E1,E2:double]'or even : could be ignored:
'A,B,C integer D RawUtf8 E{E1,E2 double}'
'A,B,C integer D RawUtf8 E[E1,E2 double]'- it will return the cached TRttiCustom instance corresponding to the supplied RTTI text definition - i.e. the rkRecord if TypeInfo(SomeArray)
- match mORMot 1.18 TTextWriter.RegisterCustomJSONSerializerFromText()
function RegisterFromText(const TypeName: RawUtf8; const RttiDefinition: RawUtf8): TRttiCustom; overload;
Register by name a custom serialization for a given dynamic array or record
- use overloaded RegisterFromText(TypeName) if the record has TypeInfo()
- the RTTI information will here be defined as plain text
function RegisterObjArray(DynArray: PRttiInfo; Item: TClass): TRttiCustom;
Register one dynamic array RTTI TypeInfo() to be serialized as T*ObjArray
- not needed on FPC and Delphi 2010+ since "array of TSomeClass" will be recognized directly - see HASDYNARRAYTYPE conditional
- allow JSON serialization and unserialization of the registered dynamic array property defined in any TPersistent or TOrm for oldest Delphi
- could be used as such (note the T*ObjArray type naming convention):
TUserObjArray = array of TUser; ... Rtti.RegisterObjArray(TypeInfo(TUserObjArray), TUser);
- then you can use ObjArrayAdd/ObjArrayFind/ObjArrayDelete to manage the stored items, and never forget to call ObjArrayClear to release the memory
- set Item=nil to unregister the type as a T*ObjArray - may be needed to bypass the FPC and Delphi 2010+ automatic recognition
- may return nil if DynArray is not a rkDynArray
- replace deprecated TJsonSerializer.RegisterObjArrayForJson() method
- not thread-safe: should be called once from the main thread, at startup, e.g. in the initialization section of your T*ObjArray definition unit
function RegisterType(Info: PRttiInfo): TRttiCustom;
Register a given RTTI TypeInfo()
- returns a new (or existing if it was already registered) TRttiCustom
- if Info.Kind is rkDynArray, it will also register the nested rkRecord
- match mORMot 1.18 TTextWriter.RegisterCustomJSONSerializerFromTextSimpleType
function RegisterTypeFromName(Name: PUtf8Char; NameLen: PtrInt; ParserType: PRttiParserType = nil): TRttiCustom; overload;
Recognize (and register if needed) a standard simple type
- calls Find() to return already registered TRttiCustom instance, and also recognize "array" or "record" keywords as expected by our parser
- returns nil if nothing was found
- will truncate any 'unitname.typename' into plain 'typename' before Find()
function RegisterTypeFromName(const Name: RawUtf8; ParserType: PRttiParserType = nil): TRttiCustom; overload;
Recognize (and register if needed) a standard simple type
- calls Find() to return already registered TRttiCustom instance, and also recognize "array" or "record" keywords as expected by our parser
- returns nil if nothing was found
- will truncate any 'unitname.typename' into plain 'typename' before Find()
procedure RegisterBinaryTypes(const InfoBinarySize: array of const);
Register one or several RTTI TypeInfo() to be serialized as hexadecimal
- TypeInfo() and associated size information will here be defined by pairs: ([TypeInfo(TType1),TYPE1_BYTES,TypeInfo(TType2),TYPE2_BYTES])
- a wrapper around the RegisterBinaryType() method
- not thread-safe: should be called once from the main thread, at startup, e.g. in the initialization section of your types definition unit
- match mORMot 1.18 TTextWriter.RegisterCustomJSONSerializerFromTextBinaryType
procedure RegisterClasses(const ObjectClass: array of TClass);
Register one or several RTTI TypeInfo()
- to ensure that those classes will be recognized by text definition
- will just call RegisterClass() for each ObjectClass[]
procedure RegisterFromText( const TypeInfoTextDefinitionPairs: array of const); overload;
Define a custom serialization for several dynamic arrays or records
- the TypeInfo() and textual RTTI information will here be defined as ([TypeInfo(TType1),_TType1, TypeInfo(TType2),_TType2]) pairs
- a wrapper around the overloaded RegisterFromText() method
- match mORMot 1.18 TTextWriter.RegisterCustomJSONSerializerFromText()
procedure RegisterObjArrays(const DynArrayItem: array of const);
Register one or several dynamic array RTTI TypeInfo() to be serialized as T*ObjArray
- not needed on FPC and Delphi 2010+ since "array of TSomeClass" will be recognized directly - see HASDYNARRAYTYPE conditional
- will call the RegisterObjArray() class method by pair:
Rtti.RegisterObjArrays([ TypeInfo(TAddressObjArray), TAddress, TypeInfo(TUserObjArray), TUser]);
- not thread-safe: should be called once from the main thread, at startup, e.g. in the initialization section of your T*ObjArray definition unit
procedure RegisterTypes(const Info: array of PRttiInfo);
Register one or several RTTI TypeInfo()
- to ensure that those types will be recognized by text definition
- will just call RegisterType() for each Info[]
- match mORMot 1.18 TTextWriter.RegisterCustomJSONSerializerFromTextSimpleType
procedure RegisterUnsafeSpiType(const Types: array of PRttiInfo);
Register some TypeInfo() containing unsafe parameter values
- i.e. any RTTI type containing Sensitive Personal Information, e.g. a bank card number or a plain password
- such values will force associated values to be ignored during loging, as a more tuned alternative to optNoLogInput or optNoLogOutput
- not thread-safe: should be called once from the main thread, at startup, e.g. in the initialization section of your types definition unit
property ByClass[C: TClass]: TRttiCustom read GetByClass;
Default property to access a given RTTI customization of a class
- you can access or register one type by using this default property:
Rtti.ByClass[TMyClass].Props.NameChanges(['old', 'new'])
property ByTypeInfo[P: PRttiInfo]: TRttiCustom read RegisterType;
Default property to access a given RTTI TypeInfo() customization
- you can access or register one type by using this default property:
Rtti[TypeInfo(TMyClass)].Props.NameChange('old', 'new')
property GlobalClass: TRttiCustomClass read fGlobalClass write SetGlobalClass;
Which kind of TRttiCustom class is to be used for registration
- properly set e.g. by mormot.core.json.pas to TRttiJson for JSON support
TRttiMap = object(TObject)
Customizable field mapping between classes and records
- Init/Map overloaded methods return self to allow proper fluid-calling
- records should have field-level extended RTTI (since Delphi 2010), or have been properly defined with Rtti.RegisterFromText() on FPC or oldest Delphi
- allow RTTI or custom mapping, e.g. with Data Transfer Objects (DTO)
function AutoMap: PRttiMap;
Use RTTI field names to map the content
function Init(A, B: PRttiInfo): PRttiMap; overload;
Initialize fields mapping between two record instances
function Init(A, B: TClass): PRttiMap; overload;
Initialize fields mapping between two class instances
function Init(A: TClass; B: PRttiInfo): PRttiMap; overload;
Initialize fields mapping between a class instance and a record
function Map(const ABPairs: array of RawUtf8): PRttiMap; overload;
Map fields by A,B pairs of names
function Map(const A, B: RawUtf8): PRttiMap; overload;
Map two fields by name
- if any field A or B name is '', this field will be ignored
function ToA(B: pointer): pointer; overload;
Create a new A class instance, copying field values from B
- returned A is a newly allocated instance of the TClass specified to Init()
- B is either a TObject instance or a @record pointer, depending on Init()
function ToB(A: pointer): pointer; overload;
Create a new B class instance, copying field values from A
- A is either a TObject instance or a @record pointer, depending on Init()
- returned B is a newly allocated instance of the TClass specified to Init()
procedure ToA(A, B: pointer); overload;
Copy B fields values into A
- A and B are either a TObject instance or a @record pointer, depending on Init()
procedure ToB(A, B: pointer); overload;
Copy A fields values into B
- A and B are either a TObject instance or a @record pointer, depending on Init()
TObjectWithCustomCreate = class(TObject)
Abstract parent class with published properties and a virtual constructor
- is the parent of both TSynPersistent and TOrm classes
- will ensure the class type is registered to the Rtti global list
- also features some protected virtual methods for custom RTTI/JSON process
constructor Create; virtual;
Virtual constructor called at instance creation
- is declared as virtual so that inherited classes may have a root constructor to override
- is recognized by our RTTI serialization/initialization process
class function NewInstance: TObject; override;
Optimized initialization code
- will also register the class type to the Rtti global list
- somewhat faster than the regular RTL implementation
- warning: this optimized version won't initialize the vmtIntfTable for this class hierarchy: as a result, you would NOT be able to implement an interface with a TSynPersistent descendent (but you should not need to, but inherit from TInterfacedObject)
- warning: under FPC, it won't initialize fields management operators
class function RttiCustom: TRttiCustom;
Very efficiently retrieve the TRttiCustom associated with this class
- since Create did register it, just return the first vmtAutoTable slot
TObjectWithID = class(TObjectWithCustomCreate)
Root class of an object with a 64-bit ID primary key
- is the parent of mormot.orm.core's TOrm, but you could use it e.g. on client side to avoid a dependency to all ORM process, but still have the proper published fields and use it in SOA - with a single conditional over your class definition to inherit either from TOrm or from TObjectWithID
constructor CreateWithID(aID: TID);
This constructor initializes the instance with a given ID
property IDValue: TID read fID write fID;
This property gives direct access to the class instance ID
- not defined as "published" since RttiCustomSetParser did register it
PPRttiInfo = ^PRttiInfo;
Double-reference to RTTI type definition
- Delphi and newer FPC do store all nested TTypeInfo as pointer to pointer, to ease linking of the executable
PRttiCache = ^TRttiCache;
Resolve once map extended PRttiInfo content
PRttiClass = ^TRttiClass;
Pointer to TClassType, as returned by PRttiInfo.RttiClass()
- as returned by PRttiInfo.RttiClass() or GetRttiClass()
- equivalency to PClassData/PClassType as defined in old mORMot.pas
PRttiEnumType = ^TRttiEnumType;
Pointer to TEnumType, as returned by PRttiInfo.EnumBaseType/SetEnumType
- equivalency to PEnumType as defined in old mORMot.pas
PRttiInfo = ^TRttiInfo;
Pointer to low-level RTTI of a type definition, as returned by TypeInfo() compiler function over a type
- equivalency to PTypeInfo as defined in TypInfo RTL unit and old mORMot.pas
- this is the main entry point of all the information exposed by this unit
PRttiInfoDynArray = array of PRttiInfo;
Dynamic array of low-level RTTI type definitions
PRttiInterfaceTypeData = ^TRttiInterfaceTypeData;
Pointer to a wrapper to interface type information
PRttiKind = ^TRttiKind;
RfSingle rfDouble rfExtended rfComp rfCurr
PRttiMap = ^TRttiMap;
Pointer to a TRttiMap reference, for fluid-interface initialization
PRttiProp = ^TRttiProp;
Pointer to a RTTI class property definition as stored in PRttiProps.PropList
- equivalency to PPropInfo as defined in TypInfo RTL unit and old mORMot.pas
PRttiPropDynArray = array of PRttiProp;
Used to store a chain of properties RTTI
- could be used e.g. by TOrmPropInfo to handled flattened properties
PRttiProps = ^TRttiProps;
Pointer to all RTTI class properties definitions
- as returned by PRttiInfo.RttiProps() or GetRttiProps()
PRttiRecordField = ^TRttiRecordField;
Pointer to the RTTI of a record/object type definition (managed) field
PRttiVarData = ^TRttiVarData;
TObject if PropValueIsInstance=true, or field addr
TObjectWithCustomCreateClass = class of TObjectWithCustomCreate;
Used to determine the exact class type of a TObjectWithCustomCreate
- allow to create instances using its virtual constructor
TObjectWithIDClass = class of TObjectWithID;
Used to determine the exact class type of a TObjectWithID
TPublishedMethodInfoDynArray = array of TPublishedMethodInfo;
Information about all methods, as returned by GetPublishedMethods
TRttiCacheFlag = ( rcfQWord, rcfBoolean, rcfHasRttiOrd, rcfGetOrdProp, rcfGetInt64Prop, rcfIsRawBlob, rcfIsNumber );
Quick identification of some RTTI value types
TRttiCacheFlags = set of TRttiCacheFlag;
As used by TRttiCache.Flags
- rcfQWord/rcfBoolean map Info^.IsQWord/IsBoolean
- rcfIsRawBlob maps Info^.IsRawBlob
- rcfIsNumber is set if Info^.Kind is in rkNumberTypes
- set rcfHasRttiOrd/rcfGetOrdProp/rcfGetInt64Prop to access the value
TRttiClassCopier = procedure(Dest, Source: TObject);
Internal function handler for copying a class instance
- use TRttiCustom.Props.CopyProperties but may be overriden e.g. for TOrm
TRttiCopier = function(Dest, Source: pointer; Info: PRttiInfo): PtrInt;
Internal function handler for copying a managed type value
- i.e. the kind of functions called via RTTI_MANAGEDCOPY[] lookup table
TRttiCopiers = array[TRttiKind] of TRttiCopier;
The type of RTTI_MANAGEDCOPY[] efficient lookup table
TRttiCustomClass = class of TRttiCustom;
Meta-class of TRttiCustom
- is usually a TRttiJson class type once mormot.core.json.pas is linked
TRttiCustomFlag = ( rcfIsManaged, rcfObjArray, rcfBinary, rcfJsonString, rcfWithoutRtti, rcfSpi, rcfHookWrite, rcfHookWriteProperty, rcfHookRead, rcfHookReadProperty, rcfHasNestedProperties, rcfHasNestedManagedProperties, rcfHasOffsetSetJsonLoadProperties, rcfArrayItemManaged, rcfReadIgnoreUnknownFields, rcfAutoCreateFields, rcfDisableStored, rcfClassMayBeID );
Define specific behavior for a given TypeInfo/PRttIinfo
- rcfIsManaged is set if a value of this type expects finalization
- rcfObjArray is for T*ObjArray dynamic arrays
- rcfBinary is for hexadecimal serialization of integers
- rcfJsonString when is to be serialized as text and properly JSON-escaped (ptStringTypes or rcfBinary, but excluding ptRawJson)
- rcfWithoutRtti is set if was created purely by text, and uses fake RTTI
- rcfSpi identifies types containing Sensitive Personal Information (e.g. a bank card number or a plain password) which should be hidden
- rcfHookWrite, rcfHookWriteProperty, rcfHookRead, rcfHookReadProperty for TObjectWithCustomCreate kind of class, to customize JSON serialization calling the set of TObjectWithCustomCreate protected virtual methods - disabled by default not to slow down the serialization process
- rcfHasNestedProperties is set e.g. for rkClass or rcfWithoutRtti records, rcfHasNestedManagedProperties if any of the property/field is rcfIsManaged
- rcfHasOffsetSetJsonLoadProperties is set if all nested properties can be directly written, i.e. have OffsetSet >= 0 and Assigned(JsonLoad)
- rcfArrayItemManaged maps rcfIsManaged flag in ArrayRtti.Flags
- rcfReadIgnoreUnknownFields will let JSON unserialization ignore unknown fields for this class/record
- rcfAutoCreateFields is defined when AutoCreateFields() has been called
- rcfDisableStored is set for TOrm, where "stored AS_UNIQUE" does not mean "not stored" for serialization but "UNIQUE SQL"
- rcfClassMayBeID is set e.g. for TOrm classes, which may be storing not instances but IDs in published properties PtrInt
TRttiCustomFlags = set of TRttiCustomFlag;
Define specific behaviors for a given TypeInfo/PRttIinfo
- as stored in TRttiCustom.Flags
TRttiCustomFromTextExpectedEnd = ( eeNothing, eeSquare, eeCurly, eeEndKeyWord );
Used internally by our RTTI text definition
TRttiCustomNewInstance = function(Rtti: TRttiCustom): pointer;
Used internally for fast allocation of a rkClass/rkInterface instance
- member is properly initialized by TRttiJson from mormot.core.json.pas
TRttiCustomPropDynArray = array of TRttiCustomProp;
Store information about the properties/fields of a given TypeInfo/PRttiInfo
TRttiCustomRandom = procedure(Data: pointer; Rtti: TRttiCustom);
Internal function handler for filling a value with some randomness
TRttiFinalizer = function(Data: pointer; Info: PRttiInfo): PtrInt;
Internal function handler for finalizing a managed type value
- i.e. the kind of functions called via RTTI_FINALIZE[] lookup table
- as used by TRttiInfo.Clear() inlined method
TRttiFinalizers = array[TRttiKind] of TRttiFinalizer;
The type of RTTI_FINALIZE[] efficient lookup table
TRttiFloat = ( rfSingle, rfDouble, rfExtended, rfComp, rfCurr );
Map TFloatType, to specify floating point (ftFloat) storage size and precision
TRttiIntfFlag = ( ifHasGuid, ifDispInterface, ifDispatch );
Define the interface abilities
TRttiIntfFlags = set of TRttiIntfFlag;
Define the set of interface abilities
TRttiKind = ( rkUnknown, rkInteger, rkChar, rkEnumeration, rkFloat, rkSString, rkSet, rkClass, rkMethod, rkWChar, rkLString, rkWString, rkVariant, rkArray, rkRecord, rkInterface, rkInt64, rkDynArray );
Available type families for Delphi 6 and up, similar to typinfo.pas
- redefined here to leverage FPC and Delphi compatibility as much as possible
TRttiMethodArgDirection = ( rmdConst, rmdVar, rmdOut, rmdResult );
Handled kind of parameters direction for an interface method
- IN, IN/OUT, OUT directions can be applied to arguments, e.g. to be available through our JSON-serialized remote access: rmdVar and rmdOut kind of parameters will be returned within the "result": JSON array
- rmdResult is used for a function method, to handle the returned value
TRttiMethodArgDirections = set of TRttiMethodArgDirection;
Set of parameter directions e.g. for an interface-based service method
TRttiOrd = ( roSByte, roUByte, roSWord, roUWord, roSLong, roULong );
Map TOrdType, to specify ordinal (rkInteger and rkEnumeration) storage size and sign
- note: on FPC, Int64 is stored as its own TRttiKind, not as rkInteger
TRttiParserComplexType = ( pctNone, pctTimeLog, pctCreateTime, pctModTime, pctID, pctSpecificClassID, pctRecordReference, pctRecordReferenceToBeDeleted, pctRecordVersion );
The complex kind of variables for ptTimeLog and ptOrm TRttiParserType
TRttiParserType = ( ptNone, ptArray, ptBoolean, ptByte, ptCardinal, ptCurrency, ptDouble, ptExtended, ptInt64, ptInteger, ptQWord, ptRawByteString, ptRawJson, ptRawUtf8, ptRecord, ptSingle, ptString, ptSynUnicode, ptDateTime, ptDateTimeMS, ptGuid, ptHash128, ptHash256, ptHash512, ptOrm, ptTimeLog, ptUnicodeString, ptUnixTime, ptUnixMSTime, ptVariant, ptWideString, ptWinAnsi, ptWord, ptEnumeration, ptSet, ptClass, ptDynArray, ptInterface, ptPUtf8Char, ptCustom );
The kind of variables handled by our RTTI/JSON parser
- the last item should be ptCustom, for non simple types
- ptOrm is recognized from TID, T*ID, TRecordReference, TRecordReferenceToBeDeleted and TRecordVersion type names
- ptTimeLog is recognized from TTimeLog, TCreateTime and TModTime
- other types (not ptComplexTypes) are recognized by their genuine type name
- ptUnicodeString is defined even if not available prior to Delphi 2009
- replace deprecated TJsonCustomParserRTTIType type from old mORMot 1.18
- TDynArrayKind is now an alias to this genuine enumerate
TRttiPropCall = ( rpcNone, rpcField, rpcMethod, rpcIndexed );
How a RTTI property definition access its value
- as returned by TPropInfo.Getter/Setter/GetterIs/SetterIs methods
TRttiPropStored = ( rpsTrue, rpsFalse, rpsGetter );
TRttiProp.IsStoredKind response - default is "stored true"
TRttiRecordAllFields = array of TRttiRecordAllField;
As returned by TRttiInfo.RecordAllFields
TRttiValueClass = ( vcNone, vcCollection, vcStrings, vcObjectList, vcList, vcSynList, vcRawUtf8List, vcESynException, vcException, vcObjectWithID );
The recognized raw RTL classes as identified in TRttiCustom.ValueRtlClass
FLOATTYPE_SIZE: array[TRttiFloat] of byte = ( 4, 8, 10 , 8, 8 );
RoSByte roUByte roSWord roUWord roSLong roULong roSQWord, roUQWord quick retrieve how many bytes a floating-point consist in
NO_INDEX = integer($80000000);
Delphi requires those definitions for proper inlining
ORDTYPE_SIZE: array[TRttiOrd] of byte = ( 1, 1, 2, 2, 4, 4 );
Quick retrieve how many bytes an ordinal consist in
ptComplexTypes = [ptArray, ptRecord, ptCustom, ptTimeLog, ptOrm, ptDynArray, ptEnumeration, ptSet, ptClass, ptInterface];
Which TRttiParserType are not simple types
- ptTimeLog and ptOrm are complex, since more than one TypeInfo() may map to their TRttiParserType - see also TRttiParserComplexType
PTC_NAME: array[TRttiParserComplexType] of RawUtf8 = ( '', 'TTimeLog', 'TCreateTime', 'TModTime', 'TID', '', 'TRecordReference', 'TRecordReferenceToBeDeleted', 'TRecordVersion');
PtNone ptArray ptBoolean ptByte ptCardinal ptCurrency ptDouble ptExtended ptInt64 ptInteger ptQWord ptRawByteString ptRawJson ptRawUtf8 ptRecord ptSingle ptString ptSynUnicode ptDateTime ptDateTimeMS ptGuid ptHash128 ptHash256 ptHash512 ptOrm ptTimeLog ptUnicodeString ptUnixTime ptUnixMSTime ptVariant ptWideString ptWinAnsi ptWord ptEnumeration ptSet ptClass ptDynArray ptInterface ptPUtf8Char ptCustom type definition name lookup to the TRttiParserComplexType values
- for ptComplexTypes types, with PT_NAME[]=''
- ptcSpecificClassID returns '' since T....ID types are variable
PTC_PT: array[TRttiParserComplexType] of TRttiParserType = ( ptNone, ptTimeLog, ptTimeLog, ptTimeLog, ptOrm, ptNone, ptOrm, ptOrm, ptOrm );
Simple lookup to the TRttiParserType of a complex type
ptMultiLineStringTypes = [ptRawUtf8, ptString, ptSynUnicode, ptUnicodeString, ptWideString, ptWinAnsi];
Which TRttiParserType types could be serialized as multi-line JSON "text"
- e.g. plain RawUtf8 which may include \n line feeds but not RawByteString, TTimeLog or THash128, which never include line breaks within their "value"
ptPtrInt = ptInteger ;
Map a PtrInt type to the TRttiParserType set
ptPtrUInt = ptCardinal ;
Map a PtrUInt type to the TRttiParserType set
ptStringTypes = [ptRawByteString .. ptRawUtf8, ptString .. ptHash512, ptTimeLog, ptUnicodeString, ptWideString, ptWinAnsi, ptPUtf8Char];
Which TRttiParserType types are (usually) serialized as JSON "text"
- actual serialization may depend e.g. on TTextWriterWriteObjectOptions
ptUnmanagedTypes = [ptBoolean..ptQWord, ptSingle, ptDateTime..ptTimeLog, ptUnixTime, ptUnixMSTime, ptWord..ptClass];
Which TRttiParserType types don't need memory management
PT_NAME: array[TRttiParserType] of RawUtf8 = ( '', '', 'boolean', 'byte', 'cardinal', 'currency', 'double', 'extended', 'Int64', 'integer', 'QWord', 'RawByteString', 'RawJson', 'RawUtf8', '', 'single', 'string', 'SynUnicode', 'TDateTime', 'TDateTimeMS', 'TGuid', 'THash128', 'THash256', 'THash512', '', '', 'UnicodeString', 'TUnixTime', 'TUnixMSTime', 'variant', 'WideString', 'WinAnsi', 'word', '', '', '', '', '', 'PUtf8Char', '');
PtNone ptArray ptBoolean ptByte ptCardinal ptCurrency ptDouble ptExtended ptInt64 ptInteger ptQWord ptRawByteString ptRawJson ptRawUtf8 ptRecord ptSingle ptString ptSynUnicode ptDateTime ptDateTimeMS ptGuid ptHash128 ptHash256 ptHash512 ptOrm ptTimeLog ptUnicodeString ptUnixTime ptUnixMSTime ptVariant ptWideString ptWinAnsi ptWord ptEnumeration ptSet ptClass ptDynArray ptInterface ptPUtf8Char ptCustom type definition name lookup to the TRttiParserType values
- ptComplexTypes types should see PTC_NAME[] constant
PT_SIZE: array[TRttiParserType] of byte = ( 0, 0, 1, 1, 4, 8, 8, 8, 8, 4, 8, SizeOf(pointer), SizeOf(pointer), SizeOf(pointer), 0, 4, SizeOf(pointer), SizeOf(pointer), 8, 8, 16, 16, 32, 64, 8, 8, SizeOf(pointer), 8, 8, SizeOf(variant), SizeOf(pointer), SizeOf(pointer), 2, 0, 0, SizeOf(pointer), SizeOf(pointer), SizeOf(pointer), SizeOf(pointer), 0 );
PctNone pctTimeLog pctCreateTime pctModTime pctID pctSpecificClassID pctRecordReference pctRecordReferenceToBeDeleted pctRecordVersion simple lookup to the size in bytes of TRttiParserType values
rkAllTypes = [succ(low(TRttiKind))..high(TRttiKind)];
All recognized TRttiKind enumerates, i.e. all but rkUnknown
rkComplexTypes = [rkClass, rkDynArray, rkInterface];
Types which are considerated as non-simple values
rkEnumerationTypes = [rkEnumeration ];
Maps enumeration types in TRttiKind RTTI
rkGetInt64PropTypes = [rkInt64 ];
Maps ordinal values which expect TRttiProp.GetInt64Prop/SetInt64Prop
- includes 64-bit ordinals
rkGetIntegerPropTypes = rkGetInt64PropTypes + [rkInteger];
Maps value which are integer or Int64/QWord, but not ordinal char/enum/set
rkGetOrdPropTypes = rkHasRttiOrdTypes + rkComplexTypes;
Maps values which expect TRttiProp.GetOrdProp/SetOrdProp
- includes 32-bit ordinals and pointers
rkHasRttiOrdTypes = [rkInteger, rkChar, rkWChar, rkEnumeration, rkSet ];
Maps types with proper TRttiProp.RttiOrd field
- i.e. rkOrdinalTypes excluding the 64-bit values
rkManagedTypes = [rkLString, rkWstring, rkArray, rkRecord, rkDynArray, rkInterface, rkVariant ];
Potentially managed types in TRttiKind enumerates
rkNumberTypes = rkOrdinalTypes + [ rkFloat ];
Maps integer and floating point types in TRttiKind RTTI enumerates
rkOrdinalTypes = rkHasRttiOrdTypes + [ rkInt64 ];
Maps 1, 8, 16, 32 and 64-bit ordinal in TRttiKind RTTI enumerates
rkPerReference = rkStringTypes + rkComplexTypes;
Types which are stored as pointers so are always accessed by reference
rkRecordOrArrayTypes = rkRecordTypes + [rkArray];
Maps records or static arrays
rkRecordOrDynArrayTypes = rkRecordTypes + [rkDynArray];
Maps records or dynamic arrays
rkRecordTypes = [rkRecord ];
Maps record or object in TTypeKind RTTI enumerates
rkStringTypes = [rkLString, rkWString ];
Maps string/text types in TRttiKind RTTI enumerates, excluding shortstring
rkWideStringTypes = [ rkWString ];
Maps UTF-16 string in TRttiKind RTTI enumerates
RTTIHASH_MAX = 31 ;
TRttiCustomList stores its TypeInfo() by Kind + PRttiInfo/Name
- optimized "hash table of the poor" (tm) for FindType() and Find(Name)
- should be a bit mask (i.e. power of two minus 1)
| Functions or procedures | Description | |
|---|---|---|
| ClassFieldAllProps | Retrieve the PRttiProp values of all published properties of a class | |
| ClassFieldCountWithParents | Retrieve the total number of properties for a class, including its parents | |
| ClassFieldInstance | Retrieve a class Field property instance from a Property class type | |
| ClassFieldInstance | Retrieve a class Field property instance from a Property Name | |
| ClassFieldInstances | Retrieve all class Field property instances from a Property class type | |
| ClassFieldInt64 | Retrieve an integer/Int64 Field propery value from a Property Name | |
| ClassFieldNamesAllProps | Retrieve the field names of all published properties of a class | |
| ClassFieldNamesAllPropsAsText | Retrieve the field names of all published properties of a class | |
| ClassFieldProp | Retrieve a Field property RTTI information from a Property Name | |
| ClassFieldPropInstanceMatchingClass | Retrieve a class instance property value matching a class type | |
| ClassFieldPropWithParents | Retrieve a Field property RTTI information from a Property Name | |
| ClassFieldPropWithParentsFromClassOffset | Retrieve a Field property RTTI information searching for an exact Property offset address | |
| ClassFieldPropWithParentsFromClassType | Retrieve a Field property RTTI information searching for an exact Property class type | |
| ClassFieldPropWithParentsFromUtf8 | Retrieve a Field property RTTI information from a Property Name | |
| ClassFieldPropWithParentsInheritsFromClassType | Retrieve a Field property RTTI information searching for an inherited Property class type | |
| ClassHasPublishedFields | Returns TRUE if the class has some published fields, including its parents | |
| ClassHierarchyWithField | Retrieve all class hierachy types which have some published properties | |
| ClearObject | Will reset all the object properties to their default | |
| CopyCollection | Copy two TCollection instances | |
| CopyObject | Create a new object instance, from an existing one | |
| CopyObject | Copy class published properties via names using RTTI | |
| CopySeveral | Efficiently copy several (dynamic) array items | |
| CopyStrings | Copy two TStrings instances | |
| DynArrayCopy | Create a dynamic array from another one | |
| DynArrayEnsureUnique | Same as Value := copy(Value) but faster and with no temporary variable | |
| DynArrayGrow | Low-level size up of a dynamic array | |
| DynArrayNew | Low-level initialization of a dynamic array | |
| EnsureUnique | Same as Value := copy(Value) but faster and with no temporary variable | |
| EnsureUnique | Same as Value := copy(Value) but faster and with no temporary variable | |
| EnsureUnique | Same as Value := copy(Value) but faster and with no temporary variable | |
| FastDynArrayClear | Low-level finalization of a dynamic array of any kind | |
| FastFinalizeArray | Low-level finalization of all dynamic array items of any kind | |
| FastRecordClear | Clear the managed fields of a record content | |
| FillZeroRtti | Fill all sensitive fields of this class or record with zeros | |
| FinalizeObject | Release all low-level managed fields of this instance | |
| FindCustomProp | Low-level internal function use when inlining TRttiCustomProps.Find() | |
| FindPrivateSlot | Low-level internal function used e.g. by TRttiCustom.GetPrivateSlot() | |
| GetCaptionFromClass | UnCamelCase and translate the class name, triming any left 'T' 'TSyn' 'TOrm' | |
| GetCaptionFromEnum | UnCamelCase and translate the enumeration item | |
| GetCaptionFromTrimmed | Low-level helper to retrieve a (translated) caption from a PShortString | |
| GetDisplayNameFromClass | Will get a class name as UTF-8 | |
| GetEnumCaptions | Helper to retrieve all (translated) caption texts of an enumerate | |
| GetEnumName | Helper to retrieve the text of an enumerate item | |
| GetEnumNames | Helper to retrieve all texts of an enumerate | |
| GetEnumNameTrimed | Get the corresponding enumeration name, without the first lowercase chars | |
| GetEnumNameUnCamelCase | Get the enumeration name, without the first lowercase chars, and uncamelcased | |
| GetEnumNameValue | Helper to retrieve the index of an enumerate item from its text | |
| GetEnumNameValue | Helper to retrieve the index of an enumerate item from its text | |
| GetEnumNameValueTrimmed | Retrieve the index of an enumerate item from its left-trimmed text | |
| GetEnumNameValueTrimmedExact | Retrieve the index of an enumerate item from its left-trimmed text | |
| GetEnumTrimmedNames | Helper to retrieve all trimmed texts of an enumerate as UTF-8 strings | |
| GetEnumTrimmedNames | Helper to retrieve all trimmed texts of an enumerate | |
| GetEnumType | Helper to retrieve low-level RTTI information of an enumeration type | |
| GetInstanceByPath | Retrieve a (possibly nested) class property RTTI and instance by path | |
| GetInterfaceFromEntry | Execute an instance method from its RTTI per-interface information | |
| GetPublishedMethods | Retrieve published methods information about any class instance | |
| GetRttiClass | Retrieve the class RTTI information for a specific class | |
| GetRttiClassGuid | Returns all TGuid implemented by a given class | |
| GetRttiInterface | Retrieve methods information of a given IInvokable | |
| GetRttiProp | Retrieve the class property RTTI information for a specific class | |
| GetRttiProps | Retrieve the class property RTTI information for a specific class | |
| GetSetCsvValue | Helper to parse some CSV values into a set, returned as 64-bit | |
| GetSetName | Helper to retrieve the CSV text of all enumerate items defined in a set | |
| GetSetNameShort | Helper to retrieve the CSV text of all enumerate items defined in a set | |
| InterfaceEntryIsStandard | Check if a pre-computed PInterfaceEntry has a direct IOffset information | |
| IsObjectDefaultOrVoid | Returns TRUE on a nil instance or if all its published properties are default/0 | |
| IsRawUtf8DynArray | Check if the TypeInfo() points to an "array of RawUtf8" | |
| ItemSizeToDynArrayKind | Internal function used e.g. for enumerations and sets | |
| ObjectToRecord | Copy an object instance properties into a record | |
| ParserTypeToTypeInfo | Retrieve the TypeInfo() from PT_INFO[] PTC_INFO[] constant arrays | |
| RawUtf8DynArrayClear | Low-level finalization of a dynamic array of RawUtf8 | |
| RecordClearSeveral | Efficient finalization of successive record items from a (dynamic) array | |
| RecordCopy | Copy a record content from source to Dest | |
| RecordToObject | Copy record properties into an object instance | |
| RecordZero | Initialize a record content | |
| SetDefaultValuesObject | Set any default integer or enumerates (including boolean) published properties values for a TPersistent/TSynPersistent | |
| SetEnumFromOrdinal | Store an enumeration value from its ordinal representation | |
| SetNamesValue | Low-level function parsing Value/ValueLen into a set, returned as 64-bit | |
| SetObjectFromExecutableCommandLine | Fill a class instance properties from command line switches | |
| SetValueObject | Set any (potentially nested) object property by path | |
| StringClearSeveral | Efficient finalization of successive RawUtf8 items from a (dynamic) array | |
| TObjectWithCustomCreateRttiCustomSetParser | Internal wrapper to protected TObjectWithCustomCreate.RttiCustomSetParser() | |
| TObjectWithIDDynArrayCompare | TDynArraySortCompare compatible function, sorting by TObjectWithID/TOrm.ID | |
| TObjectWithIDDynArrayHashOne | TDynArrayHashOne compatible function, hashing TObjectWithID/TOrm.ID | |
| ToText | Defined here to avoid circular dependency in mormot.core.os.pas | |
| ToText | Retrieve the text name of one TRttiKind enumerate | |
| ToText | Defined here to avoid circular dependency in mormot.core.os.pas | |
| ToText | PctNone pctTimeLog pctCreateTime pctModTime pctID pctSpecificClassID pctRecordReference pctRecordReferenceToBeDeleted pctRecordVersion retrieve the text name of one TRttiParserType enumerate | |
| TypeInfoToDynArrayTypeInfo | Recognize most simple types and return their known dynamic array RTTI | |
| VariantDynArrayClear | Faster alternative to Finalize(aVariantDynArray) |
function ClassFieldAllProps(ClassType: TClass; Types: TRttiKinds = [low(TRttiKind)..high(TRttiKind)]): PRttiPropDynArray;
Retrieve the PRttiProp values of all published properties of a class
- you could select which property types should be included in the list
function ClassFieldCountWithParents(ClassType: TClass; onlyWithoutGetter: boolean = false): integer;
Retrieve the total number of properties for a class, including its parents
function ClassFieldInstance(Instance: TObject; const PropName: ShortString; PropClassType: TClass; out PropInstance): boolean; overload;
Retrieve a class Field property instance from a Property Name
- this special version also searches into parent properties (TRttiProp search scope is only inside the current class level)
- returns TRUE and set PropInstance if a matching property was found
function ClassFieldInstance(Instance: TObject; PropClassType: TClass; out PropInstance): boolean; overload;
Retrieve a class Field property instance from a Property class type
- this version also searches into parent properties
- returns TRUE and set PropInstance if a matching property was found
function ClassFieldInstances(Instance: TObject; PropClassType: TClass): TObjectDynArray;
Retrieve all class Field property instances from a Property class type
- this version also searches into parent properties
- returns all matching property instances found
function ClassFieldInt64(Instance: TObject; const PropName: ShortString; out PropValue: Int64): boolean;
Retrieve an integer/Int64 Field propery value from a Property Name
- this special version also searches into parent properties (TRttiProp search scope is only inside the current class level)
- returns TRUE and set PropValue if a matching property was found
function ClassFieldNamesAllProps( ClassType: TClass; IncludePropType: boolean = false; Types: TRttiKinds = [low(TRttiKind)..high(TRttiKind)]): TRawUtf8DynArray;
Retrieve the field names of all published properties of a class
- will optionally append the property type to the name, e.g 'Age: integer'
- you could select which property types should be included in the list
function ClassFieldNamesAllPropsAsText( ClassType: TClass; IncludePropType: boolean = false; Types: TRttiKinds = [low(TRttiKind)..high(TRttiKind)]): RawUtf8;
Retrieve the field names of all published properties of a class
- will optionally append the property type to the name, e.g 'Age: integer'
- you could select which property types should be included in the list
function ClassFieldProp(ClassType: TClass; const PropName: ShortString): PRttiProp;
Retrieve a Field property RTTI information from a Property Name
function ClassFieldPropInstanceMatchingClass(aSearchedInstance: TObject; aSearchedClassType: TClass): TObject;
Retrieve a class instance property value matching a class type
- if aSearchedInstance is aSearchedClassType, will return aSearchedInstance
- if aSearchedInstance is not aSearchedClassType, it will try all nested properties of aSearchedInstance for a matching aSearchedClassType: if no exact match is found, will return aSearchedInstance
function ClassFieldPropWithParents(aClassType: TClass; const aPropName: ShortString; aCaseSensitive: boolean = false): PRttiProp;
Retrieve a Field property RTTI information from a Property Name
- this special version also searches into parent properties (TRttiProp search scope is only inside the current class level)
function ClassFieldPropWithParentsFromClassOffset(aClassType: TClass; aSearchedOffset: pointer): PRttiProp;
Retrieve a Field property RTTI information searching for an exact Property offset address
- this special version also searches into parent properties
function ClassFieldPropWithParentsFromClassType(aClassType, aSearchedClassType: TClass): PRttiProp;
Retrieve a Field property RTTI information searching for an exact Property class type
- this special version also searches into parent properties
function ClassFieldPropWithParentsFromUtf8(aClassType: TClass; PropName: PUtf8Char; PropNameLen: integer; aCaseSensitive: boolean = false): PRttiProp;
Retrieve a Field property RTTI information from a Property Name
- this special version also searches into parent properties (TRttiProp search scope is only inside the current class level)
function ClassFieldPropWithParentsInheritsFromClassType(aClassType, aSearchedClassType: TClass): PRttiProp;
Retrieve a Field property RTTI information searching for an inherited Property class type
- this special version also searches into parent properties
function ClassHasPublishedFields(ClassType: TClass): boolean;
Returns TRUE if the class has some published fields, including its parents
function ClassHierarchyWithField(ClassType: TClass): TClassDynArray;
Retrieve all class hierachy types which have some published properties
procedure ClearObject(Value: TObject; FreeAndNilNestedObjects: boolean = false);
Will reset all the object properties to their default
- strings will be set to '', numbers to 0
- if FreeAndNilNestedObjects is the default FALSE, will recursively reset all nested class properties values
- if FreeAndNilNestedObjects is TRUE, will FreeAndNil() all the nested class properties
- for a TOrm, use its ClearProperties method instead, which will handle the ID property, and any nested JOINed instances
procedure CopyCollection(Source, Dest: TCollection);
Copy two TCollection instances
- will call CopyObject() in loop to repopulate the Dest collection, which will work even if Assign() method was not overriden
procedure CopyObject(aFrom, aTo: TObject); overload;
Copy class published properties via names using RTTI
- copy integer, Int64, enumerates (including boolean), variant, records, dynamic arrays, classes and any string properties (excluding ShortString)
- TCollection items can be copied also, if they are of the same exact class
- object properties instances are created in aTo if the objects are not TOrm children (in this case, these are not class instances, but INTEGER reference to records, so only the integer value is copied), that is for regular classes
- see also TRttiMap for custom mapping between classes
function CopyObject(aFrom: TObject): TObject; overload;
Create a new object instance, from an existing one
- will create a new instance of the same class, then call the overloaded CopyObject() procedure to copy its values
- caller should use "CopyObject(...) as TDestClass" for safety
- see also TRttiMap for custom mapping between classes
procedure CopySeveral(Dest, Source: PByte; SourceCount: PtrInt; ItemInfo: PRttiInfo; ItemSize: PtrInt);
Efficiently copy several (dynamic) array items
- faster than the RTL CopyArray() function
procedure CopyStrings(Source, Dest: TStrings);
Copy two TStrings instances
- will just call Dest.Assign(Source) in practice
procedure DynArrayCopy(Dest, Source: PPointer; Info: PRttiInfo; SourceExtCount: PInteger = nil);
Create a dynamic array from another one
- same as RTTI_MANAGEDCOPY[rkDynArray] but with an optional external source count
procedure DynArrayEnsureUnique(Value: PPointer; Info: PRttiInfo);
Same as Value := copy(Value) but faster and with no temporary variable
function DynArrayGrow(Dest: PPointer; Count, ItemSize: PtrInt): PAnsiChar;
Low-level size up of a dynamic array
- faster than System.DynArraySetLength() function dynamic array with RefCnt=1
- caller should ensure that Dest is not nil
- DataBytes is expected to be Count * ItemSize
function DynArrayNew(Dest: PPointer; Count, ItemSize: PtrInt): pointer;
Low-level initialization of a dynamic array
- faster than System.DynArraySetLength() function on a void dynamic array, when the RTTI is known
- caller should ensure that Dest is not nil, but Dest^ = nil (i.e. a clear/void dynamic array)
procedure EnsureUnique(var Value: TRawUtf8DynArray); overload;
Same as Value := copy(Value) but faster and with no temporary variable
procedure EnsureUnique(var Value: TVariantDynArray); overload;
Same as Value := copy(Value) but faster and with no temporary variable
procedure EnsureUnique(var Value: TIntegerDynArray); overload;
Same as Value := copy(Value) but faster and with no temporary variable
procedure FastDynArrayClear(Value: PPointer; ElemInfo: PRttiInfo);
Low-level finalization of a dynamic array of any kind
- faster than RTL Finalize() or setting nil, when you know ElemInfo
- see also TRttiInfo.Clear if you want to finalize any type
procedure FastFinalizeArray(Value: PPointer; ElemTypeInfo: PRttiInfo; Count: integer);
Low-level finalization of all dynamic array items of any kind
- as called by FastDynArrayClear(), after dec(RefCnt) reached 0
function FastRecordClear(Value: pointer; Info: PRttiInfo): PtrInt;
Clear the managed fields of a record content
- won't reset all values to zero, only managed fields - see RecordZero()
- caller should ensure the type is indeed a record/object
- see also TRttiInfo.Clear if you want to finalize any type
- same as RTTI_FINALIZE[rkRecord]()
procedure FillZeroRtti(Info: PRttiInfo; var Value);
Fill all sensitive fields of this class or record with zeros
- RawByteString/TBytes with refcount=1 will be zeroed before freed
procedure FinalizeObject(Value: TObject);
Release all low-level managed fields of this instance
- just a wrapper around Value.CleanupInstance
function FindCustomProp(p: PRttiCustomProp; name: pointer; namelen: TStrLen; count: integer): PRttiCustomProp;
Low-level internal function use when inlining TRttiCustomProps.Find()
- caller should ensure that namelen <> 0
function FindPrivateSlot(c: TClass; slot: PPointer): pointer;
Low-level internal function used e.g. by TRttiCustom.GetPrivateSlot()
- caller should ensure that slot <> nil
function GetCaptionFromClass(C: TClass): string;
UnCamelCase and translate the class name, triming any left 'T' 'TSyn' 'TOrm'
- return RTL string type, i.e. UnicodeString for Delphi 2009+
function GetCaptionFromEnum(aTypeInfo: PRttiInfo; aIndex: integer): string;
UnCamelCase and translate the enumeration item
procedure GetCaptionFromTrimmed(PS: PShortString; var result: string);
Low-level helper to retrieve a (translated) caption from a PShortString
- as used e.g. by GetEnumCaptions or GetCaptionFromEnum
function GetDisplayNameFromClass(C: TClass): RawUtf8;
Will get a class name as UTF-8
- will trim 'T', 'TSyn' or 'TOrm' left side of the class name
- will encode the class name as UTF-8 (for Unicode Delphi versions)
- is used e.g. to extract the SQL table name for a TOrm class
procedure GetEnumCaptions(aTypeInfo: PRttiInfo; aDest: PString);
Helper to retrieve all (translated) caption texts of an enumerate
- may be used as cache for overloaded ToCaption() content
function GetEnumName(aTypeInfo: PRttiInfo; aIndex: integer): PShortString;
Helper to retrieve the text of an enumerate item
- just a wrapper around
aTypeInfo^.EnumBaseType.GetEnumNameOrd(aIndex)
procedure GetEnumNames(aTypeInfo: PRttiInfo; aDest: PPShortString);
Helper to retrieve all texts of an enumerate
- may be used as cache for overloaded ToText() content
function GetEnumNameTrimed(aTypeInfo: PRttiInfo; aIndex: integer): RawUtf8;
Get the corresponding enumeration name, without the first lowercase chars
- e.g. otDone -> 'Done'
- this will return the code-based English text; use GetEnumCaption() to retrieve the enumeration display text
function GetEnumNameUnCamelCase(aTypeInfo: PRttiInfo; aIndex: integer): RawUtf8;
Get the enumeration name, without the first lowercase chars, and uncamelcased
- e.g. otProcessDone -> 'Process done'
function GetEnumNameValue(aTypeInfo: PRttiInfo; const aValue: RawUtf8; AlsoTrimLowerCase: boolean = false): integer; overload;
Helper to retrieve the index of an enumerate item from its text
function GetEnumNameValue(aTypeInfo: PRttiInfo; aValue: PUtf8Char; aValueLen: PtrInt; AlsoTrimLowerCase: boolean = false): integer; overload;
Helper to retrieve the index of an enumerate item from its text
- returns -1 if aValue was not found
- will search for the exact text and also trim the lowercase 'a'..'z' chars on left side of the text if no exact match is found and AlsoTrimLowerCase is TRUE
function GetEnumNameValueTrimmed(aTypeInfo: PRttiInfo; aValue: PUtf8Char; aValueLen: PtrInt): integer;
Retrieve the index of an enumerate item from its left-trimmed text
- text comparison is case-insensitive for A-Z characters
- will trim the lowercase 'a'..'z' chars on left side of the supplied aValue text
- returns -1 if aValue was not found
function GetEnumNameValueTrimmedExact(aTypeInfo: PRttiInfo; aValue: PUtf8Char; aValueLen: PtrInt): integer;
Retrieve the index of an enumerate item from its left-trimmed text
- text comparison is case-sensitive for A-Z characters
- will trim the lowercase 'a'..'z' chars on left side of the supplied aValue text
- returns -1 if aValue was not found
procedure GetEnumTrimmedNames(aTypeInfo: PRttiInfo; aDest: PRawUtf8); overload;
Helper to retrieve all trimmed texts of an enumerate
- may be used as cache to retrieve UTF-8 text without lowercase 'a'..'z' chars
function GetEnumTrimmedNames(aTypeInfo: PRttiInfo): TRawUtf8DynArray; overload;
Helper to retrieve all trimmed texts of an enumerate as UTF-8 strings
- typical usage is the following:
var TXT: array[TBenchmark] of RawUtf8; ... GetEnumTrimmedNames(TypeInfo(TBenchmark), @TXT);
function GetEnumType(aTypeInfo: PRttiInfo; out List: PShortString): integer;
Helper to retrieve low-level RTTI information of an enumeration type
- just a wrapper around
aTypeInfo^.EnumBaseType(List, result);
function GetInstanceByPath(var Instance: TObject; const Path: RawUtf8; out Prop: PRttiCustomProp; PathDelim: AnsiChar = '.'): boolean;
Retrieve a (possibly nested) class property RTTI and instance by path
- as used e.g. by GetValueObject/SetValueObject wrapper functions
function GetInterfaceFromEntry(Instance: TObject; Entry: PInterfaceEntry; out Obj): boolean;
Execute an instance method from its RTTI per-interface information
- calling this function with a pre-computed PInterfaceEntry value is faster than calling the TObject.GetInterface() method, especially when the class implements several interfaces, since it avoid a slow GUID lookup
- if the interface is retrieved using a getter, will fallback to the regular TObject.GetInterface RTL method
function GetPublishedMethods(Instance: TObject; out Methods: TPublishedMethodInfoDynArray; aClass: TClass = nil): integer;
Retrieve published methods information about any class instance
- will optionaly accept a Class, in this case Instance is ignored
- will work with FPC and Delphi RTTI
function GetRttiClass(RttiClass: TClass): PRttiClass;
Retrieve the class RTTI information for a specific class
function GetRttiClassGuid(aClass: TClass): PGuidDynArray;
Returns all TGuid implemented by a given class
- TObject.GetInterfaceTable is not consistent on Delphi and FPC
function GetRttiInterface(aTypeInfo: PRttiInfo; out aDefinition: TRttiInterface): integer;
Retrieve methods information of a given IInvokable
- all methods will be added, also from inherited interface definitions
- returns the number of methods detected
function GetRttiProp(C: TClass; out PropInfo: PRttiProp): integer;
Retrieve the class property RTTI information for a specific class
- will return the number of published properties
- and set the PropInfo variable to point to the first property
- typical use to enumerate all published properties could be:
var i: integer;
CT: TClass;
P: PRttiProp;
begin
CT := ..;
repeat
for i := 1 to GetRttiProp(CT,P) do
begin
// use P^
P := P^.Next;
end;
CT := GetClassParent(CT);
until CT=nil;
end;such a loop is much faster than using the RTL's TypeInfo or RTTI units
function GetRttiProps(RttiClass: TClass): PRttiProps;
Retrieve the class property RTTI information for a specific class
function GetSetCsvValue(aTypeInfo: PRttiInfo; Csv: PUtf8Char): QWord;
Helper to parse some CSV values into a set, returned as 64-bit
- CSV could be separated by any non identifier char, e.g. ',' ';' or '|'
- see also GetSetNameValue() in mormot.core.json.pas for parsing a JSON array
function GetSetName(aTypeInfo: PRttiInfo; const value; trimmed: boolean = false): RawUtf8;
Helper to retrieve the CSV text of all enumerate items defined in a set
procedure GetSetNameShort(aTypeInfo: PRttiInfo; const value; out result: ShortString; trimlowercase: boolean = false);
Helper to retrieve the CSV text of all enumerate items defined in a set
function InterfaceEntryIsStandard(Entry: PInterfaceEntry): boolean;
Check if a pre-computed PInterfaceEntry has a direct IOffset information
function IsObjectDefaultOrVoid(Value: TObject): boolean;
Returns TRUE on a nil instance or if all its published properties are default/0
- check nested TRttiCustom.Props and TRttiCustom.ValueIterateCount
function IsRawUtf8DynArray(Info: PRttiInfo): boolean;
Check if the TypeInfo() points to an "array of RawUtf8"
- e.g. returns true for TypeInfo(TRawUtf8DynArray) or other sub-types defined as "type aNewType = type TRawUtf8DynArray"
function ItemSizeToDynArrayKind(size: integer): TRttiParserType;
Internal function used e.g. for enumerations and sets
procedure ObjectToRecord(aFrom: TObject; var aTo; aToType: PRttiInfo);
Copy an object instance properties into a record
- handle properties of the same exact type, searched by name
- copy integer, Int64, enumerates (including boolean), variant, records, dynamic arrays, classes and any string properties (excluding ShortString)
- see also TRttiMap for custom mapping between class and record
function ParserTypeToTypeInfo(pt: TRttiParserType; pct: TRttiParserComplexType): PRttiInfo;
Retrieve the TypeInfo() from PT_INFO[] PTC_INFO[] constant arrays
procedure RawUtf8DynArrayClear(var Value: TRawUtf8DynArray);
Low-level finalization of a dynamic array of RawUtf8
- faster than RTL Finalize() or setting nil
procedure RecordClearSeveral(v: PAnsiChar; info: PRttiInfo; n: integer);
Efficient finalization of successive record items from a (dynamic) array
procedure RecordCopy(var Dest; const Source; Info: PRttiInfo);
Copy a record content from source to Dest
procedure RecordToObject(const aFrom; aTo: TObject; aFromType: PRttiInfo);
Copy record properties into an object instance
- handle properties of the same exact type, searched by name
- copy integer, Int64, enumerates (including boolean), variant, records, dynamic arrays, classes and any string properties (excluding ShortString)
- see also TRttiMap for custom mapping between class and record
procedure RecordZero(Dest: pointer; Info: PRttiInfo);
Initialize a record content
- calls FastRecordClear() and FillCharFast() with 0
- do nothing if the TypeInfo is not from a record/object
procedure SetDefaultValuesObject(Instance: TObject);
Set any default integer or enumerates (including boolean) published properties values for a TPersistent/TSynPersistent
- set only the values set as "property ... default ..." at class type level
- will also reset the published properties of the nested classes
procedure SetEnumFromOrdinal(aTypeInfo: PRttiInfo; out Value; Ordinal: PtrUInt);
Store an enumeration value from its ordinal representation
procedure SetNamesValue(SetNames: PShortString; MinValue, MaxValue: integer; Value: PUtf8Char; ValueLen: PtrInt; var Result: QWord);
Low-level function parsing Value/ValueLen into a set, returned as 64-bit
function SetObjectFromExecutableCommandLine(Value: TObject; const SwitchPrefix, DescriptionSuffix: RawUtf8; CommandLine: TExecutableCommandLine = nil): boolean;
Fill a class instance properties from command line switches
- SwitchPrefix + property name will be searched in CommandLine.Names[]
- is typically used to fill a settings class instance
- won't include any nested class or dynamic array properties
function SetValueObject(Instance: TObject; const Path: RawUtf8; const Value: variant): boolean;
Set any (potentially nested) object property by path
- see also GetValueObject() from mormot.core.json
procedure StringClearSeveral(v: PPointer; n: PtrInt);
Efficient finalization of successive RawUtf8 items from a (dynamic) array
procedure TObjectWithCustomCreateRttiCustomSetParser( O: TObjectWithCustomCreateClass; Rtti: TRttiCustom);
Internal wrapper to protected TObjectWithCustomCreate.RttiCustomSetParser()
- a local TCCHook was reported to have issues on FPC with class methods
function TObjectWithIDDynArrayCompare(const Item1, Item2): integer;
TDynArraySortCompare compatible function, sorting by TObjectWithID/TOrm.ID
function TObjectWithIDDynArrayHashOne(const Elem; Hasher: THasher): cardinal;
TDynArrayHashOne compatible function, hashing TObjectWithID/TOrm.ID
function ToText(w: TWellKnownSid): PShortString; overload;
Defined here to avoid circular dependency in mormot.core.os.pas
function ToText(t: TRttiParserType): PShortString; overload;
PctNone pctTimeLog pctCreateTime pctModTime pctID pctSpecificClassID pctRecordReference pctRecordReferenceToBeDeleted pctRecordVersion retrieve the text name of one TRttiParserType enumerate
function ToText(cmd: TParseCommands): ShortString; overload;
Defined here to avoid circular dependency in mormot.core.os.pas
function ToText(k: TRttiKind): PShortString; overload;
Retrieve the text name of one TRttiKind enumerate
function TypeInfoToDynArrayTypeInfo(ElemInfo: PRttiInfo; ExpectExactElemInfo: boolean; ParserType: PRttiParserType = nil): PRttiInfo;
Recognize most simple types and return their known dynamic array RTTI
- returns nil if we don't know any dynamic array for this type
- ExpectExactElemInfo=true ensure that result's ArrayRtti.Info = ElemInfo
- currently not called: IList<T> and IKeyValue<T> just use TypeInfo(T)
procedure VariantDynArrayClear(var Value: TVariantDynArray);
Faster alternative to Finalize(aVariantDynArray)
- this function will take account and optimize the release of a dynamic array of custom variant types values
- for instance, an array of TDocVariant will be optimized for speed
PTC_INFO: array[TRttiParserComplexType] of PRttiInfo;
Simple lookup to the plain RTTI type of most simple managed types
- nil if the complex type is not known
- mormot.orm.base may set the exact TypeInfo(TRecordReference) value - this unit set plain TypeInfo(QWord) which is enough for JSON Serialization
PTC_RTTI: array[TRttiParserComplexType] of TRttiCustom;
Direct lookup to the TRttiCustom of TRttiParserComplexType values
PT_INFO: array[TRttiParserType] of PRttiInfo;
Simple lookup to the plain RTTI type of most simple managed types
- nil for unmanaged types (e.g. rkOrdinals) or for more complex types requering additional PRttiInfo (rkRecord, rkDynArray, rkArray...)
- you can use PT_INFO[] for types with no RTTI before Delphi 2010, for instance PT_INFO[ptGuid], PT_INFO[ptHash128], PT_INFO[ptHash256] and PT_INFO[ptHash512] since oldest compilers refuse to compile TypeInfo(TGuid), TypeInfo(THash128), TypeInfo(THash256) and TypeInfo(THash512)
PT_RTTI: array[TRttiParserType] of TRttiCustom;
Direct lookup to the TRttiCustom of TRttiParserType values
Rtti: TRttiCustomList;
Low-level access to the list of registered PRttiInfo/TRttiCustom/TRttiJson
RTTI_FINALIZE: TRttiFinalizers;
Lookup table of finalization functions for managed types
- as used by TRttiInfo.Clear() inlined method
- RTTI_FINALIZE[...]=nil for unmanaged types (e.g. rkOrdinalTypes)
RTTI_FROM_ORD: array[TRttiOrd] of function(P: pointer): Int64;
Convert an ordinal value from its (signed) pointer-sized integer representation
RTTI_MANAGEDCOPY: TRttiCopiers;
Lookup table of copy function for managed types
- as used by TRttiInfo.Copy() inlined method
- RTTI_MANAGEDCOPY[...]=nil for unmanaged types (e.g. rkOrdinalTypes)
RTTI_TO_FLOAT: array[TRttiFloat] of procedure(P: pointer; Value: TSynExtended);
Convert a float value into its RTTI-defined binary buffer
RTTI_TO_ORD: array[TRttiOrd] of procedure(P: pointer; Value: PtrInt);
Convert an ordinal value into its RTTI-defined binary buffer