typinfo.pp 49 KB

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