typinfo.pp 48 KB

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