2
0

typinfo.pp 50 KB

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