typinfo.pp 49 KB

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