typinfo.pp 52 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2000 by Florian Klaempfl
  4. member of the Free Pascal development team
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. { This unit provides the same Functionality as the TypInfo Unit }
  12. { of Delphi }
  13. unit typinfo;
  14. interface
  15. {$MODE objfpc}
  16. {$inline on}
  17. {$h+}
  18. uses SysUtils;
  19. // temporary types:
  20. type
  21. {$MINENUMSIZE 1 this saves a lot of memory }
  22. // if you change one of the following enumeration types
  23. // you have also to change the compiler in an appropriate way !
  24. TTypeKind = (tkUnknown,tkInteger,tkChar,tkEnumeration,
  25. tkFloat,tkSet,tkMethod,tkSString,tkLString,tkAString,
  26. tkWString,tkVariant,tkArray,tkRecord,tkInterface,
  27. tkClass,tkObject,tkWChar,tkBool,tkInt64,tkQWord,
  28. tkDynArray,tkInterfaceRaw);
  29. TOrdType = (otSByte,otUByte,otSWord,otUWord,otSLong,otULong);
  30. TFloatType = (ftSingle,ftDouble,ftExtended,ftComp,ftCurr);
  31. TMethodKind = (mkProcedure,mkFunction,mkConstructor,mkDestructor,
  32. mkClassProcedure, mkClassFunction);
  33. TParamFlag = (pfVar,pfConst,pfArray,pfAddress,pfReference,pfOut);
  34. TParamFlags = set of TParamFlag;
  35. TIntfFlag = (ifHasGuid,ifDispInterface,ifDispatch,ifHasStrGUID);
  36. TIntfFlags = set of TIntfFlag;
  37. TIntfFlagsBase = set of TIntfFlag;
  38. {$MINENUMSIZE DEFAULT}
  39. const
  40. ptField = 0;
  41. ptStatic = 1;
  42. ptVirtual = 2;
  43. ptConst = 3;
  44. tkString = tkSString;
  45. type
  46. TTypeKinds = set of TTypeKind;
  47. ShortStringBase = string[255];
  48. {$PACKRECORDS 1}
  49. TTypeInfo = record
  50. Kind : TTypeKind;
  51. Name : ShortString;
  52. // here the type data follows as TTypeData record
  53. end;
  54. PTypeInfo = ^TTypeInfo;
  55. PPTypeInfo = ^PTypeInfo;
  56. {$PACKRECORDS C}
  57. PTypeData = ^TTypeData;
  58. TTypeData =
  59. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  60. packed
  61. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  62. record
  63. case TTypeKind of
  64. tkUnKnown,tkLString,tkWString,tkAString,tkVariant:
  65. ();
  66. tkInteger,tkChar,tkEnumeration,tkWChar,tkSet:
  67. (OrdType : TOrdType;
  68. case TTypeKind of
  69. tkInteger,tkChar,tkEnumeration,tkBool,tkWChar : (
  70. MinValue,MaxValue : Longint;
  71. case TTypeKind of
  72. tkEnumeration:
  73. (
  74. BaseType : PTypeInfo;
  75. NameList : ShortString)
  76. );
  77. tkSet:
  78. (CompType : PTypeInfo)
  79. );
  80. tkFloat:
  81. (FloatType : TFloatType);
  82. tkSString:
  83. (MaxLength : Byte);
  84. tkClass:
  85. (ClassType : TClass;
  86. ParentInfo : PTypeInfo;
  87. PropCount : SmallInt;
  88. UnitName : ShortString
  89. // here the properties follow as array of TPropInfo
  90. );
  91. tkMethod:
  92. (MethodKind : TMethodKind;
  93. ParamCount : Byte;
  94. ParamList : array[0..1023] of Char
  95. {in reality ParamList is a array[1..ParamCount] of:
  96. record
  97. Flags : TParamFlags;
  98. ParamName : ShortString;
  99. TypeName : ShortString;
  100. end;
  101. followed by
  102. ResultType : ShortString}
  103. );
  104. tkInt64:
  105. (MinInt64Value, MaxInt64Value: Int64);
  106. tkQWord:
  107. (MinQWordValue, MaxQWordValue: QWord);
  108. tkInterface:
  109. (
  110. IntfParent: PTypeInfo;
  111. IntfFlags : TIntfFlagsBase;
  112. GUID: TGUID;
  113. IntfUnit: ShortString;
  114. );
  115. tkInterfaceRaw:
  116. (
  117. RawIntfParent: PTypeInfo;
  118. RawIntfFlags : TIntfFlagsBase;
  119. IID: TGUID;
  120. RawIntfUnit: ShortString;
  121. IIDStr: ShortString;
  122. );
  123. tkDynArray:
  124. (
  125. elSize : PtrUInt;
  126. elType2 : PPTypeInfo;
  127. varType : Longint;
  128. elType : PPTypeInfo;
  129. DynUnitName: ShortStringBase
  130. );
  131. end;
  132. // unsed, just for completeness
  133. TPropData =
  134. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  135. packed
  136. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  137. record
  138. PropCount : Word;
  139. PropList : record _alignmentdummy : ptrint; end;
  140. end;
  141. {$PACKRECORDS 1}
  142. PPropInfo = ^TPropInfo;
  143. TPropInfo = packed record
  144. PropType : PTypeInfo;
  145. GetProc : Pointer;
  146. SetProc : Pointer;
  147. StoredProc : Pointer;
  148. Index : Integer;
  149. Default : Longint;
  150. NameIndex : SmallInt;
  151. // contains the type of the Get/Set/Storedproc, see also ptxxx
  152. // bit 0..1 GetProc
  153. // 2..3 SetProc
  154. // 4..5 StoredProc
  155. // 6 : true, constant index property
  156. PropProcs : Byte;
  157. Name : ShortString;
  158. end;
  159. TProcInfoProc = Procedure(PropInfo : PPropInfo) of object;
  160. PPropList = ^TPropList;
  161. TPropList = array[0..65535] of PPropInfo;
  162. const
  163. tkAny = [Low(TTypeKind)..High(TTypeKind)];
  164. tkMethods = [tkMethod];
  165. tkProperties = tkAny-tkMethods-[tkUnknown];
  166. // general property handling
  167. Function GetTypeData(TypeInfo : PTypeInfo) : PTypeData;
  168. Function GetPropInfo(TypeInfo : PTypeInfo;const PropName : string) : PPropInfo;
  169. Function GetPropInfo(TypeInfo : PTypeInfo;const PropName : string; AKinds : TTypeKinds) : PPropInfo;
  170. Function GetPropInfo(Instance: TObject; const PropName: string; AKinds: TTypeKinds) : PPropInfo;
  171. Function GetPropInfo(Instance: TObject; const PropName: string): PPropInfo;
  172. Function GetPropInfo(AClass: TClass; const PropName: string; AKinds: TTypeKinds) : PPropInfo;
  173. Function GetPropInfo(AClass: TClass; const PropName: string): PPropInfo;
  174. Function FindPropInfo(Instance: TObject; const PropName: string): PPropInfo;
  175. Function FindPropInfo(AClass:TClass;const PropName: string): PPropInfo;
  176. Procedure GetPropInfos(TypeInfo : PTypeInfo;PropList : PPropList);
  177. Function GetPropList(TypeInfo : PTypeInfo;TypeKinds : TTypeKinds; PropList : PPropList;Sorted : boolean = true):longint;
  178. Function GetPropList(TypeInfo: PTypeInfo; out PropList: PPropList): SizeInt;
  179. function GetPropList(AObject: TObject; out PropList: PPropList): Integer;
  180. // Property information routines.
  181. Function IsStoredProp(Instance: TObject;PropInfo : PPropInfo) : Boolean;
  182. Function IsStoredProp(Instance: TObject; const PropName: string): Boolean;
  183. Function IsPublishedProp(Instance: TObject; const PropName: string): Boolean;
  184. Function IsPublishedProp(AClass: TClass; const PropName: string): Boolean;
  185. Function PropType(Instance: TObject; const PropName: string): TTypeKind;
  186. Function PropType(AClass: TClass; const PropName: string): TTypeKind;
  187. Function PropIsType(Instance: TObject; const PropName: string; TypeKind: TTypeKind): Boolean;
  188. Function PropIsType(AClass: TClass; const PropName: string; TypeKind: TTypeKind): Boolean;
  189. // subroutines to read/write properties
  190. Function GetOrdProp(Instance: TObject; PropInfo : PPropInfo) : Int64;
  191. Function GetOrdProp(Instance: TObject; const PropName: string): Int64;
  192. Procedure SetOrdProp(Instance: TObject; PropInfo : PPropInfo; Value : Int64);
  193. Procedure SetOrdProp(Instance: TObject; const PropName: string; Value: Int64);
  194. Function GetEnumProp(Instance: TObject; const PropName: string): string;
  195. Function GetEnumProp(Instance: TObject; const PropInfo: PPropInfo): string;
  196. Procedure SetEnumProp(Instance: TObject; const PropName: string;const Value: string);
  197. Procedure SetEnumProp(Instance: TObject; const PropInfo: PPropInfo;const Value: string);
  198. Function GetSetProp(Instance: TObject; const PropName: string): string;
  199. Function GetSetProp(Instance: TObject; const PropName: string; Brackets: Boolean): string;
  200. Function GetSetProp(Instance: TObject; const PropInfo: PPropInfo; Brackets: Boolean): string;
  201. Procedure SetSetProp(Instance: TObject; const PropName: string; const Value: string);
  202. Procedure SetSetProp(Instance: TObject; const PropInfo: PPropInfo; const Value: string);
  203. Function GetStrProp(Instance: TObject; PropInfo : PPropInfo) : Ansistring;
  204. Function GetStrProp(Instance: TObject; const PropName: string): string;
  205. Procedure SetStrProp(Instance: TObject; const PropName: string; const Value: AnsiString);
  206. Procedure SetStrProp(Instance: TObject; PropInfo : PPropInfo; const Value : Ansistring);
  207. Function GetWideStrProp(Instance: TObject; PropInfo: PPropInfo): WideString;
  208. Function GetWideStrProp(Instance: TObject; const PropName: string): WideString;
  209. Procedure SetWideStrProp(Instance: TObject; const PropName: string; const Value: WideString);
  210. Procedure SetWideStrProp(Instance: TObject; PropInfo: PPropInfo; const Value: WideString);
  211. Function GetFloatProp(Instance: TObject; PropInfo : PPropInfo) : Extended;
  212. Function GetFloatProp(Instance: TObject; const PropName: string): Extended;
  213. Procedure SetFloatProp(Instance: TObject; const PropName: string; Value: Extended);
  214. Procedure SetFloatProp(Instance: TObject; PropInfo : PPropInfo; Value : Extended);
  215. Function GetObjectProp(Instance: TObject; const PropName: string): TObject;
  216. Function GetObjectProp(Instance: TObject; const PropName: string; MinClass: TClass): TObject;
  217. Function GetObjectProp(Instance: TObject; PropInfo: PPropInfo): TObject;
  218. Function GetObjectProp(Instance: TObject; PropInfo: PPropInfo; MinClass: TClass): TObject;
  219. Procedure SetObjectProp(Instance: TObject; const PropName: string; Value: TObject);
  220. Procedure SetObjectProp(Instance: TObject; PropInfo: PPropInfo; Value: TObject);
  221. Function GetObjectPropClass(Instance: TObject; const PropName: string): TClass;
  222. Function GetMethodProp(Instance: TObject; PropInfo: PPropInfo) : TMethod;
  223. Function GetMethodProp(Instance: TObject; const PropName: string): TMethod;
  224. Procedure SetMethodProp(Instance: TObject; PropInfo: PPropInfo; const Value : TMethod);
  225. Procedure SetMethodProp(Instance: TObject; const PropName: string; const Value: TMethod);
  226. Function GetInt64Prop(Instance: TObject; PropInfo: PPropInfo): Int64;
  227. Function GetInt64Prop(Instance: TObject; const PropName: string): Int64;
  228. Procedure SetInt64Prop(Instance: TObject; PropInfo: PPropInfo; const Value: Int64);
  229. Procedure SetInt64Prop(Instance: TObject; const PropName: string; const Value: Int64);
  230. Function GetPropValue(Instance: TObject; const PropName: string): Variant;
  231. Function GetPropValue(Instance: TObject; const PropName: string; PreferStrings: Boolean): Variant;
  232. Procedure SetPropValue(Instance: TObject; const PropName: string; const Value: Variant);
  233. Function GetVariantProp(Instance: TObject; PropInfo : PPropInfo): Variant;
  234. Function GetVariantProp(Instance: TObject; const PropName: string): Variant;
  235. Procedure SetVariantProp(Instance: TObject; const PropName: string; const Value: Variant);
  236. Procedure SetVariantProp(Instance: TObject; PropInfo : PPropInfo; const Value: Variant);
  237. function GetInterfaceProp(Instance: TObject; const PropName: string): IInterface;
  238. function GetInterfaceProp(Instance: TObject; PropInfo: PPropInfo): IInterface;
  239. procedure SetInterfaceProp(Instance: TObject; const PropName: string; const Value: IInterface);
  240. procedure SetInterfaceProp(Instance: TObject; PropInfo: PPropInfo; const Value: IInterface);
  241. // Auxiliary routines, which may be useful
  242. Function GetEnumName(TypeInfo : PTypeInfo;Value : Integer) : string;
  243. Function GetEnumValue(TypeInfo : PTypeInfo;const Name : string) : Integer;
  244. function GetEnumNameCount(enum1: PTypeInfo): SizeInt;
  245. function SetToString(TypeInfo: PTypeInfo; Value: Integer; Brackets: Boolean) : String;
  246. function SetToString(PropInfo: PPropInfo; Value: Integer; Brackets: Boolean) : String;
  247. function SetToString(PropInfo: PPropInfo; Value: Integer) : String;
  248. function StringToSet(PropInfo: PPropInfo; const Value: string): Integer;
  249. function StringToSet(TypeInfo: PTypeInfo; const Value: string): Integer;
  250. const
  251. BooleanIdents: array[Boolean] of String = ('False', 'True');
  252. DotSep: String = '.';
  253. Type
  254. EPropertyError = Class(Exception);
  255. TGetPropValue = Function (Instance: TObject; const PropName: string; PreferStrings: Boolean) : Variant;
  256. TSetPropValue = Procedure (Instance: TObject; const PropName: string; const Value: Variant);
  257. TGetVariantProp = Function (Instance: TObject; PropInfo : PPropInfo): Variant;
  258. TSetVariantProp = Procedure (Instance: TObject; PropInfo : PPropInfo; const Value: Variant);
  259. EPropertyConvertError = class(Exception); // Not used (yet), but defined for compatibility.
  260. Const
  261. OnGetPropValue : TGetPropValue = Nil;
  262. OnSetPropValue : TSetPropValue = Nil;
  263. OnGetVariantprop : TGetVariantProp = Nil;
  264. OnSetVariantprop : TSetVariantProp = Nil;
  265. Implementation
  266. uses rtlconsts;
  267. type
  268. PMethod = ^TMethod;
  269. { ---------------------------------------------------------------------
  270. Auxiliary methods
  271. ---------------------------------------------------------------------}
  272. function aligntoptr(p : pointer) : pointer;inline;
  273. begin
  274. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  275. result:=align(p,sizeof(p));
  276. {$else FPC_REQUIRES_PROPER_ALIGNMENT}
  277. result:=p;
  278. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  279. end;
  280. Function GetEnumName(TypeInfo : PTypeInfo;Value : Integer) : string;
  281. Var PS : PShortString;
  282. PT : PTypeData;
  283. begin
  284. PT:=GetTypeData(TypeInfo);
  285. // ^.BaseType);
  286. // If PT^.MinValue<0 then Value:=Ord(Value<>0); {map to 0/1}
  287. PS:=@PT^.NameList;
  288. While Value>0 Do
  289. begin
  290. PS:=PShortString(pointer(PS)+PByte(PS)^+1);
  291. Dec(Value);
  292. end;
  293. Result:=PS^;
  294. end;
  295. Function GetEnumValue(TypeInfo : PTypeInfo;const Name : string) : Integer;
  296. Var PS : PShortString;
  297. PT : PTypeData;
  298. Count : longint;
  299. sName: shortstring;
  300. begin
  301. If Length(Name)=0 then
  302. exit(-1);
  303. sName := Name;
  304. PT:=GetTypeData(TypeInfo);
  305. Count:=0;
  306. Result:=-1;
  307. PS:=@PT^.NameList;
  308. While (Result=-1) and (PByte(PS)^<>0) do
  309. begin
  310. If ShortCompareText(PS^, sName) = 0 then
  311. Result:=Count;
  312. PS:=PShortString(pointer(PS)+PByte(PS)^+1);
  313. Inc(Count);
  314. end;
  315. end;
  316. function GetEnumNameCount(enum1: PTypeInfo): SizeInt;
  317. var
  318. PS: PShortString;
  319. PT: PTypeData;
  320. Count: SizeInt;
  321. begin
  322. PT:=GetTypeData(enum1);
  323. Count:=0;
  324. Result:=0;
  325. PS:=@PT^.NameList;
  326. While (PByte(PS)^<>0) do
  327. begin
  328. PS:=PShortString(pointer(PS)+PByte(PS)^+1);
  329. Inc(Count);
  330. end;
  331. Result := Count;
  332. end;
  333. Function SetToString(PropInfo: PPropInfo; Value: Integer; Brackets: Boolean) : String;
  334. begin
  335. Result:=SetToString(PropInfo^.PropType,Value,Brackets);
  336. end;
  337. Function SetToString(TypeInfo: PTypeInfo; Value: Integer; Brackets: Boolean) : String;
  338. {$ifdef FPC_NEW_BIGENDIAN_SETS}
  339. type
  340. tsetarr = bitpacked array[0..31] of 0..1;
  341. {$endif}
  342. Var
  343. I : Integer;
  344. PTI : PTypeInfo;
  345. begin
  346. {$if defined(FPC_NEW_BIGENDIAN_SETS) and defined(FPC_BIG_ENDIAN)}
  347. case GetTypeData(TypeInfo)^.OrdType of
  348. otSByte,otUByte: Value:=Value shl 24;
  349. otSWord,otUWord: Value:=Value shl 16;
  350. end;
  351. {$endif}
  352. PTI:=GetTypeData(TypeInfo)^.CompType;
  353. Result:='';
  354. For I:=0 to SizeOf(Integer)*8-1 do
  355. begin
  356. {$ifdef FPC_NEW_BIGENDIAN_SETS}
  357. if (tsetarr(Value)[i]<>0) then
  358. {$else}
  359. if ((Value and 1)<>0) then
  360. {$endif}
  361. begin
  362. If Result='' then
  363. Result:=GetEnumName(PTI,i)
  364. else
  365. Result:=Result+','+GetEnumName(PTI,I);
  366. end;
  367. {$ifndef FPC_NEW_BIGENDIAN_SETS}
  368. Value:=Value shr 1;
  369. {$endif FPC_NEW_BIGENDIAN_SETS}
  370. end;
  371. if Brackets then
  372. Result:='['+Result+']';
  373. end;
  374. Function SetToString(PropInfo: PPropInfo; Value: Integer) : String;
  375. begin
  376. Result:=SetToString(PropInfo,Value,False);
  377. end;
  378. Const
  379. SetDelim = ['[',']',',',' '];
  380. Function GetNextElement(Var S : String) : String;
  381. Var
  382. J : Integer;
  383. begin
  384. J:=1;
  385. Result:='';
  386. If Length(S)>0 then
  387. begin
  388. While (J<=Length(S)) and Not (S[j] in SetDelim) do
  389. Inc(j);
  390. Result:=Copy(S,1,j-1);
  391. Delete(S,1,j);
  392. end;
  393. end;
  394. Function StringToSet(PropInfo: PPropInfo; const Value: string): Integer;
  395. begin
  396. Result:=StringToSet(PropInfo^.PropType,Value);
  397. end;
  398. Function StringToSet(TypeInfo: PTypeInfo; const Value: string): Integer;
  399. Var
  400. S,T : String;
  401. I : Integer;
  402. PTI : PTypeInfo;
  403. begin
  404. Result:=0;
  405. PTI:=GetTypeData(TypeInfo)^.Comptype;
  406. S:=Value;
  407. I:=1;
  408. If Length(S)>0 then
  409. begin
  410. While (I<=Length(S)) and (S[i] in SetDelim) do
  411. Inc(I);
  412. Delete(S,1,i-1);
  413. end;
  414. While (S<>'') do
  415. begin
  416. T:=GetNextElement(S);
  417. if T<>'' then
  418. begin
  419. I:=GetEnumValue(PTI,T);
  420. if (I<0) then
  421. raise EPropertyError.CreateFmt(SErrUnknownEnumValue, [T]);
  422. Result:=Result or (1 shl i);
  423. end;
  424. end;
  425. end;
  426. Function GetTypeData(TypeInfo : PTypeInfo) : PTypeData;
  427. begin
  428. GetTypeData:=PTypeData(aligntoptr(PTypeData(pointer(TypeInfo)+2+PByte(pointer(TypeInfo)+1)^)));
  429. end;
  430. { ---------------------------------------------------------------------
  431. Basic Type information functions.
  432. ---------------------------------------------------------------------}
  433. Function GetPropInfo(TypeInfo : PTypeInfo;const PropName : string) : PPropInfo;
  434. var
  435. hp : PTypeData;
  436. i : longint;
  437. p : shortstring;
  438. pd : ^TPropData;
  439. begin
  440. P:=PropName; // avoid Ansi<->short conversion in a loop
  441. while Assigned(TypeInfo) do
  442. begin
  443. // skip the name
  444. hp:=GetTypeData(Typeinfo);
  445. // the class info rtti the property rtti follows immediatly
  446. pd:=aligntoptr(pointer(pointer(@hp^.UnitName)+Length(hp^.UnitName)+1));
  447. Result:=PPropInfo(@pd^.PropList);
  448. for i:=1 to pd^.PropCount do
  449. begin
  450. // found a property of that name ?
  451. if ShortCompareText(Result^.Name, P) = 0 then
  452. exit;
  453. // skip to next property
  454. Result:=PPropInfo(aligntoptr(pointer(@Result^.Name)+byte(Result^.Name[0])+1));
  455. end;
  456. // parent class
  457. Typeinfo:=hp^.ParentInfo;
  458. end;
  459. Result:=Nil;
  460. end;
  461. Function GetPropInfo(TypeInfo : PTypeInfo;const PropName : string; Akinds : TTypeKinds) : PPropInfo;
  462. begin
  463. Result:=GetPropInfo(TypeInfo,PropName);
  464. If (Akinds<>[]) then
  465. If (Result<>Nil) then
  466. If Not (Result^.PropType^.Kind in AKinds) then
  467. Result:=Nil;
  468. end;
  469. Function GetPropInfo(AClass: TClass; const PropName: string; AKinds: TTypeKinds) : PPropInfo;
  470. begin
  471. Result:=GetPropInfo(PTypeInfo(AClass.ClassInfo),PropName,AKinds);
  472. end;
  473. Function GetPropInfo(Instance: TObject; const PropName: string; AKinds: TTypeKinds) : PPropInfo;
  474. begin
  475. Result:=GetPropInfo(Instance.ClassType,PropName,AKinds);
  476. end;
  477. Function GetPropInfo(Instance: TObject; const PropName: string): PPropInfo;
  478. begin
  479. Result:=GetPropInfo(Instance,PropName,[]);
  480. end;
  481. Function GetPropInfo(AClass: TClass; const PropName: string): PPropInfo;
  482. begin
  483. Result:=GetPropInfo(AClass,PropName,[]);
  484. end;
  485. Function FindPropInfo(Instance: TObject; const PropName: string): PPropInfo;
  486. begin
  487. result:=GetPropInfo(Instance, PropName);
  488. if Result=nil then
  489. Raise EPropertyError.CreateFmt(SErrPropertyNotFound, [PropName]);
  490. end;
  491. Function FindPropInfo(AClass:TClass;const PropName: string): PPropInfo;
  492. begin
  493. result:=GetPropInfo(AClass,PropName);
  494. if result=nil then
  495. Raise EPropertyError.CreateFmt(SErrPropertyNotFound, [PropName]);
  496. end;
  497. Function IsStoredProp(Instance : TObject;PropInfo : PPropInfo) : Boolean;
  498. type
  499. TBooleanIndexFunc=function(Index:integer):boolean of object;
  500. TBooleanFunc=function:boolean of object;
  501. var
  502. AMethod : TMethod;
  503. begin
  504. case (PropInfo^.PropProcs shr 4) and 3 of
  505. ptfield:
  506. Result:=PBoolean(Pointer(Instance)+PtrUInt(PropInfo^.StoredProc))^;
  507. ptconst:
  508. Result:=LongBool(PropInfo^.StoredProc);
  509. ptstatic,
  510. ptvirtual:
  511. begin
  512. if (PropInfo^.PropProcs shr 4) and 3=ptstatic then
  513. AMethod.Code:=PropInfo^.StoredProc
  514. else
  515. AMethod.Code:=ppointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.StoredProc))^;
  516. AMethod.Data:=Instance;
  517. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  518. Result:=TBooleanIndexFunc(AMethod)(PropInfo^.Index)
  519. else
  520. Result:=TBooleanFunc(AMethod)();
  521. end;
  522. end;
  523. end;
  524. Procedure GetPropInfos(TypeInfo : PTypeInfo;PropList : PPropList);
  525. {
  526. Store Pointers to property information in the list pointed
  527. to by proplist. PRopList must contain enough space to hold ALL
  528. properties.
  529. }
  530. Var
  531. TD : PTypeData;
  532. TP : PPropInfo;
  533. Count : Longint;
  534. begin
  535. // Get this objects TOTAL published properties count
  536. TD:=GetTypeData(TypeInfo);
  537. // Clear list
  538. FillChar(PropList^,TD^.PropCount*sizeof(Pointer),0);
  539. repeat
  540. TD:=GetTypeData(TypeInfo);
  541. // published properties count for this object
  542. TP:=aligntoptr(PPropInfo(aligntoptr((Pointer(@TD^.UnitName)+Length(TD^.UnitName)+1))));
  543. Count:=PWord(TP)^;
  544. // Now point TP to first propinfo record.
  545. Inc(Pointer(TP),SizeOF(Word));
  546. tp:=aligntoptr(tp);
  547. While Count>0 do
  548. begin
  549. // Don't overwrite properties with the same name
  550. if PropList^[TP^.NameIndex]=nil then
  551. PropList^[TP^.NameIndex]:=TP;
  552. // Point to TP next propinfo record.
  553. // Located at Name[Length(Name)+1] !
  554. TP:=aligntoptr(PPropInfo(pointer(@TP^.Name)+PByte(@TP^.Name)^+1));
  555. Dec(Count);
  556. end;
  557. TypeInfo:=TD^.Parentinfo;
  558. until TypeInfo=nil;
  559. end;
  560. Procedure InsertProp (PL : PProplist;PI : PPropInfo; Count : longint);
  561. Var
  562. I : Longint;
  563. begin
  564. I:=0;
  565. While (I<Count) and (PI^.Name>PL^[I]^.Name) do
  566. Inc(I);
  567. If I<Count then
  568. Move(PL^[I], PL^[I+1], (Count - I) * SizeOf(Pointer));
  569. PL^[I]:=PI;
  570. end;
  571. Procedure InsertPropnosort (PL : PProplist;PI : PPropInfo; Count : longint);
  572. begin
  573. PL^[Count]:=PI;
  574. end;
  575. Type TInsertProp = Procedure (PL : PProplist;PI : PPropInfo; Count : longint);
  576. //Const InsertProps : array[false..boolean] of TInsertProp = (InsertPropNoSort,InsertProp);
  577. Function GetPropList(TypeInfo : PTypeInfo;TypeKinds : TTypeKinds; PropList : PPropList;Sorted : boolean = true):longint;
  578. {
  579. Store Pointers to property information OF A CERTAIN KIND in the list pointed
  580. to by proplist. PRopList must contain enough space to hold ALL
  581. properties.
  582. }
  583. Var
  584. TempList : PPropList;
  585. PropInfo : PPropinfo;
  586. I,Count : longint;
  587. DoInsertProp : TInsertProp;
  588. begin
  589. if sorted then
  590. DoInsertProp:=@InsertProp
  591. else
  592. DoInsertProp:=@InsertPropnosort;
  593. Result:=0;
  594. Count:=GetTypeData(TypeInfo)^.Propcount;
  595. If Count>0 then
  596. begin
  597. GetMem(TempList,Count*SizeOf(Pointer));
  598. Try
  599. GetPropInfos(TypeInfo,TempList);
  600. For I:=0 to Count-1 do
  601. begin
  602. PropInfo:=TempList^[i];
  603. If PropInfo^.PropType^.Kind in TypeKinds then
  604. begin
  605. If (PropList<>Nil) then
  606. DoInsertProp(PropList,PropInfo,Result);
  607. Inc(Result);
  608. end;
  609. end;
  610. finally
  611. FreeMem(TempList,Count*SizeOf(Pointer));
  612. end;
  613. end;
  614. end;
  615. Function GetPropList(TypeInfo: PTypeInfo; out PropList: PPropList): SizeInt;
  616. begin
  617. result:=GetTypeData(TypeInfo)^.Propcount;
  618. if result>0 then
  619. begin
  620. getmem(PropList,result*sizeof(pointer));
  621. GetPropInfos(TypeInfo,PropList);
  622. end;
  623. end;
  624. function GetPropList(AObject: TObject; out PropList: PPropList): Integer;
  625. begin
  626. Result := GetPropList(PTypeInfo(AObject.ClassInfo), PropList);
  627. end;
  628. { ---------------------------------------------------------------------
  629. Property access functions
  630. ---------------------------------------------------------------------}
  631. { ---------------------------------------------------------------------
  632. Ordinal properties
  633. ---------------------------------------------------------------------}
  634. Function GetOrdProp(Instance : TObject;PropInfo : PPropInfo) : Int64;
  635. type
  636. TGetInt64ProcIndex=function(index:longint):Int64 of object;
  637. TGetInt64Proc=function():Int64 of object;
  638. TGetIntegerProcIndex=function(index:longint):longint of object;
  639. TGetIntegerProc=function:longint of object;
  640. TGetWordProcIndex=function(index:longint):word of object;
  641. TGetWordProc=function:word of object;
  642. TGetByteProcIndex=function(index:longint):Byte of object;
  643. TGetByteProc=function:Byte of object;
  644. var
  645. TypeInfo: PTypeInfo;
  646. AMethod : TMethod;
  647. DataSize: Integer;
  648. OrdType: TOrdType;
  649. Signed: Boolean;
  650. begin
  651. Result:=0;
  652. TypeInfo := PropInfo^.PropType;
  653. Signed := false;
  654. DataSize := 4;
  655. case TypeInfo^.Kind of
  656. {$ifdef cpu64}
  657. tkInterface,
  658. tkInterfaceRaw,
  659. tkDynArray,
  660. tkClass:
  661. DataSize:=8;
  662. {$endif cpu64}
  663. tkChar, tkBool:
  664. DataSize:=1;
  665. tkWChar:
  666. DataSize:=2;
  667. tkSet,
  668. tkEnumeration,
  669. tkInteger:
  670. begin
  671. OrdType:=GetTypeData(TypeInfo)^.OrdType;
  672. case OrdType of
  673. otSByte,otUByte: DataSize := 1;
  674. otSWord,otUWord: DataSize := 2;
  675. end;
  676. Signed := OrdType in [otSByte,otSWord,otSLong];
  677. end;
  678. tkInt64 :
  679. begin
  680. DataSize:=8;
  681. Signed:=true;
  682. end;
  683. tkQword :
  684. begin
  685. DataSize:=8;
  686. Signed:=false;
  687. end;
  688. end;
  689. case (PropInfo^.PropProcs) and 3 of
  690. ptfield:
  691. if Signed then begin
  692. case DataSize of
  693. 1: Result:=PShortInt(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  694. 2: Result:=PSmallInt(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  695. 4: Result:=PLongint(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  696. 8: Result:=PInt64(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  697. end;
  698. end else begin
  699. case DataSize of
  700. 1: Result:=PByte(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  701. 2: Result:=PWord(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  702. 4: Result:=PLongint(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  703. 8: Result:=PInt64(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  704. end;
  705. end;
  706. ptstatic,
  707. ptvirtual :
  708. begin
  709. if (PropInfo^.PropProcs and 3)=ptStatic then
  710. AMethod.Code:=PropInfo^.GetProc
  711. else
  712. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.GetProc))^;
  713. AMethod.Data:=Instance;
  714. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then begin
  715. case DataSize of
  716. 1: Result:=TGetByteProcIndex(AMethod)(PropInfo^.Index);
  717. 2: Result:=TGetWordProcIndex(AMethod)(PropInfo^.Index);
  718. 4: Result:=TGetIntegerProcIndex(AMethod)(PropInfo^.Index);
  719. 8: result:=TGetInt64ProcIndex(AMethod)(PropInfo^.Index)
  720. end;
  721. end else begin
  722. case DataSize of
  723. 1: Result:=TGetByteProc(AMethod)();
  724. 2: Result:=TGetWordProc(AMethod)();
  725. 4: Result:=TGetIntegerProc(AMethod)();
  726. 8: result:=TGetInt64Proc(AMethod)();
  727. end;
  728. end;
  729. if Signed then begin
  730. case DataSize of
  731. 1: Result:=ShortInt(Result);
  732. 2: Result:=SmallInt(Result);
  733. end;
  734. end;
  735. end;
  736. end;
  737. end;
  738. Procedure SetOrdProp(Instance : TObject;PropInfo : PPropInfo;Value : Int64);
  739. type
  740. TSetInt64ProcIndex=procedure(index:longint;i:Int64) of object;
  741. TSetInt64Proc=procedure(i:Int64) of object;
  742. TSetIntegerProcIndex=procedure(index,i:longint) of object;
  743. TSetIntegerProc=procedure(i:longint) of object;
  744. var
  745. DataSize: Integer;
  746. AMethod : TMethod;
  747. begin
  748. if PropInfo^.PropType^.Kind in [tkInt64,tkQword
  749. { why do we have to handle classes here, see also below? (FK) }
  750. {$ifdef cpu64}
  751. ,tkInterface
  752. ,tkInterfaceRaw
  753. ,tkDynArray
  754. ,tkClass
  755. {$endif cpu64}
  756. ] then
  757. DataSize := 8
  758. else
  759. DataSize := 4;
  760. if not(PropInfo^.PropType^.Kind in [tkInt64,tkQword,tkClass]) then
  761. begin
  762. { cut off unnecessary stuff }
  763. case GetTypeData(PropInfo^.PropType)^.OrdType of
  764. otSWord,otUWord:
  765. begin
  766. Value:=Value and $ffff;
  767. DataSize := 2;
  768. end;
  769. otSByte,otUByte:
  770. begin
  771. Value:=Value and $ff;
  772. DataSize := 1;
  773. end;
  774. end;
  775. end;
  776. case (PropInfo^.PropProcs shr 2) and 3 of
  777. ptfield:
  778. case DataSize of
  779. 1: PByte(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Byte(Value);
  780. 2: PWord(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Word(Value);
  781. 4: PLongint(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Longint(Value);
  782. 8: PInt64(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Value;
  783. end;
  784. ptstatic,
  785. ptvirtual :
  786. begin
  787. if ((PropInfo^.PropProcs shr 2) and 3)=ptStatic then
  788. AMethod.Code:=PropInfo^.SetProc
  789. else
  790. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.SetProc))^;
  791. AMethod.Data:=Instance;
  792. if datasize=8 then
  793. begin
  794. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  795. TSetInt64ProcIndex(AMethod)(PropInfo^.Index,Value)
  796. else
  797. TSetInt64Proc(AMethod)(Value);
  798. end
  799. else
  800. begin
  801. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  802. TSetIntegerProcIndex(AMethod)(PropInfo^.Index,Value)
  803. else
  804. TSetIntegerProc(AMethod)(Value);
  805. end;
  806. end;
  807. end;
  808. end;
  809. Function GetOrdProp(Instance: TObject; const PropName: string): Int64;
  810. begin
  811. Result:=GetOrdProp(Instance,FindPropInfo(Instance,PropName));
  812. end;
  813. Procedure SetOrdProp(Instance: TObject; const PropName: string; Value: Int64);
  814. begin
  815. SetOrdProp(Instance,FindPropInfo(Instance,PropName),Value);
  816. end;
  817. Function GetEnumProp(Instance: TObject; Const PropInfo: PPropInfo): string;
  818. begin
  819. Result:=GetEnumName(PropInfo^.PropType, GetOrdProp(Instance, PropInfo));
  820. end;
  821. Function GetEnumProp(Instance: TObject; const PropName: string): string;
  822. begin
  823. Result:=GetEnumProp(Instance,FindPropInfo(Instance,PropName));
  824. end;
  825. Procedure SetEnumProp(Instance: TObject; const PropName: string; const Value: string);
  826. begin
  827. SetEnumProp(Instance,FindPropInfo(Instance,PropName),Value);
  828. end;
  829. Procedure SetEnumProp(Instance: TObject; Const PropInfo : PPropInfo; const Value: string);
  830. Var
  831. PV : Longint;
  832. begin
  833. If PropInfo<>Nil then
  834. begin
  835. PV:=GetEnumValue(PropInfo^.PropType, Value);
  836. if (PV<0) then
  837. raise EPropertyError.CreateFmt(SErrUnknownEnumValue, [Value]);
  838. SetOrdProp(Instance, PropInfo,PV);
  839. end;
  840. end;
  841. { ---------------------------------------------------------------------
  842. Int64 wrappers
  843. ---------------------------------------------------------------------}
  844. Function GetInt64Prop(Instance: TObject; PropInfo: PPropInfo): Int64;
  845. begin
  846. Result:=GetOrdProp(Instance,PropInfo);
  847. end;
  848. procedure SetInt64Prop(Instance: TObject; PropInfo: PPropInfo; const Value: Int64);
  849. begin
  850. SetOrdProp(Instance,PropInfo,Value);
  851. end;
  852. Function GetInt64Prop(Instance: TObject; const PropName: string): Int64;
  853. begin
  854. Result:=GetInt64Prop(Instance,FindPropInfo(Instance,PropName));
  855. end;
  856. Procedure SetInt64Prop(Instance: TObject; const PropName: string; const Value: Int64);
  857. begin
  858. SetInt64Prop(Instance,FindPropInfo(Instance,PropName),Value);
  859. end;
  860. { ---------------------------------------------------------------------
  861. Set properties
  862. ---------------------------------------------------------------------}
  863. Function GetSetProp(Instance: TObject; const PropName: string): string;
  864. begin
  865. Result:=GetSetProp(Instance,PropName,False);
  866. end;
  867. Function GetSetProp(Instance: TObject; const PropName: string; Brackets: Boolean): string;
  868. begin
  869. Result:=GetSetProp(Instance,FindPropInfo(Instance,PropName),Brackets);
  870. end;
  871. Function GetSetProp(Instance: TObject; const PropInfo: PPropInfo; Brackets: Boolean): string;
  872. begin
  873. Result:=SetToString(PropInfo,GetOrdProp(Instance,PropInfo),Brackets);
  874. end;
  875. Procedure SetSetProp(Instance: TObject; const PropName: string; const Value: string);
  876. begin
  877. SetSetProp(Instance,FindPropInfo(Instance,PropName),Value);
  878. end;
  879. Procedure SetSetProp(Instance: TObject; const PropInfo: PPropInfo; const Value: string);
  880. begin
  881. SetOrdProp(Instance,PropInfo,StringToSet(PropInfo,Value));
  882. end;
  883. { ---------------------------------------------------------------------
  884. Object properties
  885. ---------------------------------------------------------------------}
  886. Function GetObjectProp(Instance: TObject; const PropName: string): TObject;
  887. begin
  888. Result:=GetObjectProp(Instance,PropName,Nil);
  889. end;
  890. Function GetObjectProp(Instance: TObject; const PropName: string; MinClass: TClass): TObject;
  891. begin
  892. Result:=GetObjectProp(Instance,FindPropInfo(Instance,PropName),MinClass);
  893. end;
  894. Function GetObjectProp(Instance: TObject; PropInfo : PPropInfo): TObject;
  895. begin
  896. Result:=GetObjectProp(Instance,PropInfo,Nil);
  897. end;
  898. Function GetObjectProp(Instance: TObject; PropInfo : PPropInfo; MinClass: TClass): TObject;
  899. begin
  900. {$ifdef cpu64}
  901. Result:=TObject(GetInt64Prop(Instance,PropInfo));
  902. {$else cpu64}
  903. Result:=TObject(PtrInt(GetOrdProp(Instance,PropInfo)));
  904. {$endif cpu64}
  905. If (MinClass<>Nil) and (Result<>Nil) Then
  906. If Not Result.InheritsFrom(MinClass) then
  907. Result:=Nil;
  908. end;
  909. Procedure SetObjectProp(Instance: TObject; const PropName: string; Value: TObject);
  910. begin
  911. SetObjectProp(Instance,FindPropInfo(Instance,PropName),Value);
  912. end;
  913. Procedure SetObjectProp(Instance: TObject; PropInfo : PPropInfo; Value: TObject);
  914. begin
  915. {$ifdef cpu64}
  916. SetInt64Prop(Instance,PropInfo,Int64(Value));
  917. {$else cpu64}
  918. SetOrdProp(Instance,PropInfo,Integer(Value));
  919. {$endif cpu64}
  920. end;
  921. Function GetObjectPropClass(Instance: TObject; const PropName: string): TClass;
  922. begin
  923. Result:=GetTypeData(FindPropInfo(Instance,PropName)^.PropType)^.ClassType;
  924. end;
  925. { ---------------------------------------------------------------------
  926. Interface wrapprers
  927. ---------------------------------------------------------------------}
  928. function GetInterfaceProp(Instance: TObject; const PropName: string): IInterface;
  929. begin
  930. Result:=GetInterfaceProp(Instance,FindPropInfo(Instance,PropName));
  931. end;
  932. function GetInterfaceProp(Instance: TObject; PropInfo: PPropInfo): IInterface;
  933. begin
  934. {$ifdef cpu64}
  935. Result:=IInterface(GetInt64Prop(Instance,PropInfo));
  936. {$else cpu64}
  937. Result:=IInterface(PtrInt(GetOrdProp(Instance,PropInfo)));
  938. {$endif cpu64}
  939. end;
  940. procedure SetInterfaceProp(Instance: TObject; const PropName: string; const Value: IInterface);
  941. begin
  942. SetInterfaceProp(Instance,FindPropInfo(Instance,PropName),Value);
  943. end;
  944. procedure SetInterfaceProp(Instance: TObject; PropInfo: PPropInfo; const Value: IInterface);
  945. begin
  946. {$ifdef cpu64}
  947. SetInt64Prop(Instance,PropInfo,Int64(Value));
  948. {$else cpu64}
  949. SetOrdProp(Instance,PropInfo,Integer(Value));
  950. {$endif cpu64}
  951. end;
  952. { ---------------------------------------------------------------------
  953. String properties
  954. ---------------------------------------------------------------------}
  955. Function GetStrProp(Instance: TObject; PropInfo: PPropInfo): AnsiString;
  956. type
  957. TGetShortStrProcIndex=function(index:longint):ShortString of object;
  958. TGetShortStrProc=function():ShortString of object;
  959. TGetAnsiStrProcIndex=function(index:longint):AnsiString of object;
  960. TGetAnsiStrProc=function():AnsiString of object;
  961. var
  962. AMethod : TMethod;
  963. begin
  964. Result:='';
  965. case Propinfo^.PropType^.Kind of
  966. tkWString:
  967. Result:=GetWideStrProp(Instance,PropInfo);
  968. tkSString:
  969. begin
  970. case (PropInfo^.PropProcs) and 3 of
  971. ptField:
  972. Result := PShortString(Pointer(Instance) + LongWord(PropInfo^.GetProc))^;
  973. ptstatic,
  974. ptvirtual :
  975. begin
  976. if (PropInfo^.PropProcs and 3)=ptStatic then
  977. AMethod.Code:=PropInfo^.GetProc
  978. else
  979. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.GetProc))^;
  980. AMethod.Data:=Instance;
  981. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  982. Result:=TGetShortStrProcIndex(AMethod)(PropInfo^.Index)
  983. else
  984. Result:=TGetShortStrProc(AMethod)();
  985. end;
  986. end;
  987. end;
  988. tkAString:
  989. begin
  990. case (PropInfo^.PropProcs) and 3 of
  991. ptField:
  992. Result := PAnsiString(Pointer(Instance) + LongWord(PropInfo^.GetProc))^;
  993. ptstatic,
  994. ptvirtual :
  995. begin
  996. if (PropInfo^.PropProcs and 3)=ptStatic then
  997. AMethod.Code:=PropInfo^.GetProc
  998. else
  999. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.GetProc))^;
  1000. AMethod.Data:=Instance;
  1001. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  1002. Result:=TGetAnsiStrProcIndex(AMethod)(PropInfo^.Index)
  1003. else
  1004. Result:=TGetAnsiStrProc(AMethod)();
  1005. end;
  1006. end;
  1007. end;
  1008. end;
  1009. end;
  1010. Procedure SetStrProp(Instance : TObject;PropInfo : PPropInfo; const Value : AnsiString);
  1011. type
  1012. TSetShortStrProcIndex=procedure(index:longint;const s:ShortString) of object;
  1013. TSetShortStrProc=procedure(const s:ShortString) of object;
  1014. TSetAnsiStrProcIndex=procedure(index:longint;s:AnsiString) of object;
  1015. TSetAnsiStrProc=procedure(s:AnsiString) of object;
  1016. var
  1017. AMethod : TMethod;
  1018. begin
  1019. case Propinfo^.PropType^.Kind of
  1020. tkWString:
  1021. SetWideStrProp(Instance,PropInfo,Value);
  1022. tkSString:
  1023. begin
  1024. case (PropInfo^.PropProcs shr 2) and 3 of
  1025. ptField:
  1026. PShortString(Pointer(Instance) + LongWord(PropInfo^.SetProc))^:=Value;
  1027. ptstatic,
  1028. ptvirtual :
  1029. begin
  1030. if (PropInfo^.PropProcs and 3)=ptStatic then
  1031. AMethod.Code:=PropInfo^.SetProc
  1032. else
  1033. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.SetProc))^;
  1034. AMethod.Data:=Instance;
  1035. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  1036. TSetShortStrProcIndex(AMethod)(PropInfo^.Index,Value)
  1037. else
  1038. TSetShortStrProc(AMethod)(Value);
  1039. end;
  1040. end;
  1041. end;
  1042. tkAString:
  1043. begin
  1044. case (PropInfo^.PropProcs shr 2) and 3 of
  1045. ptField:
  1046. PAnsiString(Pointer(Instance) + LongWord(PropInfo^.SetProc))^:=Value;
  1047. ptstatic,
  1048. ptvirtual :
  1049. begin
  1050. if ((PropInfo^.PropProcs shr 2) and 3)=ptStatic then
  1051. AMethod.Code:=PropInfo^.SetProc
  1052. else
  1053. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.SetProc))^;
  1054. AMethod.Data:=Instance;
  1055. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  1056. TSetAnsiStrProcIndex(AMethod)(PropInfo^.Index,Value)
  1057. else
  1058. TSetAnsiStrProc(AMethod)(Value);
  1059. end;
  1060. end;
  1061. end;
  1062. end;
  1063. end;
  1064. Function GetStrProp(Instance: TObject; const PropName: string): string;
  1065. begin
  1066. Result:=GetStrProp(Instance,FindPropInfo(Instance,PropName));
  1067. end;
  1068. Procedure SetStrProp(Instance: TObject; const PropName: string; const Value: AnsiString);
  1069. begin
  1070. SetStrProp(Instance,FindPropInfo(Instance,PropName),Value);
  1071. end;
  1072. Function GetWideStrProp(Instance: TObject; const PropName: string): WideString;
  1073. begin
  1074. Result:=GetWideStrProp(Instance, FindPropInfo(Instance, PropName));
  1075. end;
  1076. procedure SetWideStrProp(Instance: TObject; const PropName: string; const Value: WideString);
  1077. begin
  1078. SetWideStrProp(Instance,FindPropInfo(Instance,PropName),Value);
  1079. end;
  1080. Function GetWideStrProp(Instance: TObject; PropInfo: PPropInfo): WideString;
  1081. type
  1082. TGetWideStrProcIndex=function(index:longint):WideString of object;
  1083. TGetWideStrProc=function():WideString of object;
  1084. var
  1085. AMethod : TMethod;
  1086. begin
  1087. Result:='';
  1088. case Propinfo^.PropType^.Kind of
  1089. tkSString,tkAString:
  1090. Result:=GetStrProp(Instance,PropInfo);
  1091. tkWString:
  1092. begin
  1093. case (PropInfo^.PropProcs) and 3 of
  1094. ptField:
  1095. Result := PWideString(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  1096. ptstatic,
  1097. ptvirtual :
  1098. begin
  1099. if (PropInfo^.PropProcs and 3)=ptStatic then
  1100. AMethod.Code:=PropInfo^.GetProc
  1101. else
  1102. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.GetProc))^;
  1103. AMethod.Data:=Instance;
  1104. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  1105. Result:=TGetWideStrProcIndex(AMethod)(PropInfo^.Index)
  1106. else
  1107. Result:=TGetWideStrProc(AMethod)();
  1108. end;
  1109. end;
  1110. end;
  1111. end;
  1112. end;
  1113. Procedure SetWideStrProp(Instance: TObject; PropInfo: PPropInfo; const Value: WideString);
  1114. type
  1115. TSetWideStrProcIndex=procedure(index:longint;s:WideString) of object;
  1116. TSetWideStrProc=procedure(s:WideString) of object;
  1117. var
  1118. AMethod : TMethod;
  1119. begin
  1120. case Propinfo^.PropType^.Kind of
  1121. tkSString,tkAString:
  1122. SetStrProp(Instance,PropInfo,Value);
  1123. tkWString:
  1124. begin
  1125. case (PropInfo^.PropProcs shr 2) and 3 of
  1126. ptField:
  1127. PWideString(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Value;
  1128. ptstatic,
  1129. ptvirtual :
  1130. begin
  1131. if ((PropInfo^.PropProcs shr 2) and 3)=ptStatic then
  1132. AMethod.Code:=PropInfo^.SetProc
  1133. else
  1134. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.SetProc))^;
  1135. AMethod.Data:=Instance;
  1136. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  1137. TSetWideStrProcIndex(AMethod)(PropInfo^.Index,Value)
  1138. else
  1139. TSetWideStrProc(AMethod)(Value);
  1140. end;
  1141. end;
  1142. end;
  1143. end;
  1144. end;
  1145. { ---------------------------------------------------------------------
  1146. Float properties
  1147. ---------------------------------------------------------------------}
  1148. function GetFloatProp(Instance : TObject;PropInfo : PPropInfo) : Extended;
  1149. type
  1150. TGetExtendedProc = function:Extended of object;
  1151. TGetExtendedProcIndex = function(Index: integer): Extended of object;
  1152. TGetDoubleProc = function:Double of object;
  1153. TGetDoubleProcIndex = function(Index: integer): Double of object;
  1154. TGetSingleProc = function:Single of object;
  1155. TGetSingleProcIndex = function(Index: integer):Single of object;
  1156. TGetCurrencyProc = function : Currency of object;
  1157. TGetCurrencyProcIndex = function(Index: integer) : Currency of object;
  1158. var
  1159. AMethod : TMethod;
  1160. begin
  1161. Result:=0.0;
  1162. case PropInfo^.PropProcs and 3 of
  1163. ptField:
  1164. Case GetTypeData(PropInfo^.PropType)^.FloatType of
  1165. ftSingle:
  1166. Result:=PSingle(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  1167. ftDouble:
  1168. Result:=PDouble(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  1169. ftExtended:
  1170. Result:=PExtended(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  1171. ftcomp:
  1172. Result:=PComp(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  1173. ftcurr:
  1174. Result:=PCurrency(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  1175. end;
  1176. ptStatic,
  1177. ptVirtual:
  1178. begin
  1179. if (PropInfo^.PropProcs and 3)=ptStatic then
  1180. AMethod.Code:=PropInfo^.GetProc
  1181. else
  1182. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.GetProc))^;
  1183. AMethod.Data:=Instance;
  1184. Case GetTypeData(PropInfo^.PropType)^.FloatType of
  1185. ftSingle:
  1186. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  1187. Result:=TGetSingleProc(AMethod)()
  1188. else
  1189. Result:=TGetSingleProcIndex(AMethod)(PropInfo^.Index);
  1190. ftDouble:
  1191. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  1192. Result:=TGetDoubleProc(AMethod)()
  1193. else
  1194. Result:=TGetDoubleProcIndex(AMethod)(PropInfo^.Index);
  1195. ftExtended:
  1196. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  1197. Result:=TGetExtendedProc(AMethod)()
  1198. else
  1199. Result:=TGetExtendedProcIndex(AMethod)(PropInfo^.Index);
  1200. ftCurr:
  1201. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  1202. Result:=TGetCurrencyProc(AMethod)()
  1203. else
  1204. Result:=TGetCurrencyProcIndex(AMethod)(PropInfo^.Index);
  1205. end;
  1206. end;
  1207. end;
  1208. end;
  1209. Procedure SetFloatProp(Instance : TObject;PropInfo : PPropInfo; Value : Extended);
  1210. type
  1211. TSetExtendedProc = procedure(const AValue: Extended) of object;
  1212. TSetExtendedProcIndex = procedure(Index: integer; AValue: Extended) of object;
  1213. TSetDoubleProc = procedure(const AValue: Double) of object;
  1214. TSetDoubleProcIndex = procedure(Index: integer; AValue: Double) of object;
  1215. TSetSingleProc = procedure(const AValue: Single) of object;
  1216. TSetSingleProcIndex = procedure(Index: integer; AValue: Single) of object;
  1217. TSetCurrencyProc = procedure(const AValue: Currency) of object;
  1218. TSetCurrencyProcIndex = procedure(Index: integer; AValue: Currency) of object;
  1219. Var
  1220. AMethod : TMethod;
  1221. begin
  1222. case (PropInfo^.PropProcs shr 2) and 3 of
  1223. ptfield:
  1224. Case GetTypeData(PropInfo^.PropType)^.FloatType of
  1225. ftSingle:
  1226. PSingle(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Value;
  1227. ftDouble:
  1228. PDouble(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Value;
  1229. ftExtended:
  1230. PExtended(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Value;
  1231. {$ifdef FPC_COMP_IS_INT64}
  1232. ftComp:
  1233. PComp(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=trunc(Value);
  1234. {$else FPC_COMP_IS_INT64}
  1235. ftComp:
  1236. PComp(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Comp(Value);
  1237. {$endif FPC_COMP_IS_INT64}
  1238. ftCurr:
  1239. PCurrency(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Value;
  1240. end;
  1241. ptStatic,
  1242. ptVirtual:
  1243. begin
  1244. if ((PropInfo^.PropProcs shr 2) and 3)=ptStatic then
  1245. AMethod.Code:=PropInfo^.SetProc
  1246. else
  1247. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.SetProc))^;
  1248. AMethod.Data:=Instance;
  1249. Case GetTypeData(PropInfo^.PropType)^.FloatType of
  1250. ftSingle:
  1251. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  1252. TSetSingleProc(AMethod)(Value)
  1253. else
  1254. TSetSingleProcIndex(AMethod)(PropInfo^.Index,Value);
  1255. ftDouble:
  1256. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  1257. TSetDoubleProc(AMethod)(Value)
  1258. else
  1259. TSetDoubleProcIndex(AMethod)(PropInfo^.Index,Value);
  1260. ftExtended:
  1261. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  1262. TSetExtendedProc(AMethod)(Value)
  1263. else
  1264. TSetExtendedProcIndex(AMethod)(PropInfo^.Index,Value);
  1265. ftCurr:
  1266. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  1267. TSetCurrencyProc(AMethod)(Value)
  1268. else
  1269. TSetCurrencyProcIndex(AMethod)(PropInfo^.Index,Value);
  1270. end;
  1271. end;
  1272. end;
  1273. end;
  1274. function GetFloatProp(Instance: TObject; const PropName: string): Extended;
  1275. begin
  1276. Result:=GetFloatProp(Instance,FindPropInfo(Instance,PropName))
  1277. end;
  1278. Procedure SetFloatProp(Instance: TObject; const PropName: string; Value: Extended);
  1279. begin
  1280. SetFloatProp(Instance,FindPropInfo(Instance,PropName),Value);
  1281. end;
  1282. { ---------------------------------------------------------------------
  1283. Method properties
  1284. ---------------------------------------------------------------------}
  1285. Function GetMethodProp(Instance : TObject;PropInfo : PPropInfo) : TMethod;
  1286. type
  1287. TGetMethodProcIndex=function(Index: Longint): TMethod of object;
  1288. TGetMethodProc=function(): TMethod of object;
  1289. var
  1290. value: PMethod;
  1291. AMethod : TMethod;
  1292. begin
  1293. Result.Code:=nil;
  1294. Result.Data:=nil;
  1295. case (PropInfo^.PropProcs) and 3 of
  1296. ptfield:
  1297. begin
  1298. Value:=PMethod(Pointer(Instance)+PtrUInt(PropInfo^.GetProc));
  1299. if Value<>nil then
  1300. Result:=Value^;
  1301. end;
  1302. ptstatic,
  1303. ptvirtual :
  1304. begin
  1305. if (PropInfo^.PropProcs and 3)=ptStatic then
  1306. AMethod.Code:=PropInfo^.GetProc
  1307. else
  1308. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.GetProc))^;
  1309. AMethod.Data:=Instance;
  1310. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  1311. Result:=TGetMethodProcIndex(AMethod)(PropInfo^.Index)
  1312. else
  1313. Result:=TGetMethodProc(AMethod)();
  1314. end;
  1315. end;
  1316. end;
  1317. Procedure SetMethodProp(Instance : TObject;PropInfo : PPropInfo; const Value : TMethod);
  1318. type
  1319. TSetMethodProcIndex=procedure(index:longint;p:TMethod) of object;
  1320. TSetMethodProc=procedure(p:TMethod) of object;
  1321. var
  1322. AMethod : TMethod;
  1323. begin
  1324. case (PropInfo^.PropProcs shr 2) and 3 of
  1325. ptfield:
  1326. PMethod(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^ := Value;
  1327. ptstatic,
  1328. ptvirtual :
  1329. begin
  1330. if ((PropInfo^.PropProcs shr 2) and 3)=ptStatic then
  1331. AMethod.Code:=PropInfo^.SetProc
  1332. else
  1333. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.SetProc))^;
  1334. AMethod.Data:=Instance;
  1335. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  1336. TSetMethodProcIndex(AMethod)(PropInfo^.Index,Value)
  1337. else
  1338. TSetMethodProc(AMethod)(Value);
  1339. end;
  1340. end;
  1341. end;
  1342. Function GetMethodProp(Instance: TObject; const PropName: string): TMethod;
  1343. begin
  1344. Result:=GetMethodProp(Instance,FindPropInfo(Instance,PropName));
  1345. end;
  1346. Procedure SetMethodProp(Instance: TObject; const PropName: string; const Value: TMethod);
  1347. begin
  1348. SetMethodProp(Instance,FindPropInfo(Instance,PropName),Value);
  1349. end;
  1350. { ---------------------------------------------------------------------
  1351. Variant properties
  1352. ---------------------------------------------------------------------}
  1353. Procedure CheckVariantEvent(P : Pointer);
  1354. begin
  1355. If (P=Nil) then
  1356. Raise Exception.Create(SErrNoVariantSupport);
  1357. end;
  1358. Function GetVariantProp(Instance : TObject;PropInfo : PPropInfo): Variant;
  1359. begin
  1360. CheckVariantEvent(Pointer(OnGetVariantProp));
  1361. Result:=OnGetVariantProp(Instance,PropInfo);
  1362. end;
  1363. Procedure SetVariantProp(Instance : TObject;PropInfo : PPropInfo; const Value: Variant);
  1364. begin
  1365. CheckVariantEvent(Pointer(OnSetVariantProp));
  1366. OnSetVariantProp(Instance,PropInfo,Value);
  1367. end;
  1368. Function GetVariantProp(Instance: TObject; const PropName: string): Variant;
  1369. begin
  1370. Result:=GetVariantProp(Instance,FindPropInfo(Instance,PropName));
  1371. end;
  1372. Procedure SetVariantProp(Instance: TObject; const PropName: string; const Value: Variant);
  1373. begin
  1374. SetVariantprop(instance,FindpropInfo(Instance,PropName),Value);
  1375. end;
  1376. { ---------------------------------------------------------------------
  1377. All properties through variant.
  1378. ---------------------------------------------------------------------}
  1379. Function GetPropValue(Instance: TObject; const PropName: string): Variant;
  1380. begin
  1381. Result:=GetPropValue(Instance,PropName,True);
  1382. end;
  1383. Function GetPropValue(Instance: TObject; const PropName: string; PreferStrings: Boolean): Variant;
  1384. begin
  1385. CheckVariantEvent(Pointer(OnGetPropValue));
  1386. Result:=OnGetPropValue(Instance,PropName,PreferStrings)
  1387. end;
  1388. Procedure SetPropValue(Instance: TObject; const PropName: string; const Value: Variant);
  1389. begin
  1390. CheckVariantEvent(Pointer(OnSetPropValue));
  1391. OnSetPropValue(Instance,PropName,Value);
  1392. end;
  1393. { ---------------------------------------------------------------------
  1394. Easy access methods that appeared in Delphi 5
  1395. ---------------------------------------------------------------------}
  1396. Function IsPublishedProp(Instance: TObject; const PropName: string): Boolean;
  1397. begin
  1398. Result:=GetPropInfo(Instance,PropName)<>Nil;
  1399. end;
  1400. Function IsPublishedProp(AClass: TClass; const PropName: string): Boolean;
  1401. begin
  1402. Result:=GetPropInfo(AClass,PropName)<>Nil;
  1403. end;
  1404. Function PropIsType(Instance: TObject; const PropName: string; TypeKind: TTypeKind): Boolean;
  1405. begin
  1406. Result:=FindPropInfo(Instance,PropName)^.PropType^.Kind=TypeKind
  1407. end;
  1408. Function PropIsType(AClass: TClass; const PropName: string; TypeKind: TTypeKind): Boolean;
  1409. begin
  1410. Result:=PropType(AClass,PropName)=TypeKind
  1411. end;
  1412. Function PropType(Instance: TObject; const PropName: string): TTypeKind;
  1413. begin
  1414. Result:=FindPropInfo(Instance,PropName)^.PropType^.Kind;
  1415. end;
  1416. Function PropType(AClass: TClass; const PropName: string): TTypeKind;
  1417. begin
  1418. Result:=FindPropInfo(AClass,PropName)^.PropType^.Kind;
  1419. end;
  1420. Function IsStoredProp(Instance: TObject; const PropName: string): Boolean;
  1421. begin
  1422. Result:=IsStoredProp(instance,FindPropInfo(Instance,PropName));
  1423. end;
  1424. end.