typinfo.pp 66 KB

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