typinfo.pp 68 KB

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