typinfo.pp 64 KB

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