typinfo.pp 49 KB

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