3 This file is part of the Free Pascal run time library
.
5 Copyright (c
) 1999-2000 by Florian Klaempfl
6 member of the Free Pascal development team
8 See the file COPYING
.FPC
, included
in this distribution
,
9 for details about the copyright
.
11 This program is distributed
in the hope that it will be useful
,
12 but WITHOUT ANY WARRANTY
; without even the implied warranty of
13 MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE
.
15 **********************************************************************}
17 { This unit provides the same functionality as the TypInfo Unit
}
32 PShortString
=^ShortString
;
49 {$MINENUMSIZE 1 this saves a lot of memory }
50 // if you change one of the following enumeration types
51 // you have also to change the compiler in an appropriate way !
52 TTypeKind = (tkUnknown,tkInteger,tkChar,tkEnumeration,
53 tkFloat,tkSet,tkMethod,tkSString,tkLString,tkAString,
54 tkWString,tkVariant,tkArray,tkRecord,tkInterface,
55 tkClass,tkObject,tkWChar,tkBool,tkInt64,tkQWord,
56 tkDynArray,tkInterfaceRaw);
58 TTOrdType = (otSByte,otUByte,otSWord,otUWord,otSLong,otULong);
60 TFloatType = (ftSingle,ftDouble,ftExtended,ftComp,ftCurr,
62 TMethodKind = (mkProcedure,mkFunction,mkConstructor,mkDestructor,
63 mkClassProcedure, mkClassFunction);
64 TParamFlags = set of (pfVar,pfConst,pfArray,pfAddress,pfReference,pfOut);
65 TIntfFlags = set of (ifHasGuid,ifDispInterface,ifDispatch);
67 {$MINENUMSIZE DEFAULT}
78 TTypeKinds = set of TTypeKind;
84 // here the type data follows as TTypeData record
87 PTypeInfo = ^TTypeInfo;
88 PPTypeInfo = ^PTypeInfo;
90 PTypeData = ^TTypeData;
91 TTypeData = packed record
93 tkUnKnown,tkLString,tkWString,tkAString,tkVariant:
95 tkInteger,tkChar,tkEnumeration,tkWChar:
98 tkInteger,tkChar,tkEnumeration,tkBool,tkWChar : (
99 MinValue,MaxValue : Longint;
103 BaseType : PTypeInfo;
104 NameList : ShortString)
107 (CompType : PTypeInfo)
110 (FloatType : TFloatType);
115 ParentInfo : PTypeInfo;
116 PropCount : SmallInt;
117 UnitName : ShortString
118 // here the properties follow as array of TPropInfo
121 (MethodKind : TMethodKind;
123 ParamList : array[0..1023] of Char
124 {in reality ParamList is a array[1..ParamCount] of:
127 ParamName : ShortString;
128 TypeName : ShortString;
131 ResultType : ShortString}
134 (MinInt64Value, MaxInt64Value: Int64);
136 (MinQWordValue, MaxQWordValue: QWord);
142 // unsed, just for completeness
143 TPropData = packed record
145 PropList : record end;
148 PPropInfo = ^TPropInfo;
149 TPropInfo = packed record
150 PropType : PTypeInfo;
153 StoredProc : Pointer;
156 NameIndex : SmallInt;
158 // contains the type of the Get/Set/Storedproc, see also ptxxx
162 // 6 : true, constant index property
168 TProcInfoProc = procedure(PropInfo : PPropInfo) of object;
170 PPropList = ^TPropList;
171 TPropList = array[0..65535] of PPropInfo;
174 tkAny = [Low(TTypeKind)..High(TTypeKind)];
175 tkMethods = [tkMethod];
176 tkProperties = tkAny-tkMethods-[tkUnknown];
178 { general property handling }
179 // just skips the id and the name
180 function GetTypeData(TypeInfo : PTypeInfo) : PTypeData;
182 // searches in the property PropName
183 function GetPropInfo(TypeInfo : PTypeInfo;const PropName : string) : PPropInfo;
184 procedure GetPropInfos(TypeInfo : PTypeInfo;PropList : PPropList);
185 function GetPropList(TypeInfo : PTypeInfo;TypeKinds : TTypeKinds;
186 PropList : PPropList) : Integer;
188 // returns true, if PropInfo is a stored property
189 function IsStoredProp(Instance : TObject;PropInfo : PPropInfo) : Boolean;
191 { subroutines to read/write properties }
192 function GetOrdProp(Instance : TObject;PropInfo : PPropInfo) : Longint;
193 procedure SetOrdProp(Instance : TObject;PropInfo : PPropInfo;
196 function GetStrProp(Instance : TObject;PropInfo : PPropInfo) : Ansistring;
197 procedure SetStrProp(Instance : TObject;PropInfo : PPropInfo;
198 const Value : Ansistring);
200 function GetFloatProp(Instance : TObject;PropInfo : PPropInfo) : Extended;
201 procedure SetFloatProp(Instance : TObject;PropInfo : PPropInfo;
204 function GetVariantProp(Instance : TObject;PropInfo : PPropInfo): Variant;
205 procedure SetVariantProp(Instance : TObject;PropInfo : PPropInfo;
206 const Value: Variant);
208 function GetMethodProp(Instance : TObject;PropInfo : PPropInfo) : TMethod;
209 procedure SetMethodProp(Instance : TObject;PropInfo : PPropInfo;
210 const Value : TMethod);
212 function GetInt64Prop(Instance: TObject; PropInfo: PPropInfo): Int64;
213 procedure SetInt64Prop(Instance: TObject; PropInfo: PPropInfo;
217 function GetEnumName(TypeInfo : PTypeInfo;Value : Integer) : string;
218 function GetEnumValue(TypeInfo : PTypeInfo;const Name : string) : Integer;
222 BooleanIdents: array[Boolean] of String = ('False
', 'True
');
223 DotSep: String = '.';
235 function CallIntegerFunc(s: Pointer; Address: Pointer; Index, IValue: LongInt): Int64; assembler;
239 // ? Indexed function
248 // now the result is in EDX:EAX
251 function CallIntegerProc(s : Pointer;Address : Pointer;Value : Integer; INdex,IValue : Longint) : Integer;assembler;
258 // ? Indexed procedure
269 function CallExtendedFunc(s : Pointer;Address : Pointer; INdex,IValue : Longint) : Extended;assembler;
273 // ? Indexed function
285 function CallExtendedProc(s : Pointer;Address : Pointer;Value : Extended; INdex,IVAlue : Longint) : Integer;assembler;
294 // ? Indexed procedure
305 function CallBooleanFunc(s : Pointer;Address : Pointer; Index,IValue : Longint) : Boolean;assembler;
309 // ? Indexed function
320 // Assembler functions can't have short stringreturn values
.
321 // So we make a procedure with var parameter
.
322 // That
's not true (FK)
324 Procedure CallSStringFunc(s : Pointer;Address : Pointer; INdex,IValue : Longint;
325 Var Res: Shortstring);assembler;
329 // ? Indexed function
335 // the result is stored in an invisible parameter
342 Procedure CallSStringProc(s : Pointer;Address : Pointer;Const Value : ShortString; INdex,IVAlue : Longint);assembler;
349 // ? Indexed procedure
362 function GetTypeData(TypeInfo : PTypeInfo) : PTypeData;
365 GetTypeData:=PTypeData(pointer(TypeInfo)+2+PByte(pointer(TypeInfo)+1)^);
368 function GetPropInfo(TypeInfo : PTypeInfo;const PropName : string) : PPropInfo;
377 while Assigned(TypeInfo) do
380 hp:=GetTypeData(Typeinfo);
382 // the class info rtti the property rtti follows
384 Result:=PPropInfo(pointer(@hp^.UnitName)+Length(hp^.UnitName)+1+SizeOF(Word));
385 for i:=1 to hp^.PropCount do
387 // found a property of that name ?
388 if Upcase(Result^.Name)=P then
391 // skip to next property
392 Result:=PPropInfo(pointer(@Result^.Name)+byte(Result^.Name[0])+1);
395 Typeinfo:=hp^.ParentInfo;
400 function IsStoredProp(Instance : TObject;PropInfo : PPropInfo) : Boolean;
403 case (PropInfo^.PropProcs shr 4) and 3 of
405 IsStoredProp:=PBoolean(Pointer(Instance)+Longint(PropInfo^.StoredProc))^;
407 IsStoredProp:=CallBooleanFunc(Instance,PropInfo^.StoredProc,0,0);
409 IsStoredProp:=CallBooleanFunc(Instance,ppointer(Pointer(Instance.ClassType)+Longint(PropInfo^.StoredProc))^,0,0);
411 IsStoredProp:=LongBool(PropInfo^.StoredProc);
415 procedure GetPropInfos(TypeInfo : PTypeInfo;PropList : PPropList);
417 Store Pointers to property information in the list pointed
418 to by proplist. PRopList must contain enough space to hold ALL
428 TD:=GetTypeData(TypeInfo);
429 // Get this objects TOTAL published properties count
430 TP:=(@TD^.UnitName+Length(TD^.UnitName)+1);
432 // Now point TP to first propinfo record.
433 Inc(Longint(TP),SizeOF(Word));
437 Inc(Longint(PropList),SizeOf(Pointer));
438 // Point to TP next propinfo record.
439 // Located at Name[Length(Name)+1] !
440 TP:=PPropInfo(pointer(@TP^.Name)+PByte(@TP^.Name)^+1);
443 // recursive call for parent info.
444 If TD^.Parentinfo<>Nil then
445 GetPropInfos (TD^.ParentInfo,PropList);
448 Procedure InsertProp (PL : PProplist;PI : PPropInfo; Count : longint);
454 While (I<Count) and (PI^.Name>PL^[I]^.Name) do Inc(I);
456 Move(PL^[I], PL^[I+1], (Count - I) * SizeOf(Pointer));
460 function GetPropList(TypeInfo : PTypeInfo;TypeKinds : TTypeKinds;
461 PropList : PPropList) : Integer;
464 Store Pointers to property information OF A CERTAIN KIND in the list pointed
465 to by proplist. PRopList must contain enough space to hold ALL
468 Var TempList : PPropList;
469 PropInfo : PPropinfo;
474 Count:=GetTypeData(TypeInfo)^.Propcount;
477 GetMem(TempList,Count*SizeOf(Pointer));
479 GetPropInfos(TypeInfo,TempList);
480 For I:=0 to Count-1 do
482 PropInfo:=TempList^[i];
483 If PropInfo^.PropType^.Kind in TypeKinds then
485 InsertProp(PropList,PropInfo,Result);
490 FreeMem(TempList,Count*SizeOf(Pointer));
495 Procedure SetIndexValues (P: PPRopInfo; Var Index,IValue : Longint);
498 Index:=((P^.PropProcs shr 6) and 1);
505 function GetOrdProp(Instance : TObject;PropInfo : PPropInfo) : Longint;
508 value,Index,Ivalue : longint;
512 SetIndexValues(PropInfo,Index,Ivalue);
513 case (PropInfo^.PropProcs) and 3 of
515 Value:=PLongint(Pointer(Instance)+Longint(PropInfo^.GetProc))^;
517 Value:=CallIntegerFunc(Instance,PropInfo^.GetProc,Index,IValue);
519 Value:=CallIntegerFunc(Instance,PPointer(Pointer(Instance.ClassType)+Longint(PropInfo^.GetProc))^,Index,IValue);
521 { cut off unnecessary stuff }
522 TypeInfo := PropInfo^.PropType;
523 case TypeInfo^.Kind of
525 Value:=Value and $ff;
527 Value:=Value and $ffff;
529 case GetTypeData(TypeInfo)^.OrdType of
531 Value:=Value and $ffff;
533 Value:=Value and $ff;
539 procedure SetOrdProp(Instance : TObject;PropInfo : PPropInfo;
543 Index,IValue : Longint;
547 { cut off unnecessary stuff }
548 case GetTypeData(PropInfo^.PropType)^.OrdType of
549 otSWord,otUWord: begin
550 Value:=Value and $ffff;
553 otSByte,otUByte: begin
554 Value:=Value and $ff;
559 SetIndexValues(PropInfo,Index,Ivalue);
560 case (PropInfo^.PropProcs shr 2) and 3 of
563 1: PByte(Pointer(Instance)+Longint(PropInfo^.SetProc))^:=Byte(Value);
564 2: PWord(Pointer(Instance)+Longint(PropInfo^.SetProc))^:=Word(Value);
565 4: PLongint(Pointer(Instance)+Longint(PropInfo^.SetProc))^:=Value;
568 CallIntegerProc(Instance,PropInfo^.SetProc,Value,Index,IValue);
570 CallIntegerProc(Instance,PPointer(Pointer(Instance.ClassType)+Longint(PropInfo^.SetProc))^,Value,Index,IValue);
574 function GetStrProp(Instance: TObject; PropInfo: PPropInfo): AnsiString;
576 Index, IValue: LongInt;
577 ShortResult: ShortString;
579 SetIndexValues(PropInfo, Index, IValue);
580 case Propinfo^.PropType^.Kind of
582 case (PropInfo^.PropProcs) and 3 of
584 Result := PShortString(Pointer(Instance) + LongWord(PropInfo^.GetProc))^;
587 CallSStringFunc(Instance, PropInfo^.GetProc, Index, IValue, ShortResult);
588 Result := ShortResult;
592 CallSStringFunc(Instance, PPointer(Pointer(Instance.ClassType) +
593 LongWord(PropInfo^.GetProc))^, Index, IValue, ShortResult);
594 Result := ShortResult;
598 case (PropInfo^.PropProcs) and 3 of
600 Result := PAnsiString(Pointer(Instance) + LongWord(PropInfo^.GetProc))^;
602 Pointer(Result) := Pointer(LongWord(CallIntegerFunc(Instance, PropInfo^.GetProc, Index, IValue)));
604 Pointer(Result) := Pointer(LongWord(CallIntegerFunc(Instance,
605 PPointer(Pointer(Instance.ClassType) + LongWord(PropInfo^.GetProc))^, Index, IValue)));
608 // Property is neither of type AnsiString nor of type ShortString
609 SetLength(Result, 0);
613 procedure SetAStrProp(Instance : TObject;PropInfo : PPropInfo;
614 const Value : AnsiString);
617 Dirty trick based on fact that AnsiString is just a pointer,
618 hence can be treated like an integer type.
621 Index,Ivalue : Longint;
623 SetIndexValues(PropInfo,Index,IValue);
624 case (PropInfo^.PropProcs shr 2) and 3 of
626 PAnsiString(Pointer(Instance) + Longint(PropInfo^.SetProc))^ := Value;
628 CallIntegerProc(Instance,PropInfo^.SetProc,Longint(Pointer(Value)),Index,IValue);
630 CallIntegerProc(Instance,PPointer(Pointer(Instance.ClassType)+Longint(PropInfo^.SetProc))^,Longint(Pointer(Value)),Index,IValue);
634 procedure SetSStrProp(Instance : TObject;PropInfo : PPropInfo;
635 const Value : ShortString);
637 Var Index,IValue: longint;
640 SetIndexValues(PRopInfo,Index,IValue);
641 case (PropInfo^.PropProcs shr 2) and 3 of
643 PShortString(Pointer(Instance)+Longint(PropInfo^.SetProc))^:=Value;
645 CallSStringProc(Instance,PropInfo^.SetProc,Value,Index,IValue);
647 CallSStringProc(Instance,PPointer(Pointer(Instance.ClassType)+Longint(PropInfo^.SetProc))^,Value,Index,IValue);
651 procedure SetStrProp(Instance : TObject;PropInfo : PPropInfo;
652 const Value : AnsiString);
655 Case Propinfo^.PropType^.Kind of
656 tkSString : SetSStrProp(Instance,PropInfo,Value);
657 tkAString : SetAStrProp(Instance,Propinfo,Value);
661 function GetFloatProp(Instance : TObject;PropInfo : PPropInfo) : Extended;
664 Index,Ivalue : longint;
669 SetIndexValues(PropInfo,Index,Ivalue);
670 case (PropInfo^.PropProcs) and 3 of
672 Case GetTypeData(PropInfo^.PropType)^.FloatType of
674 Value:=PSingle(Pointer(Instance)+Longint(PropInfo^.GetProc))^;
676 Value:=PDouble(Pointer(Instance)+Longint(PropInfo^.GetProc))^;
678 Value:=PExtended(Pointer(Instance)+Longint(PropInfo^.GetProc))^;
680 Value:=PComp(Pointer(Instance)+Longint(PropInfo^.GetProc))^;
681 { Uncommenting this code results in a internal error!!
683 Value:=PFixed16(Pointer(Instance)+Longint(PropInfo^.GetProc))^;
685 Value:=PFixed32(Pointer(Instance)+Longint(PropInfo^.GetProc))^;
689 Value:=CallExtendedFunc(Instance,PropInfo^.GetProc,Index,IValue);
691 Value:=CallExtendedFunc(Instance,PPointer(Pointer(Instance.ClassType)+Longint(PropInfo^.GetProc))^,Index,IValue);
696 procedure SetFloatProp(Instance : TObject;PropInfo : PPropInfo;
699 Var IValue,Index : longint;
702 SetIndexValues(PropInfo,Index,Ivalue);
703 case (PropInfo^.PropProcs shr 2) and 3 of
705 Case GetTypeData(PropInfo^.PropType)^.FloatType of
707 PSingle(Pointer(Instance)+Longint(PropInfo^.SetProc))^:=Value;
709 PDouble(Pointer(Instance)+Longint(PropInfo^.SetProc))^:=Value;
711 PExtended(Pointer(Instance)+Longint(PropInfo^.SetProc))^:=Value;
713 PComp(Pointer(Instance)+Longint(PropInfo^.SetProc))^:=Comp(Value);
714 { Uncommenting this code results in a internal error!!
716 PFixed16(Pointer(Instance)+Longint(PropInfo^.SetProc))^:=Value;
718 PFixed32(Pointer(Instance)+Longint(PropInfo^.SetProc))^:=Value;
722 CallExtendedProc(Instance,PropInfo^.SetProc,Value,Index,IValue);
724 CallExtendedProc(Instance,PPointer(Pointer(Instance.ClassType)+Longint(PropInfo^.SetProc))^,Value,Index,IValue);
728 function GetVariantProp(Instance : TObject;PropInfo : PPropInfo): Variant;
735 procedure SetVariantProp(Instance : TObject;PropInfo : PPropInfo;
736 const Value: Variant);
742 function GetMethodProp(Instance : TObject;PropInfo : PPropInfo) : TMethod;
746 Index,Ivalue : longint;
749 SetIndexValues(PropInfo,Index,Ivalue);
750 case (PropInfo^.PropProcs) and 3 of
752 Value:=PMethod(Pointer(Instance)+Longint(PropInfo^.GetProc));
754 Value:=PMethod(LongInt(CallIntegerFunc(Instance,PropInfo^.GetProc,Index,IValue)));
756 Value:=PMethod(LongInt(CallIntegerFunc(Instance,PPointer(Pointer(Instance.ClassType)+Longint(PropInfo^.GetProc))^,Index,IValue)));
758 GetMethodProp:=Value^;
761 procedure SetMethodProp(Instance : TObject;PropInfo : PPropInfo;
762 const Value : TMethod);
765 Index,IValue : Longint;
768 SetIndexValues(PropInfo,Index,Ivalue);
769 case (PropInfo^.PropProcs shr 2) and 3 of
771 PMethod(Pointer(Instance)+Longint(PropInfo^.SetProc))^ := Value;
773 CallIntegerProc(Instance,PropInfo^.SetProc,Integer(@Value), Index, IValue);
775 CallIntegerProc(Instance,
776 PPointer(Pointer(Instance.ClassType)+Longint(PropInfo^.SetProc))^,
777 Integer(@Value), Index, IValue);
781 function GetInt64Prop(Instance: TObject; PropInfo: PPropInfo): Int64;
783 Index, IValue: LongInt;
785 SetIndexValues(PropInfo,Index,Ivalue);
786 case PropInfo^.PropProcs and 3 of
788 Result := PInt64(Pointer(Instance)+Longint(PropInfo^.GetProc))^;
790 Result := CallIntegerFunc(Instance, PropInfo^.GetProc, Index, IValue);
792 Result := CallIntegerFunc(Instance,
793 PPointer(Pointer(Instance.ClassType) + LongInt(PropInfo^.GetProc))^,
798 procedure SetInt64Prop(Instance: TObject; PropInfo: PPropInfo;
801 // !!!: Implement me!
804 function GetEnumName(TypeInfo : PTypeInfo;Value : Integer) : string;
806 Var PS : PShortString;
810 PT:=GetTypeData(TypeInfo);
812 // If PT^.MinValue<0 then Value:=Ord(Value<>0); {map to 0/1}
816 PS:=PShortString(pointer(PS)+PByte(PS)^+1);
822 function GetEnumValue(TypeInfo : PTypeInfo;const Name : string) : Integer;
824 Var PS : PShortString;
829 If Length(Name)=0 then exit(-1);
830 PT:=GetTypeData(TypeInfo);
834 While (Result=-1) and (PByte(PS)^<>0) do
836 If CompareText(PS^, Name) = 0 then
838 PS:=PShortString(pointer(PS)+PByte(PS)^+1);
847 Revision 1.1 2002/02/19 08:25:47 sasu
850 Revision 1.1.2.6 2000/12/13 23:26:13 sg
851 * Fixed typo in SetFloatProp
852 * Rewrote GetStrProp, now all AnsiString will be correctly
855 Revision 1.1.2.5 2000/12/13 10:10:59 michael
856 + Applied patch from Mattias Gaertner, bug 1273
858 Revision 1.1.2.4 2000/12/10 14:18:50 michael
859 + Applied fix from Mattias Gaertner (bug 1288)
861 Revision 1.1.2.3 2000/12/03 21:58:53 peter
862 * typekind is the same as 1.1
864 Revision 1.1.2.2 2000/11/25 18:34:00 sg
865 * (Final) fix for AnsiString reference counter problem in SetStrProp
867 Revision 1.1.2.1 2000/07/17 07:10:29 sg
868 * Fixed GetEnumValue (bug #1049, reported by Neil Graham)
870 Revision 1.1 2000/07/13 06:31:01 michael
873 Revision 1.43 2000/06/29 08:47:13 sg
874 * Bugfix for SetAStrProp (reference counter hasn't been increased
)
875 * Implemented GetInt64Prop
877 Revision
1.42 2000/06/22 20:02:51 peter
878 * qword
,int64 rtti support basics
880 Revision
1.41 2000/06/22 15:31:09 sg
881 * Fixed a small typo
in my previous update
883 Revision
1.40 2000/06/22 15:29:31 sg
884 * Added prototypes
for GetInt64Prop
and SetInt64Prop
885 * Added constants
"BooleanIdents" and "DotSep"
887 Revision
1.39 2000/05/18 09:42:17 michael
888 + GetPropInfo now
case insensitive
890 Revision
1.38 2000/02/15 14:39:56 florian
891 * disabled FIXED
data type per default
893 Revision
1.37 2000/02/09 16:59:33 peter
896 Revision
1.36 2000/01/07 16:41:44 daniel
899 Revision
1.35 2000/01/07 16:32:29 daniel
900 * copyright
2000 added
902 Revision
1.34 2000/01/06 01:08:33 sg
903 * _This_ is the real revision
1.32... :-)
905 Revision
1.33 2000/01/06 00:23:24 pierre
906 * missing declarations
for otChar andotWChar added
908 Revision
1.32 2000/01/05 18:59:56 sg
909 * Fixed
missing () in InsertProp which caused memory corruptions
910 * GetOrdProp handles Char
and WChar now
. (there are still some
911 property types missing
!)
913 Revision
1.31 1999/12/28 12:19:36 jonas
914 * replaced
"movl mem,%eax; xorl %eax,%eax" with
"movl mem,%eax;
917 Revision
1.30 1999/11/06 14:41:31 peter
920 Revision
1.29 1999/09/16 08:59:48 florian
921 * GetPropInfo returns now
nil if the property wasn
't found
923 Revision 1.28 1999/09/15 20:27:24 florian
924 + patch of Sebastion Guenther applied: Get/SetMethodProp implementation
926 Revision 1.27 1999/09/08 16:14:43 peter
929 Revision 1.26 1999/09/03 15:39:23 michael
930 * Fixes from Sebastian Guenther
932 Revision 1.25 1999/08/29 22:21:27 michael
933 * Patch from Sebastian Guenther
935 Revision 1.24 1999/08/06 13:21:40 michael
936 * Patch from Sebastian Guenther