typinfo.pp 58 KB

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