typinfo.pp 50 KB

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