typinfo.pp 65 KB

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