rtti.pp 67 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (C) 2013 Joost van der Sluis [email protected]
  4. member of the Free Pascal development team.
  5. Extended RTTI compatibility unit
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. }
  12. unit Rtti experimental;
  13. {$mode objfpc}{$H+}
  14. {$modeswitch advancedrecords}
  15. { Note: since the Lazarus IDE is not yet capable of correctly handling generic
  16. functions it is best to define a InLazIDE define inside the IDE that disables
  17. the generic code for CodeTools. To do this do this:
  18. - go to Tools -> Codetools Defines Editor
  19. - go to Edit -> Insert Node Below -> Define Recurse
  20. - enter the following values:
  21. Name: InLazIDE
  22. Description: Define InLazIDE everywhere
  23. Variable: InLazIDE
  24. Value from text: 1
  25. }
  26. {$ifdef InLazIDE}
  27. {$define NoGenericMethods}
  28. {$endif}
  29. interface
  30. uses
  31. Classes,
  32. SysUtils,
  33. typinfo;
  34. type
  35. TRttiType = class;
  36. TRttiProperty = class;
  37. TRttiInstanceType = class;
  38. IValueData = interface
  39. ['{1338B2F3-2C21-4798-A641-CA2BC5BF2396}']
  40. procedure ExtractRawData(ABuffer: pointer);
  41. procedure ExtractRawDataNoCopy(ABuffer: pointer);
  42. function GetDataSize: SizeInt;
  43. function GetReferenceToRawData: pointer;
  44. end;
  45. TValueData = record
  46. FTypeInfo: PTypeInfo;
  47. FValueData: IValueData;
  48. case integer of
  49. 0: (FAsUByte: Byte);
  50. 1: (FAsUWord: Word);
  51. 2: (FAsULong: LongWord);
  52. 3: (FAsObject: Pointer);
  53. 4: (FAsClass: TClass);
  54. 5: (FAsSByte: Shortint);
  55. 6: (FAsSWord: Smallint);
  56. 7: (FAsSLong: LongInt);
  57. 8: (FAsSingle: Single);
  58. 9: (FAsDouble: Double);
  59. 10: (FAsExtended: Extended);
  60. 11: (FAsComp: Comp);
  61. 12: (FAsCurr: Currency);
  62. 13: (FAsUInt64: QWord);
  63. 14: (FAsSInt64: Int64);
  64. 15: (FAsMethod: TMethod);
  65. 16: (FAsPointer: Pointer);
  66. end;
  67. { TValue }
  68. TValue = record
  69. private
  70. FData: TValueData;
  71. function GetDataSize: SizeInt;
  72. function GetTypeDataProp: PTypeData; inline;
  73. function GetTypeInfo: PTypeInfo; inline;
  74. function GetTypeKind: TTypeKind; inline;
  75. function GetIsEmpty: boolean; inline;
  76. public
  77. class function Empty: TValue; static;
  78. class procedure Make(ABuffer: pointer; ATypeInfo: PTypeInfo; out result: TValue); static;
  79. {$ifndef NoGenericMethods}
  80. generic class function From<T>(constref aValue: T): TValue; static; inline;
  81. {$endif}
  82. function IsArray: boolean; inline;
  83. function AsString: string; inline;
  84. function AsUnicodeString: UnicodeString;
  85. function AsAnsiString: AnsiString;
  86. function AsExtended: Extended;
  87. function IsClass: boolean; inline;
  88. function AsClass: TClass;
  89. function IsObject: boolean; inline;
  90. function AsObject: TObject;
  91. function IsOrdinal: boolean; inline;
  92. function AsOrdinal: Int64;
  93. function AsBoolean: boolean;
  94. function AsCurrency: Currency;
  95. function AsInteger: Integer;
  96. function AsInt64: Int64;
  97. function AsUInt64: QWord;
  98. function AsInterface: IInterface;
  99. function ToString: String;
  100. function GetArrayLength: SizeInt;
  101. function GetArrayElement(AIndex: SizeInt): TValue;
  102. procedure SetArrayElement(AIndex: SizeInt; constref AValue: TValue);
  103. function IsType(ATypeInfo: PTypeInfo): boolean; inline;
  104. function TryAsOrdinal(out AResult: int64): boolean;
  105. function GetReferenceToRawData: Pointer;
  106. class operator := (const AValue: String): TValue; inline;
  107. class operator := (AValue: LongInt): TValue; inline;
  108. class operator := (AValue: Single): TValue; inline;
  109. class operator := (AValue: Double): TValue; inline;
  110. {$ifdef FPC_HAS_TYPE_EXTENDED}
  111. class operator := (AValue: Extended): TValue; inline;
  112. {$endif}
  113. class operator := (AValue: Currency): TValue; inline;
  114. class operator := (AValue: Int64): TValue; inline;
  115. class operator := (AValue: QWord): TValue; inline;
  116. class operator := (AValue: TObject): TValue; inline;
  117. class operator := (AValue: TClass): TValue; inline;
  118. class operator := (AValue: Boolean): TValue; inline;
  119. property DataSize: SizeInt read GetDataSize;
  120. property Kind: TTypeKind read GetTypeKind;
  121. property TypeData: PTypeData read GetTypeDataProp;
  122. property TypeInfo: PTypeInfo read GetTypeInfo;
  123. property IsEmpty: boolean read GetIsEmpty;
  124. end;
  125. TValueArray = specialize TArray<TValue>;
  126. { TRttiContext }
  127. TRttiContext = record
  128. private
  129. FContextToken: IInterface;
  130. public
  131. class function Create: TRttiContext; static;
  132. procedure Free;
  133. function GetType(ATypeInfo: PTypeInfo): TRttiType;
  134. function GetType(AClass: TClass): TRttiType;
  135. //function GetTypes: specialize TArray<TRttiType>;
  136. end;
  137. { TRttiObject }
  138. TRttiObject = class abstract
  139. protected
  140. function GetHandle: Pointer; virtual; abstract;
  141. public
  142. property Handle: Pointer read GetHandle;
  143. end;
  144. { TRttiNamedObject }
  145. TRttiNamedObject = class(TRttiObject)
  146. protected
  147. function GetName: string; virtual;
  148. public
  149. property Name: string read GetName;
  150. end;
  151. { TRttiType }
  152. TRttiType = class(TRttiNamedObject)
  153. private
  154. FTypeInfo: PTypeInfo;
  155. function GetAsInstance: TRttiInstanceType;
  156. protected
  157. FTypeData: PTypeData;
  158. function GetName: string; override;
  159. function GetHandle: Pointer; override;
  160. function GetIsInstance: boolean; virtual;
  161. function GetIsManaged: boolean; virtual;
  162. function GetIsOrdinal: boolean; virtual;
  163. function GetIsRecord: boolean; virtual;
  164. function GetIsSet: boolean; virtual;
  165. function GetTypeKind: TTypeKind; virtual;
  166. function GetTypeSize: integer; virtual;
  167. function GetBaseType: TRttiType; virtual;
  168. public
  169. constructor create(ATypeInfo : PTypeInfo);
  170. function GetProperties: specialize TArray<TRttiProperty>; virtual;
  171. function GetProperty(const AName: string): TRttiProperty; virtual;
  172. property IsInstance: boolean read GetIsInstance;
  173. property isManaged: boolean read GetIsManaged;
  174. property IsOrdinal: boolean read GetIsOrdinal;
  175. property IsRecord: boolean read GetIsRecord;
  176. property IsSet: boolean read GetIsSet;
  177. property BaseType: TRttiType read GetBaseType;
  178. property AsInstance: TRttiInstanceType read GetAsInstance;
  179. property TypeKind: TTypeKind read GetTypeKind;
  180. property TypeSize: integer read GetTypeSize;
  181. end;
  182. { TRttiFloatType }
  183. TRttiFloatType = class(TRttiType)
  184. private
  185. function GetFloatType: TFloatType;
  186. public
  187. property FloatType: TFloatType read GetFloatType;
  188. end;
  189. TRttiStringKind = (skShortString, skAnsiString, skWideString, skUnicodeString);
  190. { TRttiStringType }
  191. TRttiStringType = class(TRttiType)
  192. private
  193. function GetStringKind: TRttiStringKind;
  194. public
  195. property StringKind: TRttiStringKind read GetStringKind;
  196. end;
  197. TRttiPointerType = class(TRttiType)
  198. private
  199. function GetReferredType: TRttiType;
  200. public
  201. property ReferredType: TRttiType read GetReferredType;
  202. end;
  203. { TRttiMember }
  204. TMemberVisibility=(mvPrivate, mvProtected, mvPublic, mvPublished);
  205. TRttiMember = class(TRttiNamedObject)
  206. private
  207. FParent: TRttiType;
  208. protected
  209. function GetVisibility: TMemberVisibility; virtual;
  210. public
  211. constructor create(AParent: TRttiType);
  212. property Visibility: TMemberVisibility read GetVisibility;
  213. property Parent: TRttiType read FParent;
  214. end;
  215. { TRttiProperty }
  216. TRttiProperty = class(TRttiMember)
  217. private
  218. FPropInfo: PPropInfo;
  219. function GetPropertyType: TRttiType;
  220. function GetIsWritable: boolean;
  221. function GetIsReadable: boolean;
  222. protected
  223. function GetVisibility: TMemberVisibility; override;
  224. function GetName: string; override;
  225. function GetHandle: Pointer; override;
  226. public
  227. constructor create(AParent: TRttiType; APropInfo: PPropInfo);
  228. function GetValue(Instance: pointer): TValue;
  229. procedure SetValue(Instance: pointer; const AValue: TValue);
  230. property PropertyType: TRttiType read GetPropertyType;
  231. property IsReadable: boolean read GetIsReadable;
  232. property IsWritable: boolean read GetIsWritable;
  233. property Visibility: TMemberVisibility read GetVisibility;
  234. end;
  235. TRttiParameter = class(TRttiNamedObject)
  236. private
  237. FString: String;
  238. protected
  239. function GetParamType: TRttiType; virtual; abstract;
  240. function GetFlags: TParamFlags; virtual; abstract;
  241. public
  242. property ParamType: TRttiType read GetParamType;
  243. property Flags: TParamFlags read GetFlags;
  244. function ToString: String; override;
  245. end;
  246. TDispatchKind = (
  247. dkStatic,
  248. dkVtable,
  249. dkDynamic,
  250. dkMessage,
  251. dkInterface,
  252. { the following are FPC-only and will be moved should Delphi add more }
  253. dkMessageString
  254. );
  255. TRttiMethod = class(TRttiMember)
  256. private
  257. FString: String;
  258. protected
  259. function GetCallingConvention: TCallConv; virtual; abstract;
  260. function GetCodeAddress: CodePointer; virtual; abstract;
  261. function GetDispatchKind: TDispatchKind; virtual; abstract;
  262. function GetHasExtendedInfo: Boolean; virtual;
  263. function GetIsClassMethod: Boolean; virtual; abstract;
  264. function GetIsConstructor: Boolean; virtual; abstract;
  265. function GetIsDestructor: Boolean; virtual; abstract;
  266. function GetIsStatic: Boolean; virtual; abstract;
  267. function GetMethodKind: TMethodKind; virtual; abstract;
  268. function GetReturnType: TRttiType; virtual; abstract;
  269. function GetVirtualIndex: SmallInt; virtual; abstract;
  270. public
  271. property CallingConvention: TCallConv read GetCallingConvention;
  272. property CodeAddress: CodePointer read GetCodeAddress;
  273. property DispatchKind: TDispatchKind read GetDispatchKind;
  274. property HasExtendedInfo: Boolean read GetHasExtendedInfo;
  275. property IsClassMethod: Boolean read GetIsClassMethod;
  276. property IsConstructor: Boolean read GetIsConstructor;
  277. property IsDestructor: Boolean read GetIsDestructor;
  278. property IsStatic: Boolean read GetIsStatic;
  279. property MethodKind: TMethodKind read GetMethodKind;
  280. property ReturnType: TRttiType read GetReturnType;
  281. property VirtualIndex: SmallInt read GetVirtualIndex;
  282. function ToString: String; override;
  283. function GetParameters: specialize TArray<TRttiParameter>; virtual; abstract;
  284. end;
  285. TRttiStructuredType = class(TRttiType)
  286. end;
  287. TInterfaceType = (
  288. itRefCounted, { aka COM interface }
  289. itRaw { aka CORBA interface }
  290. );
  291. TRttiInterfaceType = class(TRttiType)
  292. protected
  293. function GetBaseType: TRttiType; override;
  294. function GetIntfBaseType: TRttiInterfaceType; virtual; abstract;
  295. function GetDeclaringUnitName: String; virtual; abstract;
  296. function GetGUID: TGUID; virtual; abstract;
  297. function GetGUIDStr: String; virtual;
  298. function GetIntfFlags: TIntfFlags; virtual; abstract;
  299. function GetIntfType: TInterfaceType; virtual; abstract;
  300. public
  301. property BaseType: TRttiInterfaceType read GetIntfBaseType;
  302. property DeclaringUnitName: String read GetDeclaringUnitName;
  303. property GUID: TGUID read GetGUID;
  304. property GUIDStr: String read GetGUIDStr;
  305. property IntfFlags: TIntfFlags read GetIntfFlags;
  306. property IntfType: TInterfaceType read GetIntfType;
  307. end;
  308. { TRttiInstanceType }
  309. TRttiInstanceType = class(TRttiStructuredType)
  310. private
  311. FPropertiesResolved: Boolean;
  312. FProperties: specialize TArray<TRttiProperty>;
  313. function GetDeclaringUnitName: string;
  314. function GetMetaClassType: TClass;
  315. protected
  316. function GetIsInstance: boolean; override;
  317. function GetTypeSize: integer; override;
  318. function GetBaseType: TRttiType; override;
  319. public
  320. function GetProperties: specialize TArray<TRttiProperty>; override;
  321. property MetaClassType: TClass read GetMetaClassType;
  322. property DeclaringUnitName: string read GetDeclaringUnitName;
  323. end;
  324. EInsufficientRtti = class(Exception);
  325. EInvocationError = class(Exception);
  326. ENonPublicType = class(Exception);
  327. TFunctionCallParameter = record
  328. Value: TValue;
  329. ParamFlags: TParamFlags;
  330. ParaLocs: PParameterLocations;
  331. end;
  332. TFunctionCallParameterArray = specialize TArray<TFunctionCallParameter>;
  333. TFunctionCallFlag = (
  334. fcfStatic
  335. );
  336. TFunctionCallFlags = set of TFunctionCallFlag;
  337. TFunctionCallCallback = Pointer;
  338. TFunctionCallProc = procedure(const aArgs: TValueArray; out aResult: TValue; aContext: Pointer);
  339. TFunctionCallMethod = procedure(const aArgs: TValueArray; out aResult: TValue; aContext: Pointer) of object;
  340. TFunctionCallManager = record
  341. Invoke: procedure(CodeAddress: CodePointer; const Args: TFunctionCallParameterArray; CallingConvention: TCallConv;
  342. ResultType: PTypeInfo; out ResultValue: TValue; Flags: TFunctionCallFlags);
  343. CreateCallbackProc: function(aHandler: TFunctionCallProc; aCallConv: TCallConv; aArgs: array of PTypeInfo; aResultType: PTypeInfo; aFlags: TFunctionCallFlags; aContext: Pointer): TFunctionCallCallback;
  344. CreateCallbackMethod: function(aHandler: TFunctionCallMethod; aCallConv: TCallConv; aArgs: array of PTypeInfo; aResultType: PTypeInfo; aFlags: TFunctionCallFlags; aContext: Pointer): TFunctionCallCallback;
  345. FreeCallback: procedure(aCallback: TFunctionCallCallback; aCallConv: TCallConv);
  346. end;
  347. TFunctionCallManagerArray = array[TCallConv] of TFunctionCallManager;
  348. TCallConvSet = set of TCallConv;
  349. procedure SetFunctionCallManager(aCallConv: TCallConv; constref aFuncCallMgr: TFunctionCallManager; out aOldFuncCallMgr: TFunctionCallManager);
  350. procedure SetFunctionCallManager(aCallConv: TCallConv; constref aFuncCallMgr: TFunctionCallManager);
  351. procedure SetFunctionCallManager(aCallConvs: TCallConvSet; constref aFuncCallMgr: TFunctionCallManager; out aOldFuncCallMgrs: TFunctionCallManagerArray);
  352. procedure SetFunctionCallManager(aCallConvs: TCallConvSet; constref aFuncCallMgr: TFunctionCallManager);
  353. procedure SetFunctionCallManagers(aCallConvs: TCallConvSet; constref aFuncCallMgrs: TFunctionCallManagerArray; out aOldFuncCallMgrs: TFunctionCallManagerArray);
  354. procedure SetFunctionCallManagers(aCallConvs: TCallConvSet; constref aFuncCallMgrs: TFunctionCallManagerArray);
  355. procedure SetFunctionCallManagers(constref aFuncCallMgrs: TFunctionCallManagerArray; out aOldFuncCallMgrs: TFunctionCallManagerArray);
  356. procedure SetFunctionCallManagers(constref aFuncCallMgrs: TFunctionCallManagerArray);
  357. procedure GetFunctionCallManager(aCallConv: TCallConv; out aFuncCallMgr: TFunctionCallManager);
  358. procedure GetFunctionCallManagers(aCallConvs: TCallConvSet; out aFuncCallMgrs: TFunctionCallManagerArray);
  359. procedure GetFunctionCallManagers(out aFuncCallMgrs: TFunctionCallManagerArray);
  360. function Invoke(aCodeAddress: CodePointer; const aArgs: TValueArray; aCallConv: TCallConv;
  361. aResultType: PTypeInfo; aIsStatic: Boolean; aIsConstructor: Boolean): TValue;
  362. function CreateCallbackProc(aHandler: TFunctionCallProc; aCallConv: TCallConv; aArgs: array of PTypeInfo; aResultType: PTypeInfo; aFlags: TFunctionCallFlags; aContext: Pointer): TFunctionCallCallback;
  363. function CreateCallbackMethod(aHandler: TFunctionCallMethod; aCallConv: TCallConv; aArgs: array of PTypeInfo; aResultType: PTypeInfo; aFlags: TFunctionCallFlags; aContext: Pointer): TFunctionCallCallback;
  364. procedure FreeCallback(aCallback: TFunctionCallCallback; aCallConv: TCallConv);
  365. function IsManaged(TypeInfo: PTypeInfo): boolean;
  366. { these resource strings are needed by units implementing function call managers }
  367. resourcestring
  368. SErrInvokeNotImplemented = 'Invoke functionality is not implemented';
  369. SErrInvokeFailed = 'Invoke call failed';
  370. SErrCallbackNotImplented = 'Callback functionality is not implemented';
  371. SErrCallConvNotSupported = 'Calling convention not supported: %s';
  372. SErrTypeKindNotSupported = 'Type kind is not supported: %s';
  373. SErrCallbackHandlerNil = 'Callback handler is Nil';
  374. SErrMissingSelfParam = 'Missing self parameter';
  375. implementation
  376. uses
  377. fgl;
  378. type
  379. { TRttiPool }
  380. TRttiPool = class
  381. private type
  382. TRttiObjectMap = specialize TFPGMap<Pointer, TRttiObject>;
  383. private
  384. FObjectMap: TRttiObjectMap;
  385. FTypesList: specialize TArray<TRttiType>;
  386. FTypeCount: LongInt;
  387. FLock: TRTLCriticalSection;
  388. public
  389. function GetTypes: specialize TArray<TRttiType>;
  390. function GetType(ATypeInfo: PTypeInfo): TRttiType;
  391. function GetByHandle(aHandle: Pointer): TRttiObject;
  392. procedure AddObject(aObject: TRttiObject);
  393. constructor Create;
  394. destructor Destroy; override;
  395. end;
  396. IPooltoken = interface
  397. ['{3CDB3CE9-AB55-CBAA-7B9D-2F3BB1CF5AF8}']
  398. function RttiPool: TRttiPool;
  399. end;
  400. { TPoolToken }
  401. TPoolToken = class(TInterfacedObject, IPooltoken)
  402. public
  403. constructor Create;
  404. destructor Destroy; override;
  405. function RttiPool: TRttiPool;
  406. end;
  407. { TValueDataIntImpl }
  408. TValueDataIntImpl = class(TInterfacedObject, IValueData)
  409. private
  410. FBuffer: Pointer;
  411. FDataSize: SizeInt;
  412. FTypeInfo: PTypeInfo;
  413. FIsCopy: Boolean;
  414. FUseAddRef: Boolean;
  415. public
  416. constructor CreateCopy(ACopyFromBuffer: Pointer; ALen: SizeInt; ATypeInfo: PTypeInfo; AAddRef: Boolean);
  417. constructor CreateRef(AData: Pointer; ATypeInfo: PTypeInfo; AAddRef: Boolean);
  418. destructor Destroy; override;
  419. procedure ExtractRawData(ABuffer: pointer);
  420. procedure ExtractRawDataNoCopy(ABuffer: pointer);
  421. function GetDataSize: SizeInt;
  422. function GetReferenceToRawData: pointer;
  423. end;
  424. TRttiRefCountedInterfaceType = class(TRttiInterfaceType)
  425. private
  426. function IntfData: PInterfaceData; inline;
  427. protected
  428. function GetIntfBaseType: TRttiInterfaceType; override;
  429. function GetDeclaringUnitName: String; override;
  430. function GetGUID: TGUID; override;
  431. function GetIntfFlags: TIntfFlags; override;
  432. function GetIntfType: TInterfaceType; override;
  433. end;
  434. TRttiRawInterfaceType = class(TRttiInterfaceType)
  435. private
  436. function IntfData: PInterfaceRawData; inline;
  437. protected
  438. function GetIntfBaseType: TRttiInterfaceType; override;
  439. function GetDeclaringUnitName: String; override;
  440. function GetGUID: TGUID; override;
  441. function GetGUIDStr: String; override;
  442. function GetIntfFlags: TIntfFlags; override;
  443. function GetIntfType: TInterfaceType; override;
  444. end;
  445. TRttiVmtMethodParameter = class(TRttiParameter)
  446. private
  447. FVmtMethodParam: PVmtMethodParam;
  448. protected
  449. function GetHandle: Pointer; override;
  450. function GetName: String; override;
  451. function GetFlags: TParamFlags; override;
  452. function GetParamType: TRttiType; override;
  453. public
  454. constructor Create(AVmtMethodParam: PVmtMethodParam);
  455. end;
  456. resourcestring
  457. SErrUnableToGetValueForType = 'Unable to get value for type %s';
  458. SErrUnableToSetValueForType = 'Unable to set value for type %s';
  459. SErrInvalidTypecast = 'Invalid class typecast';
  460. SErrRttiObjectNoHandle = 'RTTI object instance has no valid handle property';
  461. SErrRttiObjectAlreadyRegistered = 'A RTTI object with handle 0x%x is already registered';
  462. var
  463. PoolRefCount : integer;
  464. GRttiPool : TRttiPool;
  465. FuncCallMgr: TFunctionCallManagerArray;
  466. procedure NoInvoke(aCodeAddress: CodePointer; const aArgs: TFunctionCallParameterArray; aCallConv: TCallConv;
  467. aResultType: PTypeInfo; out aResultValue: TValue; aFlags: TFunctionCallFlags);
  468. begin
  469. raise ENotImplemented.Create(SErrInvokeNotImplemented);
  470. end;
  471. function NoCreateCallbackProc(aFunc: TFunctionCallProc; aCallConv: TCallConv; aArgs: array of PTypeInfo; aResultType: PTypeInfo; aFlags: TFunctionCallFlags; aContext: Pointer): TFunctionCallCallback;
  472. begin
  473. Result := Nil;
  474. raise ENotImplemented.Create(SErrCallbackNotImplented);
  475. end;
  476. function NoCreateCallbackMethod(aFunc: TFunctionCallMethod; aCallConv: TCallConv; aArgs: array of PTypeInfo; aResultType: PTypeInfo; aFlags: TFunctionCallFlags; aContext: Pointer): TFunctionCallCallback;
  477. begin
  478. Result := Nil;
  479. raise ENotImplemented.Create(SErrCallbackNotImplented);
  480. end;
  481. procedure NoFreeCallback(aCallback: TFunctionCallCallback; aCallConv: TCallConv);
  482. begin
  483. raise ENotImplemented.Create(SErrCallbackNotImplented);
  484. end;
  485. const
  486. NoFunctionCallManager: TFunctionCallManager = (
  487. Invoke: @NoInvoke;
  488. CreateCallbackProc: @NoCreateCallbackProc;
  489. CreateCallbackMethod: @NoCreateCallbackMethod;
  490. FreeCallback: @NoFreeCallback
  491. );
  492. procedure SetFunctionCallManager(aCallConv: TCallConv; constref aFuncCallMgr: TFunctionCallManager;
  493. out aOldFuncCallMgr: TFunctionCallManager);
  494. begin
  495. aOldFuncCallMgr := FuncCallMgr[aCallConv];
  496. FuncCallMgr[aCallConv] := aFuncCallMgr;
  497. end;
  498. procedure SetFunctionCallManager(aCallConv: TCallConv; constref aFuncCallMgr: TFunctionCallManager);
  499. var
  500. dummy: TFunctionCallManager;
  501. begin
  502. SetFunctionCallManager(aCallConv, aFuncCallMgr, dummy);
  503. end;
  504. procedure SetFunctionCallManager(aCallConvs: TCallConvSet; constref aFuncCallMgr: TFunctionCallManager;
  505. out aOldFuncCallMgrs: TFunctionCallManagerArray);
  506. var
  507. cc: TCallConv;
  508. begin
  509. for cc := Low(TCallConv) to High(TCallConv) do
  510. if cc in aCallConvs then begin
  511. aOldFuncCallMgrs[cc] := FuncCallMgr[cc];
  512. FuncCallMgr[cc] := aFuncCallMgr;
  513. end else
  514. aOldFuncCallMgrs[cc] := Default(TFunctionCallManager);
  515. end;
  516. procedure SetFunctionCallManager(aCallConvs: TCallConvSet; constref aFuncCallMgr: TFunctionCallManager);
  517. var
  518. dummy: TFunctionCallManagerArray;
  519. begin
  520. SetFunctionCallManager(aCallConvs, aFuncCallMgr, dummy);
  521. end;
  522. procedure SetFunctionCallManagers(aCallConvs: TCallConvSet; constref aFuncCallMgrs: TFunctionCallManagerArray; out aOldFuncCallMgrs: TFunctionCallManagerArray);
  523. var
  524. cc: TCallConv;
  525. begin
  526. for cc := Low(TCallConv) to High(TCallConv) do
  527. if cc in aCallConvs then begin
  528. aOldFuncCallMgrs[cc] := FuncCallMgr[cc];
  529. FuncCallMgr[cc] := aFuncCallMgrs[cc];
  530. end else
  531. aOldFuncCallMgrs[cc] := Default(TFunctionCallManager);
  532. end;
  533. procedure SetFunctionCallManagers(aCallConvs: TCallConvSet; constref aFuncCallMgrs: TFunctionCallManagerArray);
  534. var
  535. dummy: TFunctionCallManagerArray;
  536. begin
  537. SetFunctionCallManagers(aCallConvs, aFuncCallMgrs, dummy);
  538. end;
  539. procedure SetFunctionCallManagers(constref aFuncCallMgrs: TFunctionCallManagerArray; out aOldFuncCallMgrs: TFunctionCallManagerArray);
  540. begin
  541. aOldFuncCallMgrs := FuncCallMgr;
  542. FuncCallMgr := aFuncCallMgrs;
  543. end;
  544. procedure SetFunctionCallManagers(constref aFuncCallMgrs: TFunctionCallManagerArray);
  545. var
  546. dummy: TFunctionCallManagerArray;
  547. begin
  548. SetFunctionCallManagers(aFuncCallMgrs, dummy);
  549. end;
  550. procedure GetFunctionCallManager(aCallConv: TCallConv; out aFuncCallMgr: TFunctionCallManager);
  551. begin
  552. aFuncCallMgr := FuncCallMgr[aCallConv];
  553. end;
  554. procedure GetFunctionCallManagers(aCallConvs: TCallConvSet; out aFuncCallMgrs: TFunctionCallManagerArray);
  555. var
  556. cc: TCallConv;
  557. begin
  558. for cc := Low(TCallConv) to High(TCallConv) do
  559. if cc in aCallConvs then
  560. aFuncCallMgrs[cc] := FuncCallMgr[cc]
  561. else
  562. aFuncCallMgrs[cc] := Default(TFunctionCallManager);
  563. end;
  564. procedure GetFunctionCallManagers(out aFuncCallMgrs: TFunctionCallManagerArray);
  565. begin
  566. aFuncCallMgrs := FuncCallMgr;
  567. end;
  568. procedure InitDefaultFunctionCallManager;
  569. var
  570. cc: TCallConv;
  571. begin
  572. for cc := Low(TCallConv) to High(TCallConv) do
  573. FuncCallMgr[cc] := NoFunctionCallManager;
  574. end;
  575. function Invoke(aCodeAddress: CodePointer; const aArgs: TValueArray;
  576. aCallConv: TCallConv; aResultType: PTypeInfo; aIsStatic: Boolean;
  577. aIsConstructor: Boolean): TValue;
  578. var
  579. funcargs: TFunctionCallParameterArray;
  580. i: LongInt;
  581. flags: TFunctionCallFlags;
  582. begin
  583. { sanity check }
  584. if not Assigned(FuncCallMgr[aCallConv].Invoke) then
  585. raise ENotImplemented.Create(SErrInvokeNotImplemented);
  586. { ToDo: handle IsConstructor }
  587. if aIsConstructor then
  588. raise ENotImplemented.Create(SErrInvokeNotImplemented);
  589. flags := [];
  590. if aIsStatic then
  591. Include(flags, fcfStatic)
  592. else if Length(aArgs) = 0 then
  593. raise EInvocationError.Create(SErrMissingSelfParam);
  594. SetLength(funcargs, Length(aArgs));
  595. for i := Low(aArgs) to High(aArgs) do begin
  596. funcargs[i - Low(aArgs) + Low(funcargs)].Value := aArgs[i];
  597. funcargs[i - Low(aArgs) + Low(funcargs)].ParamFlags := [];
  598. funcargs[i - Low(aArgs) + Low(funcargs)].ParaLocs := Nil;
  599. end;
  600. FuncCallMgr[aCallConv].Invoke(aCodeAddress, funcargs, aCallConv, aResultType, Result, flags);
  601. end;
  602. function CreateCallbackProc(aHandler: TFunctionCallProc; aCallConv: TCallConv; aArgs: array of PTypeInfo; aResultType: PTypeInfo; aFlags: TFunctionCallFlags; aContext: Pointer): TFunctionCallCallback;
  603. begin
  604. if not Assigned(FuncCallMgr[aCallConv].CreateCallbackProc) then
  605. raise ENotImplemented.Create(SErrCallbackNotImplented);
  606. if not Assigned(aHandler) then
  607. raise EArgumentNilException.Create(SErrCallbackHandlerNil);
  608. Result := FuncCallMgr[aCallConv].CreateCallbackProc(aHandler, aCallConv, aArgs, aResultType, aFlags, aContext);
  609. end;
  610. function CreateCallbackMethod(aHandler: TFunctionCallMethod; aCallConv: TCallConv; aArgs: array of PTypeInfo; aResultType: PTypeInfo; aFlags: TFunctionCallFlags; aContext: Pointer): TFunctionCallCallback;
  611. begin
  612. if not Assigned(FuncCallMgr[aCallConv].CreateCallbackMethod) then
  613. raise ENotImplemented.Create(SErrCallbackNotImplented);
  614. if not Assigned(aHandler) then
  615. raise EArgumentNilException.Create(SErrCallbackHandlerNil);
  616. Result := FuncCallMgr[aCallConv].CreateCallbackMethod(aHandler, aCallConv, aArgs, aResultType, aFlags, aContext);
  617. end;
  618. procedure FreeCallback(aCallback: TFunctionCallCallback; aCallConv: TCallConv);
  619. begin
  620. if Assigned(FuncCallMgr[aCallConv].FreeCallback) then
  621. FuncCallMgr[aCallConv].FreeCallback(aCallback, aCallConv);
  622. end;
  623. function IsManaged(TypeInfo: PTypeInfo): boolean;
  624. begin
  625. if Assigned(TypeInfo) then
  626. case TypeInfo^.Kind of
  627. tkAString,
  628. tkLString,
  629. tkWString,
  630. tkUString,
  631. tkInterface,
  632. tkVariant,
  633. tkDynArray : Result := true;
  634. tkArray : Result := IsManaged(GetTypeData(TypeInfo)^.ArrayData.ElType);
  635. tkRecord,
  636. tkObject :
  637. with GetTypeData(TypeInfo)^.RecInitData^ do
  638. Result := (ManagedFieldCount > 0) or Assigned(ManagementOp);
  639. else
  640. Result := false;
  641. end
  642. else
  643. Result := false;
  644. end;
  645. { TRttiPointerType }
  646. function TRttiPointerType.GetReferredType: TRttiType;
  647. begin
  648. Result := GRttiPool.GetType(FTypeData^.RefType);
  649. end;
  650. { TRttiPool }
  651. function TRttiPool.GetTypes: specialize TArray<TRttiType>;
  652. begin
  653. if not Assigned(FTypesList) then
  654. Exit(Nil);
  655. {$ifdef FPC_HAS_FEATURE_THREADING}
  656. EnterCriticalsection(FLock);
  657. try
  658. {$endif}
  659. Result := Copy(FTypesList, 0, FTypeCount);
  660. {$ifdef FPC_HAS_FEATURE_THREADING}
  661. finally
  662. LeaveCriticalsection(FLock);
  663. end;
  664. {$endif}
  665. end;
  666. function TRttiPool.GetType(ATypeInfo: PTypeInfo): TRttiType;
  667. var
  668. obj: TRttiObject;
  669. begin
  670. if not Assigned(ATypeInfo) then
  671. Exit(Nil);
  672. {$ifdef FPC_HAS_FEATURE_THREADING}
  673. EnterCriticalsection(FLock);
  674. try
  675. {$endif}
  676. Result := Nil;
  677. obj := GetByHandle(ATypeInfo);
  678. if Assigned(obj) then
  679. Result := obj as TRttiType;
  680. if not Assigned(Result) then
  681. begin
  682. if FTypeCount = Length(FTypesList) then
  683. begin
  684. SetLength(FTypesList, FTypeCount * 2);
  685. end;
  686. case ATypeInfo^.Kind of
  687. tkClass : Result := TRttiInstanceType.Create(ATypeInfo);
  688. tkInterface: Result := TRttiRefCountedInterfaceType.Create(ATypeInfo);
  689. tkInterfaceRaw: Result := TRttiRawInterfaceType.Create(ATypeInfo);
  690. tkSString,
  691. tkLString,
  692. tkAString,
  693. tkUString,
  694. tkWString : Result := TRttiStringType.Create(ATypeInfo);
  695. tkFloat : Result := TRttiFloatType.Create(ATypeInfo);
  696. tkPointer : Result := TRttiPointerType.Create(ATypeInfo);
  697. else
  698. Result := TRttiType.Create(ATypeInfo);
  699. end;
  700. FTypesList[FTypeCount] := Result;
  701. FObjectMap.Add(ATypeInfo, Result);
  702. Inc(FTypeCount);
  703. end;
  704. {$ifdef FPC_HAS_FEATURE_THREADING}
  705. finally
  706. LeaveCriticalsection(FLock);
  707. end;
  708. {$endif}
  709. end;
  710. function TRttiPool.GetByHandle(aHandle: Pointer): TRttiObject;
  711. var
  712. idx: LongInt;
  713. begin
  714. if not Assigned(aHandle) then
  715. Exit(Nil);
  716. {$ifdef FPC_HAS_FEATURE_THREADING}
  717. EnterCriticalsection(FLock);
  718. try
  719. {$endif}
  720. idx := FObjectMap.IndexOf(aHandle);
  721. if idx < 0 then
  722. Result := Nil
  723. else
  724. Result := FObjectMap.Data[idx];
  725. {$ifdef FPC_HAS_FEATURE_THREADING}
  726. finally
  727. LeaveCriticalsection(FLock);
  728. end;
  729. {$endif}
  730. end;
  731. procedure TRttiPool.AddObject(aObject: TRttiObject);
  732. var
  733. idx: LongInt;
  734. begin
  735. if not Assigned(aObject) then
  736. Exit;
  737. if not Assigned(aObject.Handle) then
  738. raise EArgumentException.Create(SErrRttiObjectNoHandle);
  739. {$ifdef FPC_HAS_FEATURE_THREADING}
  740. EnterCriticalsection(FLock);
  741. try
  742. {$endif}
  743. idx := FObjectMap.IndexOf(aObject.Handle);
  744. if idx < 0 then
  745. FObjectMap.Add(aObject.Handle, aObject)
  746. else if FObjectMap.Data[idx] <> aObject then
  747. raise EInvalidOpException.CreateFmt(SErrRttiObjectAlreadyRegistered, [aObject.Handle]);
  748. {$ifdef FPC_HAS_FEATURE_THREADING}
  749. finally
  750. LeaveCriticalsection(FLock);
  751. end;
  752. {$endif}
  753. end;
  754. constructor TRttiPool.Create;
  755. begin
  756. {$ifdef FPC_HAS_FEATURE_THREADING}
  757. InitCriticalSection(FLock);
  758. {$endif}
  759. SetLength(FTypesList, 32);
  760. FObjectMap := TRttiObjectMap.Create;
  761. end;
  762. destructor TRttiPool.Destroy;
  763. var
  764. i: LongInt;
  765. begin
  766. for i := 0 to FObjectMap.Count - 1 do
  767. FObjectMap.Data[i].Free;
  768. FObjectMap.Free;
  769. {$ifdef FPC_HAS_FEATURE_THREADING}
  770. DoneCriticalsection(FLock);
  771. {$endif}
  772. inherited Destroy;
  773. end;
  774. { TPoolToken }
  775. constructor TPoolToken.Create;
  776. begin
  777. inherited Create;
  778. if InterlockedIncrement(PoolRefCount)=1 then
  779. GRttiPool := TRttiPool.Create;
  780. end;
  781. destructor TPoolToken.Destroy;
  782. begin
  783. if InterlockedDecrement(PoolRefCount)=0 then
  784. GRttiPool.Free;
  785. inherited;
  786. end;
  787. function TPoolToken.RttiPool: TRttiPool;
  788. begin
  789. result := GRttiPool;
  790. end;
  791. { TValueDataIntImpl }
  792. procedure IntFinalize(APointer, ATypeInfo: Pointer);
  793. external name 'FPC_FINALIZE';
  794. procedure IntInitialize(APointer, ATypeInfo: Pointer);
  795. external name 'FPC_INITIALIZE';
  796. procedure IntAddRef(APointer, ATypeInfo: Pointer);
  797. external name 'FPC_ADDREF';
  798. function IntCopy(ASource, ADest, ATypeInfo: Pointer): SizeInt;
  799. external name 'FPC_COPY';
  800. constructor TValueDataIntImpl.CreateCopy(ACopyFromBuffer: Pointer; ALen: SizeInt; ATypeInfo: PTypeInfo; AAddRef: Boolean);
  801. begin
  802. FTypeInfo := ATypeInfo;
  803. FDataSize:=ALen;
  804. if ALen>0 then
  805. begin
  806. Getmem(FBuffer,FDataSize);
  807. if Assigned(ACopyFromBuffer) then
  808. system.move(ACopyFromBuffer^,FBuffer^,FDataSize)
  809. else
  810. FillChar(FBuffer^, FDataSize, 0);
  811. end;
  812. FIsCopy := True;
  813. FUseAddRef := AAddRef;
  814. if AAddRef and (ALen > 0) then begin
  815. if Assigned(ACopyFromBuffer) then
  816. IntAddRef(FBuffer, FTypeInfo)
  817. else
  818. IntInitialize(FBuffer, FTypeInfo);
  819. end;
  820. end;
  821. constructor TValueDataIntImpl.CreateRef(AData: Pointer; ATypeInfo: PTypeInfo; AAddRef: Boolean);
  822. begin
  823. FTypeInfo := ATypeInfo;
  824. FDataSize := SizeOf(Pointer);
  825. if Assigned(AData) then
  826. FBuffer := PPointer(AData)^
  827. else
  828. FBuffer := Nil;
  829. FIsCopy := False;
  830. FUseAddRef := AAddRef;
  831. if AAddRef and Assigned(AData) then
  832. IntAddRef(@FBuffer, FTypeInfo);
  833. end;
  834. destructor TValueDataIntImpl.Destroy;
  835. begin
  836. if Assigned(FBuffer) then begin
  837. if FUseAddRef then
  838. if FIsCopy then
  839. IntFinalize(FBuffer, FTypeInfo)
  840. else
  841. IntFinalize(@FBuffer, FTypeInfo);
  842. if FIsCopy then
  843. Freemem(FBuffer);
  844. end;
  845. inherited Destroy;
  846. end;
  847. procedure TValueDataIntImpl.ExtractRawData(ABuffer: pointer);
  848. begin
  849. if FDataSize = 0 then
  850. Exit;
  851. if FIsCopy then
  852. System.Move(FBuffer^, ABuffer^, FDataSize)
  853. else
  854. System.Move(FBuffer{!}, ABuffer^, FDataSize);
  855. if FUseAddRef then
  856. IntAddRef(ABuffer, FTypeInfo);
  857. end;
  858. procedure TValueDataIntImpl.ExtractRawDataNoCopy(ABuffer: pointer);
  859. begin
  860. if FDataSize = 0 then
  861. Exit;
  862. if FIsCopy then
  863. system.move(FBuffer^, ABuffer^, FDataSize)
  864. else
  865. System.Move(FBuffer{!}, ABuffer^, FDataSize);
  866. end;
  867. function TValueDataIntImpl.GetDataSize: SizeInt;
  868. begin
  869. result := FDataSize;
  870. end;
  871. function TValueDataIntImpl.GetReferenceToRawData: pointer;
  872. begin
  873. if FIsCopy then
  874. result := FBuffer
  875. else
  876. result := @FBuffer;
  877. end;
  878. { TRttiRefCountedInterfaceType }
  879. function TRttiRefCountedInterfaceType.IntfData: PInterfaceData;
  880. begin
  881. Result := PInterfaceData(FTypeData);
  882. end;
  883. function TRttiRefCountedInterfaceType.GetIntfBaseType: TRttiInterfaceType;
  884. var
  885. context: TRttiContext;
  886. begin
  887. if not Assigned(IntfData^.Parent) then
  888. Exit(Nil);
  889. context := TRttiContext.Create;
  890. try
  891. Result := context.GetType(IntfData^.Parent^) as TRttiInterfaceType;
  892. finally
  893. context.Free;
  894. end;
  895. end;
  896. function TRttiRefCountedInterfaceType.GetDeclaringUnitName: String;
  897. begin
  898. Result := IntfData^.UnitName;
  899. end;
  900. function TRttiRefCountedInterfaceType.GetGUID: TGUID;
  901. begin
  902. Result := IntfData^.GUID;
  903. end;
  904. function TRttiRefCountedInterfaceType.GetIntfFlags: TIntfFlags;
  905. begin
  906. Result := IntfData^.Flags;
  907. end;
  908. function TRttiRefCountedInterfaceType.GetIntfType: TInterfaceType;
  909. begin
  910. Result := itRefCounted;
  911. end;
  912. { TRttiRawInterfaceType }
  913. function TRttiRawInterfaceType.IntfData: PInterfaceRawData;
  914. begin
  915. Result := PInterfaceRawData(FTypeData);
  916. end;
  917. function TRttiRawInterfaceType.GetIntfBaseType: TRttiInterfaceType;
  918. var
  919. context: TRttiContext;
  920. begin
  921. if not Assigned(IntfData^.Parent) then
  922. Exit(Nil);
  923. context := TRttiContext.Create;
  924. try
  925. Result := context.GetType(IntfData^.Parent^) as TRttiInterfaceType;
  926. finally
  927. context.Free;
  928. end;
  929. end;
  930. function TRttiRawInterfaceType.GetDeclaringUnitName: String;
  931. begin
  932. Result := IntfData^.UnitName;
  933. end;
  934. function TRttiRawInterfaceType.GetGUID: TGUID;
  935. begin
  936. Result := IntfData^.IID;
  937. end;
  938. function TRttiRawInterfaceType.GetGUIDStr: String;
  939. begin
  940. Result := IntfData^.IIDStr;
  941. end;
  942. function TRttiRawInterfaceType.GetIntfFlags: TIntfFlags;
  943. begin
  944. Result := IntfData^.Flags;
  945. end;
  946. function TRttiRawInterfaceType.GetIntfType: TInterfaceType;
  947. begin
  948. Result := itRaw;
  949. end;
  950. { TRttiVmtMethodParameter }
  951. function TRttiVmtMethodParameter.GetHandle: Pointer;
  952. begin
  953. Result := FVmtMethodParam;
  954. end;
  955. function TRttiVmtMethodParameter.GetName: String;
  956. begin
  957. Result := FVmtMethodParam^.Name;
  958. end;
  959. function TRttiVmtMethodParameter.GetFlags: TParamFlags;
  960. begin
  961. Result := FVmtMethodParam^.Flags;
  962. end;
  963. function TRttiVmtMethodParameter.GetParamType: TRttiType;
  964. var
  965. context: TRttiContext;
  966. begin
  967. if not Assigned(FVmtMethodParam^.ParamType) then
  968. Exit(Nil);
  969. context := TRttiContext.Create;
  970. try
  971. Result := context.GetType(FVmtMethodParam^.ParamType^);
  972. finally
  973. context.Free;
  974. end;
  975. end;
  976. constructor TRttiVmtMethodParameter.Create(AVmtMethodParam: PVmtMethodParam);
  977. begin
  978. inherited Create;
  979. FVmtMethodParam := AVmtMethodParam;
  980. end;
  981. { TRttiFloatType }
  982. function TRttiFloatType.GetFloatType: TFloatType;
  983. begin
  984. result := FTypeData^.FloatType;
  985. end;
  986. { TValue }
  987. class function TValue.Empty: TValue;
  988. begin
  989. result.FData.FTypeInfo := nil;
  990. {$if SizeOf(TMethod) > SizeOf(QWord)}
  991. Result.FData.FAsMethod.Code := Nil;
  992. Result.FData.FAsMethod.Data := Nil;
  993. {$else}
  994. Result.FData.FAsUInt64 := 0;
  995. {$endif}
  996. end;
  997. class procedure TValue.Make(ABuffer: pointer; ATypeInfo: PTypeInfo; out result: TValue);
  998. type
  999. PBoolean16 = ^Boolean16;
  1000. PBoolean32 = ^Boolean32;
  1001. PBoolean64 = ^Boolean64;
  1002. PByteBool = ^ByteBool;
  1003. PQWordBool = ^QWordBool;
  1004. PMethod = ^TMethod;
  1005. var
  1006. td: PTypeData;
  1007. size: SizeInt;
  1008. begin
  1009. result.FData.FTypeInfo:=ATypeInfo;
  1010. { resets the whole variant part; FValueData is already Nil }
  1011. {$if SizeOf(TMethod) > SizeOf(QWord)}
  1012. Result.FData.FAsMethod.Code := Nil;
  1013. Result.FData.FAsMethod.Data := Nil;
  1014. {$else}
  1015. Result.FData.FAsUInt64 := 0;
  1016. {$endif}
  1017. if not Assigned(ATypeInfo) then
  1018. Exit;
  1019. { first handle those types that need a TValueData implementation }
  1020. case ATypeInfo^.Kind of
  1021. tkSString : begin
  1022. if Assigned(ABuffer) then
  1023. size := Length(PShortString(ABuffer)^) + 1
  1024. else
  1025. size := 256;
  1026. result.FData.FValueData := TValueDataIntImpl.CreateCopy(ABuffer, size, ATypeInfo, True);
  1027. end;
  1028. tkWString,
  1029. tkUString,
  1030. tkAString : result.FData.FValueData := TValueDataIntImpl.CreateRef(ABuffer, ATypeInfo, True);
  1031. tkDynArray : result.FData.FValueData := TValueDataIntImpl.CreateRef(ABuffer, ATypeInfo, True);
  1032. tkArray : result.FData.FValueData := TValueDataIntImpl.CreateCopy(ABuffer, Result.TypeData^.ArrayData.Size, ATypeInfo, False);
  1033. tkObject,
  1034. tkRecord : result.FData.FValueData := TValueDataIntImpl.CreateCopy(ABuffer, Result.TypeData^.RecSize, ATypeInfo, False);
  1035. tkInterface: result.FData.FValueData := TValueDataIntImpl.CreateRef(ABuffer, ATypeInfo, True);
  1036. end;
  1037. if not Assigned(ABuffer) then
  1038. Exit;
  1039. { now handle those that are happy with the variant part of FData }
  1040. case ATypeInfo^.Kind of
  1041. tkSString,
  1042. tkWString,
  1043. tkUString,
  1044. tkAString,
  1045. tkDynArray,
  1046. tkArray,
  1047. tkObject,
  1048. tkRecord,
  1049. tkInterface:
  1050. { ignore }
  1051. ;
  1052. tkClass : result.FData.FAsObject := PPointer(ABuffer)^;
  1053. tkClassRef : result.FData.FAsClass := PClass(ABuffer)^;
  1054. tkInterfaceRaw : result.FData.FAsPointer := PPointer(ABuffer)^;
  1055. tkInt64 : result.FData.FAsSInt64 := PInt64(ABuffer)^;
  1056. tkQWord : result.FData.FAsUInt64 := PQWord(ABuffer)^;
  1057. tkProcVar : result.FData.FAsMethod.Code := PCodePointer(ABuffer)^;
  1058. tkMethod : result.FData.FAsMethod := PMethod(ABuffer)^;
  1059. tkPointer : result.FData.FAsPointer := PPointer(ABuffer)^;
  1060. tkSet : begin
  1061. td := GetTypeData(ATypeInfo);
  1062. case td^.OrdType of
  1063. otUByte: begin
  1064. { this can either really be 1 Byte or a set > 32-bit, so
  1065. check the underlying type }
  1066. if not (td^.CompType^.Kind in [tkInteger,tkEnumeration]) then
  1067. raise Exception.CreateFmt(SErrUnableToGetValueForType,[ATypeInfo^.Name]);
  1068. case td^.SetSize of
  1069. 0, 1:
  1070. Result.FData.FAsUByte := PByte(ABuffer)^;
  1071. { these two cases shouldn't happen, but better safe than sorry... }
  1072. 2:
  1073. Result.FData.FAsUWord := PWord(ABuffer)^;
  1074. 3, 4:
  1075. Result.FData.FAsULong := PLongWord(ABuffer)^;
  1076. { maybe we should also allow storage as otUQWord? }
  1077. 5..8:
  1078. Result.FData.FAsUInt64 := PQWord(ABuffer)^;
  1079. else
  1080. Result.FData.FValueData := TValueDataIntImpl.CreateCopy(ABuffer, td^.SetSize, ATypeInfo, False);
  1081. end;
  1082. end;
  1083. otUWord:
  1084. Result.FData.FAsUWord := PWord(ABuffer)^;
  1085. otULong:
  1086. Result.FData.FAsULong := PLongWord(ABuffer)^;
  1087. else
  1088. { ehm... Panic? }
  1089. raise Exception.CreateFmt(SErrUnableToGetValueForType,[ATypeInfo^.Name]);
  1090. end;
  1091. end;
  1092. tkEnumeration,
  1093. tkInteger : begin
  1094. case GetTypeData(ATypeInfo)^.OrdType of
  1095. otSByte: result.FData.FAsSByte := PShortInt(ABuffer)^;
  1096. otUByte: result.FData.FAsUByte := PByte(ABuffer)^;
  1097. otSWord: result.FData.FAsSWord := PSmallInt(ABuffer)^;
  1098. otUWord: result.FData.FAsUWord := PWord(ABuffer)^;
  1099. otSLong: result.FData.FAsSLong := PLongInt(ABuffer)^;
  1100. otULong: result.FData.FAsULong := PLongWord(ABuffer)^;
  1101. end;
  1102. end;
  1103. tkBool : begin
  1104. case GetTypeData(ATypeInfo)^.OrdType of
  1105. otUByte: result.FData.FAsSByte := ShortInt(PBoolean(ABuffer)^);
  1106. otUWord: result.FData.FAsUWord := Byte(PBoolean16(ABuffer)^);
  1107. otULong: result.FData.FAsULong := SmallInt(PBoolean32(ABuffer)^);
  1108. otUQWord: result.FData.FAsUInt64 := QWord(PBoolean64(ABuffer)^);
  1109. otSByte: result.FData.FAsSByte := Word(PByteBool(ABuffer)^);
  1110. otSWord: result.FData.FAsSWord := LongInt(PWordBool(ABuffer)^);
  1111. otSLong: result.FData.FAsSLong := LongWord(PLongBool(ABuffer)^);
  1112. otSQWord: result.FData.FAsSInt64 := Int64(PQWordBool(ABuffer)^);
  1113. end;
  1114. end;
  1115. tkFloat : begin
  1116. case GetTypeData(ATypeInfo)^.FloatType of
  1117. ftCurr : result.FData.FAsCurr := PCurrency(ABuffer)^;
  1118. ftSingle : result.FData.FAsSingle := PSingle(ABuffer)^;
  1119. ftDouble : result.FData.FAsDouble := PDouble(ABuffer)^;
  1120. ftExtended: result.FData.FAsExtended := PExtended(ABuffer)^;
  1121. ftComp : result.FData.FAsComp := PComp(ABuffer)^;
  1122. end;
  1123. end;
  1124. else
  1125. raise Exception.CreateFmt(SErrUnableToGetValueForType,[ATypeInfo^.Name]);
  1126. end;
  1127. end;
  1128. {$ifndef NoGenericMethods}
  1129. generic class function TValue.From<T>(constref aValue: T): TValue;
  1130. begin
  1131. TValue.Make(@aValue, System.TypeInfo(T), Result);
  1132. end;
  1133. {$endif}
  1134. function TValue.GetTypeDataProp: PTypeData;
  1135. begin
  1136. result := GetTypeData(FData.FTypeInfo);
  1137. end;
  1138. function TValue.GetDataSize: SizeInt;
  1139. begin
  1140. if Assigned(FData.FValueData) and (Kind <> tkSString) then
  1141. Result := FData.FValueData.GetDataSize
  1142. else begin
  1143. Result := 0;
  1144. case Kind of
  1145. tkEnumeration,
  1146. tkBool,
  1147. tkInt64,
  1148. tkQWord,
  1149. tkInteger:
  1150. case TypeData^.OrdType of
  1151. otSByte,
  1152. otUByte:
  1153. Result := SizeOf(Byte);
  1154. otSWord,
  1155. otUWord:
  1156. Result := SizeOf(Word);
  1157. otSLong,
  1158. otULong:
  1159. Result := SizeOf(LongWord);
  1160. otSQWord,
  1161. otUQWord:
  1162. Result := SizeOf(QWord);
  1163. end;
  1164. tkChar:
  1165. Result := SizeOf(AnsiChar);
  1166. tkFloat:
  1167. case TypeData^.FloatType of
  1168. ftSingle:
  1169. Result := SizeOf(Single);
  1170. ftDouble:
  1171. Result := SizeOf(Double);
  1172. ftExtended:
  1173. Result := SizeOf(Extended);
  1174. ftComp:
  1175. Result := SizeOf(Comp);
  1176. ftCurr:
  1177. Result := SizeOf(Currency);
  1178. end;
  1179. tkSet:
  1180. Result := TypeData^.SetSize;
  1181. tkMethod:
  1182. Result := SizeOf(TMethod);
  1183. tkSString:
  1184. { ShortString can hold max. 254 characters as [0] is Length and [255] is #0 }
  1185. Result := SizeOf(ShortString) - 2;
  1186. tkVariant:
  1187. Result := SizeOf(Variant);
  1188. tkProcVar:
  1189. Result := SizeOf(CodePointer);
  1190. tkWChar:
  1191. Result := SizeOf(WideChar);
  1192. tkUChar:
  1193. Result := SizeOf(UnicodeChar);
  1194. tkFile:
  1195. { ToDo }
  1196. Result := SizeOf(TTextRec);
  1197. tkAString,
  1198. tkWString,
  1199. tkUString,
  1200. tkInterface,
  1201. tkDynArray,
  1202. tkClass,
  1203. tkHelper,
  1204. tkClassRef,
  1205. tkInterfaceRaw,
  1206. tkPointer:
  1207. Result := SizeOf(Pointer);
  1208. tkObject,
  1209. tkRecord:
  1210. Result := TypeData^.RecSize;
  1211. tkArray:
  1212. Result := TypeData^.ArrayData.Size;
  1213. tkUnknown,
  1214. tkLString:
  1215. Assert(False);
  1216. end;
  1217. end;
  1218. end;
  1219. function TValue.GetTypeInfo: PTypeInfo;
  1220. begin
  1221. result := FData.FTypeInfo;
  1222. end;
  1223. function TValue.GetTypeKind: TTypeKind;
  1224. begin
  1225. if not Assigned(FData.FTypeInfo) then
  1226. Result := tkUnknown
  1227. else
  1228. result := FData.FTypeInfo^.Kind;
  1229. end;
  1230. function TValue.GetIsEmpty: boolean;
  1231. begin
  1232. result := (FData.FTypeInfo=nil) or
  1233. ((Kind in [tkSString, tkObject, tkRecord, tkArray]) and not Assigned(FData.FValueData)) or
  1234. ((Kind in [tkClass, tkClassRef, tkInterfaceRaw]) and not Assigned(FData.FAsPointer));
  1235. end;
  1236. function TValue.IsArray: boolean;
  1237. begin
  1238. result := kind in [tkArray, tkDynArray];
  1239. end;
  1240. function TValue.AsString: string;
  1241. begin
  1242. if System.GetTypeKind(String) = tkUString then
  1243. Result := String(AsUnicodeString)
  1244. else
  1245. Result := String(AsAnsiString);
  1246. end;
  1247. function TValue.AsUnicodeString: UnicodeString;
  1248. begin
  1249. if (Kind in [tkSString, tkAString, tkUString, tkWString]) and not Assigned(FData.FValueData) then
  1250. Result := ''
  1251. else
  1252. case Kind of
  1253. tkSString:
  1254. Result := UnicodeString(PShortString(FData.FValueData.GetReferenceToRawData)^);
  1255. tkAString:
  1256. Result := UnicodeString(PAnsiString(FData.FValueData.GetReferenceToRawData)^);
  1257. tkWString:
  1258. Result := UnicodeString(PWideString(FData.FValueData.GetReferenceToRawData)^);
  1259. tkUString:
  1260. Result := UnicodeString(PUnicodeString(FData.FValueData.GetReferenceToRawData)^);
  1261. else
  1262. raise EInvalidCast.Create(SErrInvalidTypecast);
  1263. end;
  1264. end;
  1265. function TValue.AsAnsiString: AnsiString;
  1266. begin
  1267. if (Kind in [tkSString, tkAString, tkUString, tkWString]) and not Assigned(FData.FValueData) then
  1268. Result := ''
  1269. else
  1270. case Kind of
  1271. tkSString:
  1272. Result := AnsiString(PShortString(FData.FValueData.GetReferenceToRawData)^);
  1273. tkAString:
  1274. Result := AnsiString(PAnsiString(FData.FValueData.GetReferenceToRawData)^);
  1275. tkWString:
  1276. Result := AnsiString(PWideString(FData.FValueData.GetReferenceToRawData)^);
  1277. tkUString:
  1278. Result := AnsiString(PUnicodeString(FData.FValueData.GetReferenceToRawData)^);
  1279. else
  1280. raise EInvalidCast.Create(SErrInvalidTypecast);
  1281. end;
  1282. end;
  1283. function TValue.AsExtended: Extended;
  1284. begin
  1285. if Kind = tkFloat then
  1286. begin
  1287. case TypeData^.FloatType of
  1288. ftSingle : result := FData.FAsSingle;
  1289. ftDouble : result := FData.FAsDouble;
  1290. ftExtended : result := FData.FAsExtended;
  1291. else
  1292. raise EInvalidCast.Create(SErrInvalidTypecast);
  1293. end;
  1294. end
  1295. else
  1296. raise EInvalidCast.Create(SErrInvalidTypecast);
  1297. end;
  1298. function TValue.AsObject: TObject;
  1299. begin
  1300. if IsObject or (IsClass and not Assigned(FData.FAsObject)) then
  1301. result := TObject(FData.FAsObject)
  1302. else
  1303. raise EInvalidCast.Create(SErrInvalidTypecast);
  1304. end;
  1305. function TValue.IsObject: boolean;
  1306. begin
  1307. result := (Kind = tkClass) or ((Kind = tkUnknown) and not Assigned(FData.FAsObject));
  1308. end;
  1309. function TValue.IsClass: boolean;
  1310. begin
  1311. result := (Kind = tkClassRef) or ((Kind in [tkClass,tkUnknown]) and not Assigned(FData.FAsObject));
  1312. end;
  1313. function TValue.AsClass: TClass;
  1314. begin
  1315. if IsClass then
  1316. result := FData.FAsClass
  1317. else
  1318. raise EInvalidCast.Create(SErrInvalidTypecast);
  1319. end;
  1320. function TValue.IsOrdinal: boolean;
  1321. begin
  1322. result := (Kind in [tkInteger, tkInt64, tkQWord, tkBool]) or
  1323. ((Kind in [tkClass, tkClassRef, tkInterfaceRaw, tkUnknown]) and not Assigned(FData.FAsPointer));
  1324. end;
  1325. function TValue.AsBoolean: boolean;
  1326. begin
  1327. if (Kind = tkBool) then
  1328. case TypeData^.OrdType of
  1329. otSByte: Result := ByteBool(FData.FAsSByte);
  1330. otUByte: Result := Boolean(FData.FAsUByte);
  1331. otSWord: Result := WordBool(FData.FAsSWord);
  1332. otUWord: Result := Boolean16(FData.FAsUWord);
  1333. otSLong: Result := LongBool(FData.FAsSLong);
  1334. otULong: Result := Boolean32(FData.FAsULong);
  1335. otSQWord: Result := QWordBool(FData.FAsSInt64);
  1336. otUQWord: Result := Boolean64(FData.FAsUInt64);
  1337. end
  1338. else
  1339. raise EInvalidCast.Create(SErrInvalidTypecast);
  1340. end;
  1341. function TValue.AsOrdinal: Int64;
  1342. begin
  1343. if IsOrdinal then
  1344. if Kind in [tkClass, tkClassRef, tkInterfaceRaw, tkUnknown] then
  1345. Result := 0
  1346. else
  1347. case TypeData^.OrdType of
  1348. otSByte: Result := FData.FAsSByte;
  1349. otUByte: Result := FData.FAsUByte;
  1350. otSWord: Result := FData.FAsSWord;
  1351. otUWord: Result := FData.FAsUWord;
  1352. otSLong: Result := FData.FAsSLong;
  1353. otULong: Result := FData.FAsULong;
  1354. otSQWord: Result := FData.FAsSInt64;
  1355. otUQWord: Result := FData.FAsUInt64;
  1356. end
  1357. else
  1358. raise EInvalidCast.Create(SErrInvalidTypecast);
  1359. end;
  1360. function TValue.AsCurrency: Currency;
  1361. begin
  1362. if (Kind = tkFloat) and (TypeData^.FloatType=ftCurr) then
  1363. result := FData.FAsCurr
  1364. else
  1365. raise EInvalidCast.Create(SErrInvalidTypecast);
  1366. end;
  1367. function TValue.AsInteger: Integer;
  1368. begin
  1369. if Kind in [tkInteger, tkInt64, tkQWord] then
  1370. case TypeData^.OrdType of
  1371. otSByte: Result := FData.FAsSByte;
  1372. otUByte: Result := FData.FAsUByte;
  1373. otSWord: Result := FData.FAsSWord;
  1374. otUWord: Result := FData.FAsUWord;
  1375. otSLong: Result := FData.FAsSLong;
  1376. otULong: Result := FData.FAsULong;
  1377. otSQWord: Result := FData.FAsSInt64;
  1378. otUQWord: Result := FData.FAsUInt64;
  1379. end
  1380. else
  1381. raise EInvalidCast.Create(SErrInvalidTypecast);
  1382. end;
  1383. function TValue.AsInt64: Int64;
  1384. begin
  1385. if Kind in [tkInteger, tkInt64, tkQWord] then
  1386. case TypeData^.OrdType of
  1387. otSByte: Result := FData.FAsSByte;
  1388. otUByte: Result := FData.FAsUByte;
  1389. otSWord: Result := FData.FAsSWord;
  1390. otUWord: Result := FData.FAsUWord;
  1391. otSLong: Result := FData.FAsSLong;
  1392. otULong: Result := FData.FAsULong;
  1393. otSQWord: Result := FData.FAsSInt64;
  1394. otUQWord: Result := FData.FAsUInt64;
  1395. end;
  1396. end;
  1397. function TValue.AsUInt64: QWord;
  1398. begin
  1399. if Kind in [tkInteger, tkInt64, tkQWord] then
  1400. case TypeData^.OrdType of
  1401. otSByte: Result := FData.FAsSByte;
  1402. otUByte: Result := FData.FAsUByte;
  1403. otSWord: Result := FData.FAsSWord;
  1404. otUWord: Result := FData.FAsUWord;
  1405. otSLong: Result := FData.FAsSLong;
  1406. otULong: Result := FData.FAsULong;
  1407. otSQWord: Result := FData.FAsSInt64;
  1408. otUQWord: Result := FData.FAsUInt64;
  1409. end;
  1410. end;
  1411. function TValue.AsInterface: IInterface;
  1412. begin
  1413. if Kind = tkInterface then
  1414. Result := PInterface(FData.FValueData.GetReferenceToRawData)^
  1415. else if (Kind in [tkClass, tkClassRef, tkUnknown]) and not Assigned(FData.FAsPointer) then
  1416. Result := Nil
  1417. else
  1418. raise EInvalidCast.Create(SErrInvalidTypecast);
  1419. end;
  1420. function TValue.ToString: String;
  1421. begin
  1422. case Kind of
  1423. tkSString,
  1424. tkAString : result := AsString;
  1425. tkInteger : result := IntToStr(AsInteger);
  1426. tkBool : result := BoolToStr(AsBoolean, True);
  1427. else
  1428. result := '';
  1429. end;
  1430. end;
  1431. function TValue.GetArrayLength: SizeInt;
  1432. begin
  1433. if not IsArray then
  1434. raise EInvalidCast.Create(SErrInvalidTypecast);
  1435. if Kind = tkDynArray then
  1436. Result := DynArraySize(PPointer(FData.FValueData.GetReferenceToRawData)^)
  1437. else
  1438. Result := TypeData^.ArrayData.ElCount;
  1439. end;
  1440. function TValue.GetArrayElement(AIndex: SizeInt): TValue;
  1441. var
  1442. data: Pointer;
  1443. eltype: PTypeInfo;
  1444. td: PTypeData;
  1445. begin
  1446. if not IsArray then
  1447. raise EInvalidCast.Create(SErrInvalidTypecast);
  1448. if Kind = tkDynArray then begin
  1449. data := DynArrayIndex(PPointer(FData.FValueData.GetReferenceToRawData)^, [AIndex], FData.FTypeInfo);
  1450. eltype := TypeData^.elType2;
  1451. end else begin
  1452. td := TypeData;
  1453. eltype := td^.ArrayData.ElType;
  1454. data := PByte(FData.FValueData.GetReferenceToRawData) + AIndex * (td^.ArrayData.Size div td^.ArrayData.ElCount);
  1455. end;
  1456. { MakeWithoutCopy? }
  1457. Make(data, eltype, Result);
  1458. end;
  1459. procedure TValue.SetArrayElement(AIndex: SizeInt; constref AValue: TValue);
  1460. var
  1461. data: Pointer;
  1462. eltype: PTypeInfo;
  1463. td, tdv: PTypeData;
  1464. begin
  1465. if not IsArray then
  1466. raise EInvalidCast.Create(SErrInvalidTypecast);
  1467. if Kind = tkDynArray then begin
  1468. data := DynArrayIndex(PPointer(FData.FValueData.GetReferenceToRawData)^, [AIndex], FData.FTypeInfo);
  1469. eltype := TypeData^.elType2;
  1470. end else begin
  1471. td := TypeData;
  1472. eltype := td^.ArrayData.ElType;
  1473. data := PByte(FData.FValueData.GetReferenceToRawData) + AIndex * (td^.ArrayData.Size div td^.ArrayData.ElCount);
  1474. end;
  1475. { maybe we'll later on allow some typecasts, but for now be restrictive }
  1476. if eltype^.Kind <> AValue.Kind then
  1477. raise EInvalidCast.Create(SErrInvalidTypecast);
  1478. td := GetTypeData(eltype);
  1479. tdv := AValue.TypeData;
  1480. if ((eltype^.Kind in [tkInteger, tkBool, tkEnumeration, tkSet]) and (td^.OrdType <> tdv^.OrdType)) or
  1481. ((eltype^.Kind = tkFloat) and (td^.FloatType <> tdv^.FloatType)) then
  1482. raise EInvalidCast.Create(SErrInvalidTypecast);
  1483. if Assigned(AValue.FData.FValueData) and (eltype^.Kind <> tkSString) then
  1484. IntCopy(AValue.FData.FValueData.GetReferenceToRawData, data, eltype)
  1485. else
  1486. Move(AValue.GetReferenceToRawData^, data^, AValue.DataSize);
  1487. end;
  1488. function TValue.IsType(ATypeInfo: PTypeInfo): boolean;
  1489. begin
  1490. result := ATypeInfo = TypeInfo;
  1491. end;
  1492. function TValue.TryAsOrdinal(out AResult: int64): boolean;
  1493. begin
  1494. result := IsOrdinal;
  1495. if result then
  1496. AResult := AsOrdinal;
  1497. end;
  1498. function TValue.GetReferenceToRawData: Pointer;
  1499. begin
  1500. if IsEmpty then
  1501. Result := Nil
  1502. else if Assigned(FData.FValueData) then
  1503. Result := FData.FValueData.GetReferenceToRawData
  1504. else begin
  1505. Result := Nil;
  1506. case Kind of
  1507. tkInteger,
  1508. tkEnumeration,
  1509. tkInt64,
  1510. tkQWord,
  1511. tkBool:
  1512. case TypeData^.OrdType of
  1513. otSByte:
  1514. Result := @FData.FAsSByte;
  1515. otUByte:
  1516. Result := @FData.FAsUByte;
  1517. otSWord:
  1518. Result := @FData.FAsSWord;
  1519. otUWord:
  1520. Result := @FData.FAsUWord;
  1521. otSLong:
  1522. Result := @FData.FAsSLong;
  1523. otULong:
  1524. Result := @FData.FAsULong;
  1525. otSQWord:
  1526. Result := @FData.FAsSInt64;
  1527. otUQWord:
  1528. Result := @FData.FAsUInt64;
  1529. end;
  1530. tkSet: begin
  1531. case TypeData^.OrdType of
  1532. otUByte: begin
  1533. case TypeData^.SetSize of
  1534. 1:
  1535. Result := @FData.FAsUByte;
  1536. 2:
  1537. Result := @FData.FAsUWord;
  1538. 3, 4:
  1539. Result := @FData.FAsULong;
  1540. 5..8:
  1541. Result := @FData.FAsUInt64;
  1542. else
  1543. { this should have gone through FAsValueData :/ }
  1544. Result := Nil;
  1545. end;
  1546. end;
  1547. otUWord:
  1548. Result := @FData.FAsUWord;
  1549. otULong:
  1550. Result := @FData.FAsULong;
  1551. else
  1552. Result := Nil;
  1553. end;
  1554. end;
  1555. tkChar:
  1556. Result := @FData.FAsUByte;
  1557. tkFloat:
  1558. case TypeData^.FloatType of
  1559. ftSingle:
  1560. Result := @FData.FAsSingle;
  1561. ftDouble:
  1562. Result := @FData.FAsDouble;
  1563. ftExtended:
  1564. Result := @FData.FAsExtended;
  1565. ftComp:
  1566. Result := @FData.FAsComp;
  1567. ftCurr:
  1568. Result := @FData.FAsCurr;
  1569. end;
  1570. tkMethod:
  1571. Result := @FData.FAsMethod;
  1572. tkClass:
  1573. Result := @FData.FAsObject;
  1574. tkWChar:
  1575. Result := @FData.FAsUWord;
  1576. tkInterfaceRaw:
  1577. Result := @FData.FAsPointer;
  1578. tkProcVar:
  1579. Result := @FData.FAsMethod.Code;
  1580. tkUChar:
  1581. Result := @FData.FAsUWord;
  1582. tkFile:
  1583. Result := @FData.FAsPointer;
  1584. tkClassRef:
  1585. Result := @FData.FAsClass;
  1586. tkPointer:
  1587. Result := @FData.FAsPointer;
  1588. tkVariant,
  1589. tkDynArray,
  1590. tkArray,
  1591. tkObject,
  1592. tkRecord,
  1593. tkInterface,
  1594. tkSString,
  1595. tkLString,
  1596. tkAString,
  1597. tkUString,
  1598. tkWString:
  1599. Assert(false, 'Managed/complex type not handled through IValueData');
  1600. end;
  1601. end;
  1602. end;
  1603. class operator TValue.:=(const AValue: String): TValue;
  1604. begin
  1605. Make(@AValue, System.TypeInfo(AValue), Result);
  1606. end;
  1607. class operator TValue.:=(AValue: LongInt): TValue;
  1608. begin
  1609. Make(@AValue, System.TypeInfo(AValue), Result);
  1610. end;
  1611. class operator TValue.:=(AValue: Single): TValue;
  1612. begin
  1613. Make(@AValue, System.TypeInfo(AValue), Result);
  1614. end;
  1615. class operator TValue.:=(AValue: Double): TValue;
  1616. begin
  1617. Make(@AValue, System.TypeInfo(AValue), Result);
  1618. end;
  1619. {$ifdef FPC_HAS_TYPE_EXTENDED}
  1620. class operator TValue.:=(AValue: Extended): TValue;
  1621. begin
  1622. Make(@AValue, System.TypeInfo(AValue), Result);
  1623. end;
  1624. {$endif}
  1625. class operator TValue.:=(AValue: Currency): TValue;
  1626. begin
  1627. Make(@AValue, System.TypeInfo(AValue), Result);
  1628. end;
  1629. class operator TValue.:=(AValue: Int64): TValue;
  1630. begin
  1631. Make(@AValue, System.TypeInfo(AValue), Result);
  1632. end;
  1633. class operator TValue.:=(AValue: QWord): TValue;
  1634. begin
  1635. Make(@AValue, System.TypeInfo(AValue), Result);
  1636. end;
  1637. class operator TValue.:=(AValue: TObject): TValue;
  1638. begin
  1639. Make(@AValue, System.TypeInfo(AValue), Result);
  1640. end;
  1641. class operator TValue.:=(AValue: TClass): TValue;
  1642. begin
  1643. Make(@AValue, System.TypeInfo(AValue), Result);
  1644. end;
  1645. class operator TValue.:=(AValue: Boolean): TValue;
  1646. begin
  1647. Make(@AValue, System.TypeInfo(AValue), Result);
  1648. end;
  1649. { TRttiParameter }
  1650. function TRttiParameter.ToString: String;
  1651. var
  1652. f: TParamFlags;
  1653. n: String;
  1654. t: TRttiType;
  1655. begin
  1656. if FString = '' then begin
  1657. f := Flags;
  1658. if pfVar in f then
  1659. FString := 'var'
  1660. else if pfConst in f then
  1661. FString := 'const'
  1662. else if pfOut in f then
  1663. FString := 'out'
  1664. else if pfConstRef in f then
  1665. FString := 'constref';
  1666. if FString <> '' then
  1667. FString := FString + ' ';
  1668. n := Name;
  1669. if n = '' then
  1670. n := '<unknown>';
  1671. FString := FString + n;
  1672. t := ParamType;
  1673. if Assigned(t) then begin
  1674. FString := FString + ': ';
  1675. if pfArray in flags then
  1676. FString := 'array of ';
  1677. FString := FString + t.Name;
  1678. end;
  1679. end;
  1680. Result := FString;
  1681. end;
  1682. { TRttiMethod }
  1683. function TRttiMethod.GetHasExtendedInfo: Boolean;
  1684. begin
  1685. Result := False;
  1686. end;
  1687. function TRttiMethod.ToString: String;
  1688. var
  1689. ret: TRttiType;
  1690. n: String;
  1691. params: specialize TArray<TRttiParameter>;
  1692. i: LongInt;
  1693. begin
  1694. if FString = '' then begin
  1695. n := Name;
  1696. if n = '' then
  1697. n := '<unknown>';
  1698. if not HasExtendedInfo then begin
  1699. FString := 'method ' + n;
  1700. end else begin
  1701. ret := ReturnType;
  1702. if IsClassMethod then
  1703. FString := 'class ';
  1704. if IsConstructor then
  1705. FString := FString + 'constructor'
  1706. else if IsDestructor then
  1707. FString := FString + 'destructor'
  1708. else if Assigned(ret) then
  1709. FString := FString + 'function'
  1710. else
  1711. FString := FString + 'procedure';
  1712. FString := FString + ' ' + n;
  1713. params := GetParameters;
  1714. if Length(params) > 0 then begin
  1715. FString := FString + '(';
  1716. for i := 0 to High(params) do begin
  1717. if i > 0 then
  1718. FString := FString + '; ';
  1719. FString := FString + params[i].ToString;
  1720. end;
  1721. FString := FString + ')';
  1722. end;
  1723. if Assigned(ret) then
  1724. FString := FString + ': ' + ret.Name;
  1725. if IsStatic then
  1726. FString := FString + '; static';
  1727. end;
  1728. end;
  1729. Result := FString;
  1730. end;
  1731. { TRttiStringType }
  1732. function TRttiStringType.GetStringKind: TRttiStringKind;
  1733. begin
  1734. case TypeKind of
  1735. tkSString : result := skShortString;
  1736. tkLString : result := skAnsiString;
  1737. tkAString : result := skAnsiString;
  1738. tkUString : result := skUnicodeString;
  1739. tkWString : result := skWideString;
  1740. end;
  1741. end;
  1742. { TRttiInterfaceType }
  1743. function TRttiInterfaceType.GetBaseType: TRttiType;
  1744. begin
  1745. Result := GetIntfBaseType;
  1746. end;
  1747. function TRttiInterfaceType.GetGUIDStr: String;
  1748. begin
  1749. Result := GUIDToString(GUID);
  1750. end;
  1751. { TRttiInstanceType }
  1752. function TRttiInstanceType.GetMetaClassType: TClass;
  1753. begin
  1754. result := FTypeData^.ClassType;
  1755. end;
  1756. function TRttiInstanceType.GetDeclaringUnitName: string;
  1757. begin
  1758. result := FTypeData^.UnitName;
  1759. end;
  1760. function TRttiInstanceType.GetBaseType: TRttiType;
  1761. var
  1762. AContext: TRttiContext;
  1763. begin
  1764. AContext := TRttiContext.Create;
  1765. try
  1766. result := AContext.GetType(FTypeData^.ParentInfo);
  1767. finally
  1768. AContext.Free;
  1769. end;
  1770. end;
  1771. function TRttiInstanceType.GetIsInstance: boolean;
  1772. begin
  1773. Result:=True;
  1774. end;
  1775. function TRttiInstanceType.GetTypeSize: integer;
  1776. begin
  1777. Result:=sizeof(TObject);
  1778. end;
  1779. function TRttiInstanceType.GetProperties: specialize TArray<TRttiProperty>;
  1780. var
  1781. TypeInfo: PTypeInfo;
  1782. TypeRttiType: TRttiType;
  1783. TD: PTypeData;
  1784. PPD: PPropData;
  1785. TP: PPropInfo;
  1786. Count: longint;
  1787. obj: TRttiObject;
  1788. begin
  1789. if not FPropertiesResolved then
  1790. begin
  1791. TypeInfo := FTypeInfo;
  1792. // Get the total properties count
  1793. SetLength(FProperties,FTypeData^.PropCount);
  1794. TypeRttiType:= self;
  1795. repeat
  1796. TD:=GetTypeData(TypeInfo);
  1797. // published properties count for this object
  1798. // skip the attribute-info if available
  1799. PPD := PClassData(TD)^.PropertyTable;
  1800. Count:=PPD^.PropCount;
  1801. // Now point TP to first propinfo record.
  1802. TP:=PPropInfo(@PPD^.PropList);
  1803. While Count>0 do
  1804. begin
  1805. // Don't overwrite properties with the same name
  1806. if FProperties[TP^.NameIndex]=nil then begin
  1807. obj := GRttiPool.GetByHandle(TP);
  1808. if Assigned(obj) then
  1809. FProperties[TP^.NameIndex] := obj as TRttiProperty
  1810. else begin
  1811. FProperties[TP^.NameIndex] := TRttiProperty.Create(TypeRttiType, TP);
  1812. GRttiPool.AddObject(FProperties[TP^.NameIndex]);
  1813. end;
  1814. end;
  1815. // Point to TP next propinfo record.
  1816. // Located at Name[Length(Name)+1] !
  1817. TP:=TP^.Next;
  1818. Dec(Count);
  1819. end;
  1820. TypeInfo:=TD^.Parentinfo;
  1821. TypeRttiType:= GRttiPool.GetType(TypeInfo);
  1822. until TypeInfo=nil;
  1823. end;
  1824. result := FProperties;
  1825. end;
  1826. { TRttiMember }
  1827. function TRttiMember.GetVisibility: TMemberVisibility;
  1828. begin
  1829. result := mvPublished;
  1830. end;
  1831. constructor TRttiMember.create(AParent: TRttiType);
  1832. begin
  1833. inherited create();
  1834. FParent := AParent;
  1835. end;
  1836. { TRttiProperty }
  1837. function TRttiProperty.GetPropertyType: TRttiType;
  1838. begin
  1839. result := GRttiPool.GetType(FPropInfo^.PropType);
  1840. end;
  1841. function TRttiProperty.GetIsReadable: boolean;
  1842. begin
  1843. result := assigned(FPropInfo^.GetProc);
  1844. end;
  1845. function TRttiProperty.GetIsWritable: boolean;
  1846. begin
  1847. result := assigned(FPropInfo^.SetProc);
  1848. end;
  1849. function TRttiProperty.GetVisibility: TMemberVisibility;
  1850. begin
  1851. // At this moment only pulished rtti-property-info is supported by fpc
  1852. result := mvPublished;
  1853. end;
  1854. function TRttiProperty.GetName: string;
  1855. begin
  1856. Result:=FPropInfo^.Name;
  1857. end;
  1858. function TRttiProperty.GetHandle: Pointer;
  1859. begin
  1860. Result := FPropInfo;
  1861. end;
  1862. constructor TRttiProperty.create(AParent: TRttiType; APropInfo: PPropInfo);
  1863. begin
  1864. inherited create(AParent);
  1865. FPropInfo := APropInfo;
  1866. end;
  1867. function TRttiProperty.GetValue(Instance: pointer): TValue;
  1868. procedure ValueFromBool(value: Int64);
  1869. var
  1870. b8: Boolean;
  1871. b16: Boolean16;
  1872. b32: Boolean32;
  1873. bb: ByteBool;
  1874. bw: WordBool;
  1875. bl: LongBool;
  1876. td: PTypeData;
  1877. p: Pointer;
  1878. begin
  1879. td := GetTypeData(FPropInfo^.PropType);
  1880. case td^.OrdType of
  1881. otUByte:
  1882. begin
  1883. b8 := Boolean(value);
  1884. p := @b8;
  1885. end;
  1886. otUWord:
  1887. begin
  1888. b16 := Boolean16(value);
  1889. p := @b16;
  1890. end;
  1891. otULong:
  1892. begin
  1893. b32 := Boolean32(value);
  1894. p := @b32;
  1895. end;
  1896. otSByte:
  1897. begin
  1898. bb := ByteBool(value);
  1899. p := @bb;
  1900. end;
  1901. otSWord:
  1902. begin
  1903. bw := WordBool(value);
  1904. p := @bw;
  1905. end;
  1906. otSLong:
  1907. begin
  1908. bl := LongBool(value);
  1909. p := @bl;
  1910. end;
  1911. end;
  1912. TValue.Make(p, FPropInfo^.PropType, result);
  1913. end;
  1914. procedure ValueFromInt(value: Int64);
  1915. var
  1916. i8: UInt8;
  1917. i16: UInt16;
  1918. i32: UInt32;
  1919. td: PTypeData;
  1920. p: Pointer;
  1921. begin
  1922. td := GetTypeData(FPropInfo^.PropType);
  1923. case td^.OrdType of
  1924. otUByte,
  1925. otSByte:
  1926. begin
  1927. i8 := value;
  1928. p := @i8;
  1929. end;
  1930. otUWord,
  1931. otSWord:
  1932. begin
  1933. i16 := value;
  1934. p := @i16;
  1935. end;
  1936. otULong,
  1937. otSLong:
  1938. begin
  1939. i32 := value;
  1940. p := @i32;
  1941. end;
  1942. end;
  1943. TValue.Make(p, FPropInfo^.PropType, result);
  1944. end;
  1945. var
  1946. s: string;
  1947. ss: ShortString;
  1948. i: int64;
  1949. c: Char;
  1950. wc: WideChar;
  1951. begin
  1952. case FPropinfo^.PropType^.Kind of
  1953. tkSString:
  1954. begin
  1955. ss := GetStrProp(TObject(Instance), FPropInfo);
  1956. TValue.Make(@ss, FPropInfo^.PropType, result);
  1957. end;
  1958. tkAString:
  1959. begin
  1960. s := GetStrProp(TObject(Instance), FPropInfo);
  1961. TValue.Make(@s, FPropInfo^.PropType, result);
  1962. end;
  1963. tkBool:
  1964. begin
  1965. i := GetOrdProp(TObject(Instance), FPropInfo);
  1966. ValueFromBool(i);
  1967. end;
  1968. tkInteger:
  1969. begin
  1970. i := GetOrdProp(TObject(Instance), FPropInfo);
  1971. ValueFromInt(i);
  1972. end;
  1973. tkChar:
  1974. begin
  1975. c := AnsiChar(GetOrdProp(TObject(Instance), FPropInfo));
  1976. TValue.Make(@c, FPropInfo^.PropType, result);
  1977. end;
  1978. tkWChar:
  1979. begin
  1980. wc := WideChar(GetOrdProp(TObject(Instance), FPropInfo));
  1981. TValue.Make(@wc, FPropInfo^.PropType, result);
  1982. end;
  1983. tkInt64,
  1984. tkQWord:
  1985. begin
  1986. i := GetOrdProp(TObject(Instance), FPropInfo);
  1987. TValue.Make(@i, FPropInfo^.PropType, result);
  1988. end;
  1989. else
  1990. result := TValue.Empty;
  1991. end
  1992. end;
  1993. procedure TRttiProperty.SetValue(Instance: pointer; const AValue: TValue);
  1994. begin
  1995. case FPropinfo^.PropType^.Kind of
  1996. tkSString,
  1997. tkAString:
  1998. SetStrProp(TObject(Instance), FPropInfo, AValue.AsString);
  1999. tkInteger,
  2000. tkInt64,
  2001. tkQWord,
  2002. tkChar,
  2003. tkBool,
  2004. tkWChar:
  2005. SetOrdProp(TObject(Instance), FPropInfo, AValue.AsOrdinal);
  2006. else
  2007. raise exception.createFmt(SErrUnableToSetValueForType, [PropertyType.Name]);
  2008. end
  2009. end;
  2010. function TRttiType.GetIsInstance: boolean;
  2011. begin
  2012. result := false;
  2013. end;
  2014. function TRttiType.GetIsManaged: boolean;
  2015. begin
  2016. result := Rtti.IsManaged(FTypeInfo);
  2017. end;
  2018. function TRttiType.GetIsOrdinal: boolean;
  2019. begin
  2020. result := false;
  2021. end;
  2022. function TRttiType.GetIsRecord: boolean;
  2023. begin
  2024. result := false;
  2025. end;
  2026. function TRttiType.GetIsSet: boolean;
  2027. begin
  2028. result := false;
  2029. end;
  2030. function TRttiType.GetAsInstance: TRttiInstanceType;
  2031. begin
  2032. // This is a ridicoulous design, but Delphi-compatible...
  2033. result := TRttiInstanceType(self);
  2034. end;
  2035. function TRttiType.GetBaseType: TRttiType;
  2036. begin
  2037. result := nil;
  2038. end;
  2039. function TRttiType.GetTypeKind: TTypeKind;
  2040. begin
  2041. result := FTypeInfo^.Kind;
  2042. end;
  2043. function TRttiType.GetTypeSize: integer;
  2044. begin
  2045. result := -1;
  2046. end;
  2047. function TRttiType.GetName: string;
  2048. begin
  2049. Result:=FTypeInfo^.Name;
  2050. end;
  2051. function TRttiType.GetHandle: Pointer;
  2052. begin
  2053. Result := FTypeInfo;
  2054. end;
  2055. constructor TRttiType.create(ATypeInfo: PTypeInfo);
  2056. begin
  2057. inherited create();
  2058. FTypeInfo:=ATypeInfo;
  2059. if assigned(FTypeInfo) then
  2060. FTypeData:=GetTypeData(ATypeInfo);
  2061. end;
  2062. function TRttiType.GetProperties: specialize TArray<TRttiProperty>;
  2063. begin
  2064. Result := Nil;
  2065. end;
  2066. function TRttiType.GetProperty(const AName: string): TRttiProperty;
  2067. var
  2068. FPropList: specialize TArray<TRttiProperty>;
  2069. i: Integer;
  2070. begin
  2071. result := nil;
  2072. FPropList := GetProperties;
  2073. for i := 0 to length(FPropList)-1 do
  2074. if sametext(FPropList[i].Name,AName) then
  2075. begin
  2076. result := FPropList[i];
  2077. break;
  2078. end;
  2079. end;
  2080. { TRttiNamedObject }
  2081. function TRttiNamedObject.GetName: string;
  2082. begin
  2083. result := '';
  2084. end;
  2085. { TRttiContext }
  2086. class function TRttiContext.Create: TRttiContext;
  2087. begin
  2088. result.FContextToken := nil;
  2089. end;
  2090. procedure TRttiContext.Free;
  2091. begin
  2092. FContextToken := nil;
  2093. end;
  2094. function TRttiContext.GetType(ATypeInfo: PTypeInfo): TRttiType;
  2095. begin
  2096. if not assigned(FContextToken) then
  2097. FContextToken := TPoolToken.Create;
  2098. result := (FContextToken as IPooltoken).RttiPool.GetType(ATypeInfo);
  2099. end;
  2100. function TRttiContext.GetType(AClass: TClass): TRttiType;
  2101. begin
  2102. if assigned(AClass) then
  2103. result := GetType(PTypeInfo(AClass.ClassInfo))
  2104. else
  2105. result := nil;
  2106. end;
  2107. {function TRttiContext.GetTypes: specialize TArray<TRttiType>;
  2108. begin
  2109. if not assigned(FContextToken) then
  2110. FContextToken := TPoolToken.Create;
  2111. result := (FContextToken as IPooltoken).RttiPool.GetTypes;
  2112. end;}
  2113. initialization
  2114. PoolRefCount := 0;
  2115. InitDefaultFunctionCallManager;
  2116. end.