typinfo.pp 67 KB

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