typinfo.pp 62 KB

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