typinfo.pp 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1999-2000 by Florian Klaempfl
  5. member of the Free Pascal development team
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. { This unit provides the same Functionality as the TypInfo Unit }
  13. { of Delphi }
  14. unit typinfo;
  15. interface
  16. {$MODE objfpc}
  17. uses SysUtils;
  18. // temporary types:
  19. type
  20. //{$ifndef HASVARIANT}
  21. Variant = Pointer;
  22. //{$endif}
  23. {$MINENUMSIZE 1 this saves a lot of memory }
  24. // if you change one of the following enumeration types
  25. // you have also to change the compiler in an appropriate way !
  26. TTypeKind = (tkUnknown,tkInteger,tkChar,tkEnumeration,
  27. tkFloat,tkSet,tkMethod,tkSString,tkLString,tkAString,
  28. tkWString,tkVariant,tkArray,tkRecord,tkInterface,
  29. tkClass,tkObject,tkWChar,tkBool,tkInt64,tkQWord,
  30. tkDynArray,tkInterfaceRaw);
  31. TTOrdType = (otSByte,otUByte,otSWord,otUWord,otSLong,otULong);
  32. TFloatType = (ftSingle,ftDouble,ftExtended,ftComp,ftCurr);
  33. TMethodKind = (mkProcedure,mkFunction,mkConstructor,mkDestructor,
  34. mkClassProcedure, mkClassFunction);
  35. TParamFlags = set of (pfVar,pfConst,pfArray,pfAddress,pfReference,pfOut);
  36. TIntfFlags = set of (ifHasGuid,ifDispInterface,ifDispatch);
  37. {$MINENUMSIZE DEFAULT}
  38. const
  39. ptField = 0;
  40. ptStatic = 1;
  41. ptVirtual = 2;
  42. ptConst = 3;
  43. tkString = tkSString;
  44. type
  45. TTypeKinds = set of TTypeKind;
  46. {$PACKRECORDS 1}
  47. TTypeInfo = record
  48. Kind : TTypeKind;
  49. Name : ShortString;
  50. // here the type data follows as TTypeData record
  51. end;
  52. PTypeInfo = ^TTypeInfo;
  53. PPTypeInfo = ^PTypeInfo;
  54. PTypeData = ^TTypeData;
  55. TTypeData = packed record
  56. case TTypeKind of
  57. tkUnKnown,tkLString,tkWString,tkAString,tkVariant:
  58. ();
  59. tkInteger,tkChar,tkEnumeration,tkWChar:
  60. (OrdType : TTOrdType;
  61. case TTypeKind of
  62. tkInteger,tkChar,tkEnumeration,tkBool,tkWChar : (
  63. MinValue,MaxValue : Longint;
  64. case TTypeKind of
  65. tkEnumeration:
  66. (
  67. BaseType : PTypeInfo;
  68. NameList : ShortString)
  69. );
  70. tkSet:
  71. (CompType : PTypeInfo)
  72. );
  73. tkFloat:
  74. (FloatType : TFloatType);
  75. tkSString:
  76. (MaxLength : Byte);
  77. tkClass:
  78. (ClassType : TClass;
  79. ParentInfo : PTypeInfo;
  80. PropCount : SmallInt;
  81. UnitName : ShortString
  82. // here the properties follow as array of TPropInfo
  83. );
  84. tkMethod:
  85. (MethodKind : TMethodKind;
  86. ParamCount : Byte;
  87. ParamList : array[0..1023] of Char
  88. {in reality ParamList is a array[1..ParamCount] of:
  89. record
  90. Flags : TParamFlags;
  91. ParamName : ShortString;
  92. TypeName : ShortString;
  93. end;
  94. followed by
  95. ResultType : ShortString}
  96. );
  97. tkInt64:
  98. (MinInt64Value, MaxInt64Value: Int64);
  99. tkQWord:
  100. (MinQWordValue, MaxQWordValue: QWord);
  101. tkInterface,
  102. tkInterfaceRaw:
  103. (
  104. IntfParent: PPTypeInfo;
  105. IID: PGUID;
  106. IIDStr: ShortString;
  107. IntfUnit: ShortString;
  108. );
  109. end;
  110. // unsed, just for completeness
  111. TPropData = packed record
  112. PropCount : Word;
  113. PropList : record end;
  114. end;
  115. PPropInfo = ^TPropInfo;
  116. TPropInfo = packed record
  117. PropType : PTypeInfo;
  118. GetProc : Pointer;
  119. SetProc : Pointer;
  120. StoredProc : Pointer;
  121. Index : Integer;
  122. Default : Longint;
  123. NameIndex : SmallInt;
  124. // contains the type of the Get/Set/Storedproc, see also ptxxx
  125. // bit 0..1 GetProc
  126. // 2..3 SetProc
  127. // 4..5 StoredProc
  128. // 6 : true, constant index property
  129. PropProcs : Byte;
  130. Name : ShortString;
  131. end;
  132. TProcInfoProc = Procedure(PropInfo : PPropInfo) of object;
  133. PPropList = ^TPropList;
  134. TPropList = array[0..65535] of PPropInfo;
  135. const
  136. tkAny = [Low(TTypeKind)..High(TTypeKind)];
  137. tkMethods = [tkMethod];
  138. tkProperties = tkAny-tkMethods-[tkUnknown];
  139. // general property handling
  140. Function GetTypeData(TypeInfo : PTypeInfo) : PTypeData;
  141. Function GetPropInfo(TypeInfo : PTypeInfo;const PropName : string) : PPropInfo;
  142. Function GetPropInfo(TypeInfo : PTypeInfo;const PropName : string; AKinds : TTypeKinds) : PPropInfo;
  143. Function GetPropInfo(Instance: TObject; const PropName: string; AKinds: TTypeKinds) : PPropInfo;
  144. Function GetPropInfo(Instance: TObject; const PropName: string): PPropInfo;
  145. Function GetPropInfo(AClass: TClass; const PropName: string; AKinds: TTypeKinds) : PPropInfo;
  146. Function GetPropInfo(AClass: TClass; const PropName: string): PPropInfo;
  147. Function FindPropInfo(Instance: TObject; const PropName: string): PPropInfo;
  148. Function FindPropInfo(AClass:TClass;const PropName: string): PPropInfo;
  149. Procedure GetPropInfos(TypeInfo : PTypeInfo;PropList : PPropList);
  150. Function GetPropList(TypeInfo : PTypeInfo;TypeKinds : TTypeKinds; PropList : PPropList) : Integer;
  151. // Property information routines.
  152. Function IsStoredProp(Instance: TObject;PropInfo : PPropInfo) : Boolean;
  153. Function IsStoredProp(Instance: TObject; const PropName: string): Boolean;
  154. Function IsPublishedProp(Instance: TObject; const PropName: string): Boolean;
  155. Function IsPublishedProp(AClass: TClass; const PropName: string): Boolean;
  156. Function PropType(Instance: TObject; const PropName: string): TTypeKind;
  157. Function PropType(AClass: TClass; const PropName: string): TTypeKind;
  158. Function PropIsType(Instance: TObject; const PropName: string; TypeKind: TTypeKind): Boolean;
  159. Function PropIsType(AClass: TClass; const PropName: string; TypeKind: TTypeKind): Boolean;
  160. // subroutines to read/write properties
  161. Function GetOrdProp(Instance: TObject; PropInfo : PPropInfo) : Longint;
  162. Function GetOrdProp(Instance: TObject; const PropName: string): Longint;
  163. Procedure SetOrdProp(Instance: TObject; PropInfo : PPropInfo; Value : Longint);
  164. Procedure SetOrdProp(Instance: TObject; const PropName: string; Value: Longint);
  165. Function GetEnumProp(Instance: TObject; const PropName: string): string;
  166. Function GetEnumProp(Instance: TObject; const PropInfo: PPropInfo): string;
  167. Procedure SetEnumProp(Instance: TObject; const PropName: string;const Value: string);
  168. Procedure SetEnumProp(Instance: TObject; const PropInfo: PPropInfo;const Value: string);
  169. Function GetSetProp(Instance: TObject; const PropName: string): string;
  170. Function GetSetProp(Instance: TObject; const PropName: string; Brackets: Boolean): string;
  171. Function GetSetProp(Instance: TObject; const PropInfo: PPropInfo; Brackets: Boolean): string;
  172. Procedure SetSetProp(Instance: TObject; const PropName: string; const Value: string);
  173. Procedure SetSetProp(Instance: TObject; const PropInfo: PPropInfo; const Value: string);
  174. Function GetStrProp(Instance: TObject; PropInfo : PPropInfo) : Ansistring;
  175. Function GetStrProp(Instance: TObject; const PropName: string): string;
  176. Procedure SetStrProp(Instance: TObject; const PropName: string; const Value: AnsiString);
  177. Procedure SetStrProp(Instance: TObject; PropInfo : PPropInfo; const Value : Ansistring);
  178. Function GetFloatProp(Instance: TObject; PropInfo : PPropInfo) : Extended;
  179. Function GetFloatProp(Instance: TObject; const PropName: string): Extended;
  180. Procedure SetFloatProp(Instance: TObject; const PropName: string; Value: Extended);
  181. Procedure SetFloatProp(Instance: TObject; PropInfo : PPropInfo; Value : Extended);
  182. Function GetVariantProp(Instance: TObject; PropInfo : PPropInfo): Variant;
  183. Function GetVariantProp(Instance: TObject; const PropName: string): Variant;
  184. Procedure SetVariantProp(Instance: TObject; const PropName: string; const Value: Variant);
  185. Procedure SetVariantProp(Instance: TObject; PropInfo : PPropInfo; const Value: Variant);
  186. Function GetObjectProp(Instance: TObject; const PropName: string): TObject;
  187. Function GetObjectProp(Instance: TObject; const PropName: string; MinClass: TClass): TObject;
  188. Function GetObjectProp(Instance: TObject; PropInfo: PPropInfo; MinClass: TClass): TObject;
  189. Procedure SetObjectProp(Instance: TObject; const PropName: string; Value: TObject);
  190. Procedure SetObjectProp(Instance: TObject; PropInfo: PPropInfo; Value: TObject);
  191. Function GetObjectPropClass(Instance: TObject; const PropName: string): TClass;
  192. Function GetMethodProp(Instance: TObject; PropInfo: PPropInfo) : TMethod;
  193. Function GetMethodProp(Instance: TObject; const PropName: string): TMethod;
  194. Procedure SetMethodProp(Instance: TObject; PropInfo: PPropInfo; const Value : TMethod);
  195. Procedure SetMethodProp(Instance: TObject; const PropName: string; const Value: TMethod);
  196. Function GetInt64Prop(Instance: TObject; PropInfo: PPropInfo): Int64;
  197. Function GetInt64Prop(Instance: TObject; const PropName: string): Int64;
  198. Procedure SetInt64Prop(Instance: TObject; PropInfo: PPropInfo; const Value: Int64);
  199. Procedure SetInt64Prop(Instance: TObject; const PropName: string; const Value: Int64);
  200. Function GetPropValue(Instance: TObject; const PropName: string): Variant;
  201. Function GetPropValue(Instance: TObject; const PropName: string; PreferStrings: Boolean): Variant;
  202. Procedure SetPropValue(Instance: TObject; const PropName: string; const Value: Variant);
  203. // Auxiliary routines, which may be useful
  204. Function GetEnumName(TypeInfo : PTypeInfo;Value : Integer) : string;
  205. Function GetEnumValue(TypeInfo : PTypeInfo;const Name : string) : Integer;
  206. function SetToString(PropInfo: PPropInfo; Value: Integer; Brackets: Boolean) : String;
  207. function SetToString(PropInfo: PPropInfo; Value: Integer) : String;
  208. function StringToSet(PropInfo: PPropInfo; const Value: string): Integer;
  209. const
  210. BooleanIdents: array[Boolean] of String = ('False', 'True');
  211. DotSep: String = '.';
  212. Type
  213. EPropertyError = Class(Exception);
  214. Implementation
  215. ResourceString
  216. SErrPropertyNotFound = 'Unknown property: "%s"';
  217. SErrUnknownEnumValue = 'Unknown enumeration value: "%s"';
  218. type
  219. PMethod = ^TMethod;
  220. { ---------------------------------------------------------------------
  221. Auxiliary methods
  222. ---------------------------------------------------------------------}
  223. Function GetEnumName(TypeInfo : PTypeInfo;Value : Integer) : string;
  224. Var PS : PShortString;
  225. PT : PTypeData;
  226. begin
  227. PT:=GetTypeData(TypeInfo);
  228. // ^.BaseType);
  229. // If PT^.MinValue<0 then Value:=Ord(Value<>0); {map to 0/1}
  230. PS:=@PT^.NameList;
  231. While Value>0 Do
  232. begin
  233. PS:=PShortString(pointer(PS)+PByte(PS)^+1);
  234. Dec(Value);
  235. end;
  236. Result:=PS^;
  237. end;
  238. Function GetEnumValue(TypeInfo : PTypeInfo;const Name : string) : Integer;
  239. Var PS : PShortString;
  240. PT : PTypeData;
  241. Count : longint;
  242. begin
  243. If Length(Name)=0 then exit(-1);
  244. PT:=GetTypeData(TypeInfo);
  245. Count:=0;
  246. Result:=-1;
  247. PS:=@PT^.NameList;
  248. While (Result=-1) and (PByte(PS)^<>0) do
  249. begin
  250. If CompareText(PS^, Name) = 0 then
  251. Result:=Count;
  252. PS:=PShortString(pointer(PS)+PByte(PS)^+1);
  253. Inc(Count);
  254. end;
  255. end;
  256. Function SetToString(PropInfo: PPropInfo; Value: Integer; Brackets: Boolean) : String;
  257. Var
  258. I : Integer;
  259. PTI : PTypeInfo;
  260. begin
  261. PTI:=GetTypeData(PropInfo^.PropType)^.CompType;
  262. Result:='';
  263. For I:=0 to SizeOf(Integer)*8-1 do
  264. begin
  265. if ((Value and 1)<>0) then
  266. begin
  267. If Result='' then
  268. Result:=GetEnumName(PTI,i)
  269. else
  270. Result:=Result+','+GetEnumName(PTI,I);
  271. end;
  272. Value:=Value shr 1;
  273. end;
  274. if Brackets then
  275. Result:='['+Result+']';
  276. end;
  277. Function SetToString(PropInfo: PPropInfo; Value: Integer) : String;
  278. begin
  279. Result:=SetToString(PropInfo,Value,False);
  280. end;
  281. Const
  282. SetDelim = ['[',']',',',' '];
  283. Function GetNextElement(Var S : String) : String;
  284. Var
  285. J : Integer;
  286. begin
  287. J:=1;
  288. Result:='';
  289. If Length(S)>0 then
  290. begin
  291. While (J<=Length(S)) and Not (S[j] in SetDelim) do
  292. Inc(j);
  293. Result:=Copy(S,1,j-1);
  294. Delete(S,1,j);
  295. end;
  296. end;
  297. Function StringToSet(PropInfo: PPropInfo; const Value: string): Integer;
  298. Var
  299. S,T : String;
  300. I : Integer;
  301. PTI : PTypeInfo;
  302. begin
  303. Result:=0;
  304. PTI:=GetTypeData(PropInfo^.PropType)^.Comptype;
  305. S:=Value;
  306. I:=1;
  307. If Length(S)>0 then
  308. begin
  309. While (I<=Length(S)) and (S[i] in SetDelim) do
  310. Inc(I);
  311. Delete(S,1,i-1);
  312. end;
  313. While (S<>'') do
  314. begin
  315. T:=GetNextElement(S);
  316. if T<>'' then
  317. begin
  318. I:=GetEnumValue(PTI,T);
  319. if (I<0) then
  320. raise EPropertyError.CreateFmt(SErrUnknownEnumValue, [T]);
  321. Result:=Result or (1 shl i);
  322. end;
  323. end;
  324. end;
  325. Function GetTypeData(TypeInfo : PTypeInfo) : PTypeData;
  326. begin
  327. GetTypeData:=PTypeData(pointer(TypeInfo)+2+PByte(pointer(TypeInfo)+1)^);
  328. end;
  329. { ---------------------------------------------------------------------
  330. Low-level calling of methods.
  331. ---------------------------------------------------------------------}
  332. {$I typinfo.inc}
  333. { ---------------------------------------------------------------------
  334. Basic Type information functions.
  335. ---------------------------------------------------------------------}
  336. Function GetPropInfo(TypeInfo : PTypeInfo;const PropName : string) : PPropInfo;
  337. var
  338. hp : PTypeData;
  339. i : longint;
  340. p : string;
  341. pd : ^TPropData;
  342. begin
  343. P:=UpCase(PropName);
  344. while Assigned(TypeInfo) do
  345. begin
  346. // skip the name
  347. hp:=GetTypeData(Typeinfo);
  348. // the class info rtti the property rtti follows immediatly
  349. pd:=pointer(pointer(@hp^.UnitName)+Length(hp^.UnitName)+1);
  350. Result:=@pd^.PropList;
  351. for i:=1 to pd^.PropCount do
  352. begin
  353. // found a property of that name ?
  354. if Upcase(Result^.Name)=P then
  355. exit;
  356. // skip to next property
  357. Result:=PPropInfo(pointer(@Result^.Name)+byte(Result^.Name[0])+1);
  358. end;
  359. // parent class
  360. Typeinfo:=hp^.ParentInfo;
  361. end;
  362. Result:=Nil;
  363. end;
  364. Function GetPropInfo(TypeInfo : PTypeInfo;const PropName : string; Akinds : TTypeKinds) : PPropInfo;
  365. begin
  366. Result:=GetPropInfo(TypeInfo,PropName);
  367. If (Akinds<>[]) then
  368. If (Result<>Nil) then
  369. If Not (Result^.PropType^.Kind in AKinds) then
  370. Result:=Nil;
  371. end;
  372. Function GetPropInfo(AClass: TClass; const PropName: string; AKinds: TTypeKinds) : PPropInfo;
  373. begin
  374. Result:=GetPropInfo(PTypeInfo(AClass.ClassInfo),PropName,AKinds);
  375. end;
  376. Function GetPropInfo(Instance: TObject; const PropName: string; AKinds: TTypeKinds) : PPropInfo;
  377. begin
  378. Result:=GetPropInfo(Instance.ClassType,PropName,AKinds);
  379. end;
  380. Function GetPropInfo(Instance: TObject; const PropName: string): PPropInfo;
  381. begin
  382. Result:=GetPropInfo(Instance,PropName,[]);
  383. end;
  384. Function GetPropInfo(AClass: TClass; const PropName: string): PPropInfo;
  385. begin
  386. Result:=GetPropInfo(AClass,PropName,[]);
  387. end;
  388. Function FindPropInfo(Instance: TObject; const PropName: string): PPropInfo;
  389. begin
  390. result:=GetPropInfo(Instance, PropName);
  391. if Result=nil then
  392. Raise EPropertyError.CreateFmt(SErrPropertyNotFound, [PropName]);
  393. end;
  394. Function FindPropInfo(AClass:TClass;const PropName: string): PPropInfo;
  395. begin
  396. result:=GetPropInfo(AClass,PropName);
  397. if result=nil then
  398. Raise EPropertyError.CreateFmt(SErrPropertyNotFound, [PropName]);
  399. end;
  400. Function IsStoredProp(Instance : TObject;PropInfo : PPropInfo) : Boolean;
  401. begin
  402. case (PropInfo^.PropProcs shr 4) and 3 of
  403. ptfield:
  404. IsStoredProp:=PBoolean(Pointer(Instance)+Longint(PropInfo^.StoredProc))^;
  405. ptstatic:
  406. IsStoredProp:=CallBooleanFunc(Instance,PropInfo^.StoredProc,0,0);
  407. ptvirtual:
  408. IsStoredProp:=CallBooleanFunc(Instance,ppointer(Pointer(Instance.ClassType)+Longint(PropInfo^.StoredProc))^,0,0);
  409. ptconst:
  410. IsStoredProp:=LongBool(PropInfo^.StoredProc);
  411. end;
  412. end;
  413. Procedure GetPropInfos(TypeInfo : PTypeInfo;PropList : PPropList);
  414. {
  415. Store Pointers to property information in the list pointed
  416. to by proplist. PRopList must contain enough space to hold ALL
  417. properties.
  418. }
  419. Type PWord = ^Word;
  420. Var TD : PTypeData;
  421. TP : PPropInfo;
  422. Count : Longint;
  423. begin
  424. TD:=GetTypeData(TypeInfo);
  425. // Get this objects TOTAL published properties count
  426. TP:=(@TD^.UnitName+Length(TD^.UnitName)+1);
  427. Count:=PWord(TP)^;
  428. // Now point TP to first propinfo record.
  429. Inc(Longint(TP),SizeOF(Word));
  430. While Count>0 do
  431. begin
  432. PropList^[0]:=TP;
  433. Inc(Longint(PropList),SizeOf(Pointer));
  434. // Point to TP next propinfo record.
  435. // Located at Name[Length(Name)+1] !
  436. TP:=PPropInfo(pointer(@TP^.Name)+PByte(@TP^.Name)^+1);
  437. Dec(Count);
  438. end;
  439. // recursive call for parent info.
  440. If TD^.Parentinfo<>Nil then
  441. GetPropInfos (TD^.ParentInfo,PropList);
  442. end;
  443. Procedure InsertProp (PL : PProplist;PI : PPropInfo; Count : longint);
  444. Var I : Longint;
  445. begin
  446. I:=0;
  447. While (I<Count) and (PI^.Name>PL^[I]^.Name) do Inc(I);
  448. If I<Count then
  449. Move(PL^[I], PL^[I+1], (Count - I) * SizeOf(Pointer));
  450. PL^[I]:=PI;
  451. end;
  452. Function GetPropList(TypeInfo : PTypeInfo;TypeKinds : TTypeKinds;
  453. PropList : PPropList) : Integer;
  454. {
  455. Store Pointers to property information OF A CERTAIN KIND in the list pointed
  456. to by proplist. PRopList must contain enough space to hold ALL
  457. properties.
  458. }
  459. Var TempList : PPropList;
  460. PropInfo : PPropinfo;
  461. I,Count : longint;
  462. begin
  463. Result:=0;
  464. Count:=GetTypeData(TypeInfo)^.Propcount;
  465. If Count>0 then
  466. begin
  467. GetMem(TempList,Count*SizeOf(Pointer));
  468. Try
  469. GetPropInfos(TypeInfo,TempList);
  470. For I:=0 to Count-1 do
  471. begin
  472. PropInfo:=TempList^[i];
  473. If PropInfo^.PropType^.Kind in TypeKinds then
  474. begin
  475. InsertProp(PropList,PropInfo,Result);
  476. Inc(Result);
  477. end;
  478. end;
  479. finally
  480. FreeMem(TempList,Count*SizeOf(Pointer));
  481. end;
  482. end;
  483. end;
  484. Procedure SetIndexValues (P: PPRopInfo; Var Index,IValue : Longint);
  485. begin
  486. Index:=((P^.PropProcs shr 6) and 1);
  487. If Index<>0 then
  488. IValue:=P^.Index
  489. else
  490. IValue:=0;
  491. end;
  492. { ---------------------------------------------------------------------
  493. Property access functions
  494. ---------------------------------------------------------------------}
  495. { ---------------------------------------------------------------------
  496. Ordinal properties
  497. ---------------------------------------------------------------------}
  498. Function GetOrdProp(Instance : TObject;PropInfo : PPropInfo) : Longint;
  499. var
  500. value,Index,Ivalue : longint;
  501. TypeInfo: PTypeInfo;
  502. begin
  503. SetIndexValues(PropInfo,Index,Ivalue);
  504. case (PropInfo^.PropProcs) and 3 of
  505. ptfield:
  506. Value:=PLongint(Pointer(Instance)+Longint(PropInfo^.GetProc))^;
  507. ptstatic:
  508. Value:=CallIntegerFunc(Instance,PropInfo^.GetProc,Index,IValue);
  509. ptvirtual:
  510. Value:=CallIntegerFunc(Instance,PPointer(Pointer(Instance.ClassType)+Longint(PropInfo^.GetProc))^,Index,IValue);
  511. end;
  512. { cut off unnecessary stuff }
  513. TypeInfo := PropInfo^.PropType;
  514. case TypeInfo^.Kind of
  515. tkChar, tkBool:
  516. Value:=Value and $ff;
  517. tkWChar:
  518. Value:=Value and $ffff;
  519. tkInteger:
  520. case GetTypeData(TypeInfo)^.OrdType of
  521. otSWord,otUWord:
  522. Value:=Value and $ffff;
  523. otSByte,otUByte:
  524. Value:=Value and $ff;
  525. end;
  526. end;
  527. GetOrdProp:=Value;
  528. end;
  529. Procedure SetOrdProp(Instance : TObject;PropInfo : PPropInfo;
  530. Value : Longint);
  531. var
  532. Index,IValue : Longint;
  533. DataSize: Integer;
  534. begin
  535. if PropInfo^.PropType^.Kind <> tkClass then
  536. { cut off unnecessary stuff }
  537. case GetTypeData(PropInfo^.PropType)^.OrdType of
  538. otSWord,otUWord:
  539. begin
  540. Value:=Value and $ffff;
  541. DataSize := 2;
  542. end;
  543. otSByte,otUByte:
  544. begin
  545. Value:=Value and $ff;
  546. DataSize := 1;
  547. end;
  548. else
  549. DataSize := 4;
  550. end
  551. else
  552. DataSize := 4;
  553. SetIndexValues(PropInfo,Index,Ivalue);
  554. case (PropInfo^.PropProcs shr 2) and 3 of
  555. ptfield:
  556. case DataSize of
  557. 1: PByte(Pointer(Instance)+Longint(PropInfo^.SetProc))^:=Byte(Value);
  558. 2: PWord(Pointer(Instance)+Longint(PropInfo^.SetProc))^:=Word(Value);
  559. 4: PLongint(Pointer(Instance)+Longint(PropInfo^.SetProc))^:=Value;
  560. end;
  561. ptstatic:
  562. CallIntegerProc(Instance,PropInfo^.SetProc,Value,Index,IValue);
  563. ptvirtual:
  564. CallIntegerProc(Instance,PPointer(Pointer(Instance.ClassType)+Longint(PropInfo^.SetProc))^,Value,Index,IValue);
  565. end;
  566. end;
  567. Function GetOrdProp(Instance: TObject; const PropName: string): Longint;
  568. begin
  569. Result:=GetOrdProp(Instance,FindPropInfo(Instance,PropName));
  570. end;
  571. Procedure SetOrdProp(Instance: TObject; const PropName: string; Value: Longint);
  572. begin
  573. SetOrdProp(Instance,FindPropInfo(Instance,PropName),Value);
  574. end;
  575. Function GetEnumProp(Instance: TObject; Const PropInfo: PPropInfo): string;
  576. begin
  577. Result:=GetEnumName(PropInfo^.PropType, GetOrdProp(Instance, PropInfo));
  578. end;
  579. Function GetEnumProp(Instance: TObject; const PropName: string): string;
  580. begin
  581. Result:=GetEnumProp(Instance,FindPropInfo(Instance,PropName));
  582. end;
  583. Procedure SetEnumProp(Instance: TObject; const PropName: string; const Value: string);
  584. begin
  585. SetEnumProp(Instance,FindPropInfo(Instance,PropName),Value);
  586. end;
  587. Procedure SetEnumProp(Instance: TObject; Const PropInfo : PPropInfo; const Value: string);
  588. Var
  589. PV : Longint;
  590. begin
  591. If PropInfo<>Nil then
  592. begin
  593. PV:=GetEnumValue(PropInfo^.PropType, Value);
  594. if (PV<0) then
  595. raise EPropertyError.CreateFmt(SErrUnknownEnumValue, [Value]);
  596. SetOrdProp(Instance, PropInfo,PV);
  597. end;
  598. end;
  599. { ---------------------------------------------------------------------
  600. Set properties
  601. ---------------------------------------------------------------------}
  602. Function GetSetProp(Instance: TObject; const PropName: string): string;
  603. begin
  604. Result:=GetSetProp(Instance,PropName,False);
  605. end;
  606. Function GetSetProp(Instance: TObject; const PropName: string; Brackets: Boolean): string;
  607. begin
  608. Result:=GetSetProp(Instance,FindPropInfo(Instance,PropName),Brackets);
  609. end;
  610. Function GetSetProp(Instance: TObject; const PropInfo: PPropInfo; Brackets: Boolean): string;
  611. begin
  612. Result:=SetToString(PropInfo,GetOrdProp(Instance,PropInfo),Brackets);
  613. end;
  614. Procedure SetSetProp(Instance: TObject; const PropName: string; const Value: string);
  615. begin
  616. SetSetProp(Instance,FindPropInfo(Instance,PropName),Value);
  617. end;
  618. Procedure SetSetProp(Instance: TObject; const PropInfo: PPropInfo; const Value: string);
  619. begin
  620. SetOrdProp(Instance,PropInfo,StringToSet(PropInfo,Value));
  621. end;
  622. { ---------------------------------------------------------------------
  623. Object properties
  624. ---------------------------------------------------------------------}
  625. Function GetObjectProp(Instance: TObject; const PropName: string): TObject;
  626. begin
  627. Result:=GetObjectProp(Instance,PropName,Nil);
  628. end;
  629. Function GetObjectProp(Instance: TObject; const PropName: string; MinClass: TClass): TObject;
  630. begin
  631. Result:=GetObjectProp(Instance,FindPropInfo(Instance,PropName),MinClass);
  632. end;
  633. Function GetObjectProp(Instance: TObject; PropInfo : PPropInfo; MinClass: TClass): TObject;
  634. begin
  635. Result:=TObject(GetOrdProp(Instance,PropInfo));
  636. If (MinClass<>Nil) and (Result<>Nil) Then
  637. If Not Result.InheritsFrom(MinClass) then
  638. Result:=Nil;
  639. end;
  640. Procedure SetObjectProp(Instance: TObject; const PropName: string; Value: TObject);
  641. begin
  642. SetObjectProp(Instance,FindPropInfo(Instance,PropName),Value);
  643. end;
  644. Procedure SetObjectProp(Instance: TObject; PropInfo : PPropInfo; Value: TObject);
  645. begin
  646. SetOrdProp(Instance,PropInfo,Integer(Value));
  647. end;
  648. Function GetObjectPropClass(Instance: TObject; const PropName: string): TClass;
  649. begin
  650. Result:=GetTypeData(FindPropInfo(Instance,PropName)^.PropType)^.ClassType;
  651. end;
  652. { ---------------------------------------------------------------------
  653. String properties
  654. ---------------------------------------------------------------------}
  655. Function GetStrProp(Instance: TObject; PropInfo: PPropInfo): AnsiString;
  656. var
  657. Index, IValue: LongInt;
  658. ShortResult: ShortString;
  659. begin
  660. SetIndexValues(PropInfo, Index, IValue);
  661. case Propinfo^.PropType^.Kind of
  662. tkSString:
  663. case (PropInfo^.PropProcs) and 3 of
  664. ptField:
  665. Result := PShortString(Pointer(Instance) + LongWord(PropInfo^.GetProc))^;
  666. ptStatic:
  667. begin
  668. CallSStringFunc(Instance, PropInfo^.GetProc, Index, IValue, ShortResult);
  669. Result := ShortResult;
  670. end;
  671. ptVirtual:
  672. begin
  673. CallSStringFunc(Instance, PPointer(Pointer(Instance.ClassType) +
  674. LongWord(PropInfo^.GetProc))^, Index, IValue, ShortResult);
  675. Result := ShortResult;
  676. end;
  677. end;
  678. tkAString:
  679. case (PropInfo^.PropProcs) and 3 of
  680. ptField:
  681. Result := PAnsiString(Pointer(Instance) + LongWord(PropInfo^.GetProc))^;
  682. ptStatic:
  683. Pointer(Result) := Pointer(LongWord(CallIntegerFunc(Instance, PropInfo^.GetProc, Index, IValue)));
  684. ptVirtual:
  685. Pointer(Result) := Pointer(LongWord(CallIntegerFunc(Instance,
  686. PPointer(Pointer(Instance.ClassType) + LongWord(PropInfo^.GetProc))^, Index, IValue)));
  687. end;
  688. else
  689. // Property is neither of type AnsiString nor of type ShortString
  690. SetLength(Result, 0);
  691. end;
  692. end;
  693. Procedure SetAStrProp(Instance : TObject;PropInfo : PPropInfo;
  694. const Value : AnsiString);
  695. {
  696. Dirty trick based on fact that AnsiString is just a pointer,
  697. hence can be treated like an integer type.
  698. }
  699. var
  700. Index,Ivalue : Longint;
  701. begin
  702. SetIndexValues(PropInfo,Index,IValue);
  703. case (PropInfo^.PropProcs shr 2) and 3 of
  704. ptfield:
  705. PAnsiString(Pointer(Instance) + Longint(PropInfo^.SetProc))^ := Value;
  706. ptstatic:
  707. CallIntegerProc(Instance,PropInfo^.SetProc,Longint(Pointer(Value)),Index,IValue);
  708. ptvirtual:
  709. CallIntegerProc(Instance,PPointer(Pointer(Instance.ClassType)+Longint(PropInfo^.SetProc))^,Longint(Pointer(Value)),Index,IValue);
  710. end;
  711. end;
  712. Procedure SetSStrProp(Instance : TObject;PropInfo : PPropInfo;
  713. const Value : ShortString);
  714. Var Index,IValue: longint;
  715. begin
  716. SetIndexValues(PRopInfo,Index,IValue);
  717. case (PropInfo^.PropProcs shr 2) and 3 of
  718. ptfield:
  719. PShortString(Pointer(Instance)+Longint(PropInfo^.SetProc))^:=Value;
  720. ptstatic:
  721. CallSStringProc(Instance,PropInfo^.SetProc,Value,Index,IValue);
  722. ptvirtual:
  723. CallSStringProc(Instance,PPointer(Pointer(Instance.ClassType)+Longint(PropInfo^.SetProc))^,Value,Index,IValue);
  724. end;
  725. end;
  726. Procedure SetStrProp(Instance : TObject;PropInfo : PPropInfo;
  727. const Value : AnsiString);
  728. begin
  729. Case Propinfo^.PropType^.Kind of
  730. tkSString : SetSStrProp(Instance,PropInfo,Value);
  731. tkAString : SetAStrProp(Instance,Propinfo,Value);
  732. end;
  733. end;
  734. Function GetStrProp(Instance: TObject; const PropName: string): string;
  735. begin
  736. Result:=GetStrProp(Instance,FindPropInfo(Instance,PropName));
  737. end;
  738. Procedure SetStrProp(Instance: TObject; const PropName: string; const Value: AnsiString);
  739. begin
  740. SetStrProp(Instance,FindPropInfo(Instance,PropName),Value);
  741. end;
  742. { ---------------------------------------------------------------------
  743. Float properties
  744. ---------------------------------------------------------------------}
  745. Function GetFloatProp(Instance : TObject;PropInfo : PPropInfo) : Extended;
  746. var
  747. Index,Ivalue : longint;
  748. Value : Extended;
  749. begin
  750. SetIndexValues(PropInfo,Index,Ivalue);
  751. case (PropInfo^.PropProcs) and 3 of
  752. ptfield:
  753. Case GetTypeData(PropInfo^.PropType)^.FloatType of
  754. ftSingle:
  755. Value:=PSingle(Pointer(Instance)+Longint(PropInfo^.GetProc))^;
  756. ftDouble:
  757. Value:=PDouble(Pointer(Instance)+Longint(PropInfo^.GetProc))^;
  758. ftExtended:
  759. Value:=PExtended(Pointer(Instance)+Longint(PropInfo^.GetProc))^;
  760. {$ifndef m68k}
  761. ftcomp:
  762. Value:=PComp(Pointer(Instance)+Longint(PropInfo^.GetProc))^;
  763. {$endif m68k}
  764. end;
  765. ptstatic:
  766. Value:=CallExtendedFunc(Instance,PropInfo^.GetProc,Index,IValue);
  767. ptvirtual:
  768. Value:=CallExtendedFunc(Instance,PPointer(Pointer(Instance.ClassType)+Longint(PropInfo^.GetProc))^,Index,IValue);
  769. end;
  770. Result:=Value;
  771. end;
  772. Procedure SetFloatProp(Instance : TObject;PropInfo : PPropInfo;
  773. Value : Extended);
  774. Var IValue,Index : longint;
  775. begin
  776. SetIndexValues(PropInfo,Index,Ivalue);
  777. case (PropInfo^.PropProcs shr 2) and 3 of
  778. ptfield:
  779. Case GetTypeData(PropInfo^.PropType)^.FloatType of
  780. ftSingle:
  781. PSingle(Pointer(Instance)+Longint(PropInfo^.SetProc))^:=Value;
  782. ftDouble:
  783. PDouble(Pointer(Instance)+Longint(PropInfo^.SetProc))^:=Value;
  784. ftExtended:
  785. PExtended(Pointer(Instance)+Longint(PropInfo^.SetProc))^:=Value;
  786. {$ifndef m68k}
  787. ftcomp:
  788. PComp(Pointer(Instance)+Longint(PropInfo^.SetProc))^:=Comp(Value);
  789. {$endif m68k}
  790. end;
  791. ptstatic:
  792. CallExtendedProc(Instance,PropInfo^.SetProc,Value,Index,IValue);
  793. ptvirtual:
  794. CallExtendedProc(Instance,PPointer(Pointer(Instance.ClassType)+Longint(PropInfo^.SetProc))^,Value,Index,IValue);
  795. end;
  796. end;
  797. Function GetFloatProp(Instance: TObject; const PropName: string): Extended;
  798. begin
  799. Result:=GetFloatProp(Instance,FindPropInfo(Instance,PropName))
  800. end;
  801. Procedure SetFloatProp(Instance: TObject; const PropName: string; Value: Extended);
  802. begin
  803. SetFloatProp(Instance,FindPropInfo(Instance,PropName),Value);
  804. end;
  805. { ---------------------------------------------------------------------
  806. Variant properties
  807. ---------------------------------------------------------------------}
  808. Function GetVariantProp(Instance : TObject;PropInfo : PPropInfo): Variant;
  809. begin
  810. {!!!!!!!!!!!}
  811. Result:=nil;
  812. end;
  813. Procedure SetVariantProp(Instance : TObject;PropInfo : PPropInfo;
  814. const Value: Variant);
  815. begin
  816. {!!!!!!!!!!!}
  817. end;
  818. Function GetVariantProp(Instance: TObject; const PropName: string): Variant;
  819. begin
  820. Result:=GetVariantProp(Instance,FindPropInfo(Instance,PropName));
  821. end;
  822. Procedure SetVariantProp(Instance: TObject; const PropName: string; const Value: Variant);
  823. begin
  824. SetVariantprop(instance,FindpropInfo(Instance,PropName),Value);
  825. end;
  826. { ---------------------------------------------------------------------
  827. Method properties
  828. ---------------------------------------------------------------------}
  829. Function GetMethodProp(Instance : TObject;PropInfo : PPropInfo) : TMethod;
  830. var
  831. value: PMethod;
  832. Index,Ivalue : longint;
  833. begin
  834. SetIndexValues(PropInfo,Index,Ivalue);
  835. case (PropInfo^.PropProcs) and 3 of
  836. ptfield:
  837. Value:=PMethod(Pointer(Instance)+Longint(PropInfo^.GetProc));
  838. ptstatic:
  839. Value:=PMethod(LongInt(CallIntegerFunc(Instance,PropInfo^.GetProc,Index,IValue)));
  840. ptvirtual:
  841. Value:=PMethod(LongInt(CallIntegerFunc(Instance,PPointer(Pointer(Instance.ClassType)+Longint(PropInfo^.GetProc))^,Index,IValue)));
  842. end;
  843. GetMethodProp:=Value^;
  844. end;
  845. Procedure SetMethodProp(Instance : TObject;PropInfo : PPropInfo;
  846. const Value : TMethod);
  847. var
  848. Index,IValue : Longint;
  849. begin
  850. SetIndexValues(PropInfo,Index,Ivalue);
  851. case (PropInfo^.PropProcs shr 2) and 3 of
  852. ptfield:
  853. PMethod(Pointer(Instance)+Longint(PropInfo^.SetProc))^ := Value;
  854. ptstatic:
  855. CallIntegerProc(Instance,PropInfo^.SetProc,Integer(@Value), Index, IValue);
  856. ptvirtual:
  857. CallIntegerProc(Instance,
  858. PPointer(Pointer(Instance.ClassType)+Longint(PropInfo^.SetProc))^,
  859. Integer(@Value), Index, IValue);
  860. end;
  861. end;
  862. Function GetMethodProp(Instance: TObject; const PropName: string): TMethod;
  863. begin
  864. Result:=GetMethodProp(Instance,FindPropInfo(Instance,PropName));
  865. end;
  866. Procedure SetMethodProp(Instance: TObject; const PropName: string; const Value: TMethod);
  867. begin
  868. SetMethodProp(Instance,FindPropInfo(Instance,PropName),Value);
  869. end;
  870. { ---------------------------------------------------------------------
  871. Int64 properties
  872. ---------------------------------------------------------------------}
  873. Function GetInt64Prop(Instance: TObject; PropInfo: PPropInfo): Int64;
  874. var
  875. Index, IValue: LongInt;
  876. begin
  877. SetIndexValues(PropInfo,Index,Ivalue);
  878. case PropInfo^.PropProcs and 3 of
  879. ptfield:
  880. Result := PInt64(Pointer(Instance)+Longint(PropInfo^.GetProc))^;
  881. ptstatic:
  882. Result := CallIntegerFunc(Instance, PropInfo^.GetProc, Index, IValue);
  883. ptvirtual:
  884. Result := CallIntegerFunc(Instance,
  885. PPointer(Pointer(Instance.ClassType) + LongInt(PropInfo^.GetProc))^,
  886. Index, IValue);
  887. end;
  888. end;
  889. procedure SetInt64Prop(Instance: TObject; PropInfo: PPropInfo; const Value: Int64);
  890. var
  891. Index, IValue: LongInt;
  892. begin
  893. SetIndexValues(PropInfo,Index,Ivalue);
  894. case PropInfo^.PropProcs and 3 of
  895. ptfield:
  896. PInt64(Pointer(Instance)+Longint(PropInfo^.GetProc))^ := Value;
  897. ptstatic:
  898. CallIntegerProc(Instance,PropInfo^.SetProc,Value,Index,IValue);
  899. ptvirtual:
  900. CallIntegerProc(Instance,PPointer(Pointer(Instance.ClassType)+Longint(PropInfo^.SetProc))^,Value,Index,IValue);
  901. end;
  902. end;
  903. Function GetInt64Prop(Instance: TObject; const PropName: string): Int64;
  904. begin
  905. Result:=GetInt64Prop(Instance,FindPropInfo(Instance,PropName));
  906. end;
  907. Procedure SetInt64Prop(Instance: TObject; const PropName: string; const Value: Int64);
  908. begin
  909. SetInt64Prop(Instance,FindPropInfo(Instance,PropName),Value);
  910. end;
  911. { ---------------------------------------------------------------------
  912. All properties through variant.
  913. ---------------------------------------------------------------------}
  914. Function GetPropValue(Instance: TObject; const PropName: string): Variant;
  915. begin
  916. Result:=GetPropValue(Instance,PropName,True);
  917. end;
  918. Function GetPropValue(Instance: TObject; const PropName: string; PreferStrings: Boolean): Variant;
  919. begin
  920. end;
  921. Procedure SetPropValue(Instance: TObject; const PropName: string; const Value: Variant);
  922. begin
  923. end;
  924. { ---------------------------------------------------------------------
  925. Easy access methods that appeared in Delphi 5
  926. ---------------------------------------------------------------------}
  927. Function IsPublishedProp(Instance: TObject; const PropName: string): Boolean;
  928. begin
  929. Result:=GetPropInfo(Instance,PropName)<>Nil;
  930. end;
  931. Function IsPublishedProp(AClass: TClass; const PropName: string): Boolean;
  932. begin
  933. Result:=GetPropInfo(AClass,PropName)<>Nil;
  934. end;
  935. Function PropIsType(Instance: TObject; const PropName: string; TypeKind: TTypeKind): Boolean;
  936. begin
  937. Result:=FindPropInfo(Instance,PropName)^.PropType^.Kind=TypeKind
  938. end;
  939. Function PropIsType(AClass: TClass; const PropName: string; TypeKind: TTypeKind): Boolean;
  940. begin
  941. Result:=PropType(AClass,PropName)=TypeKind
  942. end;
  943. Function PropType(Instance: TObject; const PropName: string): TTypeKind;
  944. begin
  945. Result:=FindPropInfo(Instance,PropName)^.PropType^.Kind;
  946. end;
  947. Function PropType(AClass: TClass; const PropName: string): TTypeKind;
  948. begin
  949. Result:=FindPropInfo(AClass,PropName)^.PropType^.Kind;
  950. end;
  951. Function IsStoredProp(Instance: TObject; const PropName: string): Boolean;
  952. begin
  953. Result:=IsStoredProp(instance,FindPropInfo(Instance,PropName));
  954. end;
  955. end.
  956. {
  957. $Log$
  958. Revision 1.14 2002-09-07 16:01:22 peter
  959. * old logs removed and tabs fixed
  960. Revision 1.13 2002/04/04 18:32:59 peter
  961. * merged getpropinfo fix
  962. }