typinfo.pp 58 KB

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