typinfo.pp 65 KB

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