typinfo.pp 58 KB

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