typinfo.pp 63 KB

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