typinfo.pp 61 KB

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