typinfo.pp 66 KB

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