typinfo.pp 50 KB

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