typinfo.pp 87 KB

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