typinfo.pp 59 KB

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