typinfo.pp 49 KB

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