typinfo.pp 78 KB

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