typinfo.pp 66 KB

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