rtti.pp 53 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901
  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
  139. public
  140. end;
  141. { TRttiNamedObject }
  142. TRttiNamedObject = class(TRttiObject)
  143. protected
  144. function GetName: string; virtual;
  145. public
  146. property Name: string read GetName;
  147. end;
  148. { TRttiType }
  149. TRttiType = class(TRttiNamedObject)
  150. private
  151. FTypeInfo: PTypeInfo;
  152. FPropertiesResolved: boolean;
  153. FProperties: specialize TArray<TRttiProperty>;
  154. function GetAsInstance: TRttiInstanceType;
  155. protected
  156. FTypeData: PTypeData;
  157. function GetName: string; override;
  158. function GetIsInstance: boolean; virtual;
  159. function GetIsManaged: boolean; virtual;
  160. function GetIsOrdinal: boolean; virtual;
  161. function GetIsRecord: boolean; virtual;
  162. function GetIsSet: boolean; virtual;
  163. function GetTypeKind: TTypeKind; virtual;
  164. function GetTypeSize: integer; virtual;
  165. function GetBaseType: TRttiType; virtual;
  166. public
  167. constructor create(ATypeInfo : PTypeInfo);
  168. function GetProperties: specialize TArray<TRttiProperty>;
  169. function GetProperty(const AName: string): TRttiProperty; virtual;
  170. destructor destroy; override;
  171. property IsInstance: boolean read GetIsInstance;
  172. property isManaged: boolean read GetIsManaged;
  173. property IsOrdinal: boolean read GetIsOrdinal;
  174. property IsRecord: boolean read GetIsRecord;
  175. property IsSet: boolean read GetIsSet;
  176. property BaseType: TRttiType read GetBaseType;
  177. property AsInstance: TRttiInstanceType read GetAsInstance;
  178. property TypeKind: TTypeKind read GetTypeKind;
  179. property TypeSize: integer read GetTypeSize;
  180. end;
  181. TRttiStructuredType = class(TRttiType)
  182. end;
  183. { TRttiFloatType }
  184. TRttiFloatType = class(TRttiType)
  185. private
  186. function GetFloatType: TFloatType;
  187. public
  188. property FloatType: TFloatType read GetFloatType;
  189. end;
  190. TRttiStringKind = (skShortString, skAnsiString, skWideString, skUnicodeString);
  191. { TRttiStringType }
  192. TRttiStringType = class(TRttiType)
  193. private
  194. function GetStringKind: TRttiStringKind;
  195. public
  196. property StringKind: TRttiStringKind read GetStringKind;
  197. end;
  198. { TRttiInstanceType }
  199. TRttiInstanceType = class(TRttiStructuredType)
  200. private
  201. function GetDeclaringUnitName: string;
  202. function GetMetaClassType: TClass;
  203. protected
  204. function GetIsInstance: boolean; override;
  205. function GetTypeSize: integer; override;
  206. function GetBaseType: TRttiType; override;
  207. public
  208. property MetaClassType: TClass read GetMetaClassType;
  209. property DeclaringUnitName: string read GetDeclaringUnitName;
  210. end;
  211. { TRttiMember }
  212. TMemberVisibility=(mvPrivate, mvProtected, mvPublic, mvPublished);
  213. TRttiMember = class(TRttiNamedObject)
  214. private
  215. FParent: TRttiType;
  216. protected
  217. function GetVisibility: TMemberVisibility; virtual;
  218. public
  219. constructor create(AParent: TRttiType);
  220. property Visibility: TMemberVisibility read GetVisibility;
  221. property Parent: TRttiType read FParent;
  222. end;
  223. { TRttiProperty }
  224. TRttiProperty = class(TRttiMember)
  225. private
  226. FPropInfo: PPropInfo;
  227. function GetPropertyType: TRttiType;
  228. function GetIsWritable: boolean;
  229. function GetIsReadable: boolean;
  230. protected
  231. function GetVisibility: TMemberVisibility; override;
  232. function GetName: string; override;
  233. public
  234. constructor create(AParent: TRttiType; APropInfo: PPropInfo);
  235. function GetValue(Instance: pointer): TValue;
  236. procedure SetValue(Instance: pointer; const AValue: TValue);
  237. property PropertyType: TRttiType read GetPropertyType;
  238. property IsReadable: boolean read GetIsReadable;
  239. property IsWritable: boolean read GetIsWritable;
  240. property Visibility: TMemberVisibility read GetVisibility;
  241. end;
  242. EInsufficientRtti = class(Exception);
  243. EInvocationError = class(Exception);
  244. ENonPublicType = class(Exception);
  245. TFunctionCallParameter = record
  246. Value: TValue;
  247. ParamFlags: TParamFlags;
  248. ParaLocs: PParameterLocations;
  249. end;
  250. TFunctionCallParameterArray = specialize TArray<TFunctionCallParameter>;
  251. TFunctionCallFlag = (
  252. fcfStatic
  253. );
  254. TFunctionCallFlags = set of TFunctionCallFlag;
  255. TFunctionCallCallback = Pointer;
  256. TFunctionCallProc = procedure(const aArgs: TValueArray; out aResult: TValue; aContext: Pointer);
  257. TFunctionCallMethod = procedure(const aArgs: TValueArray; out aResult: TValue; aContext: Pointer) of object;
  258. TFunctionCallManager = record
  259. Invoke: procedure(CodeAddress: CodePointer; const Args: TFunctionCallParameterArray; CallingConvention: TCallConv;
  260. ResultType: PTypeInfo; out ResultValue: TValue; Flags: TFunctionCallFlags);
  261. CreateCallbackProc: function(aHandler: TFunctionCallProc; aCallConv: TCallConv; aArgs: array of PTypeInfo; aResultType: PTypeInfo; aFlags: TFunctionCallFlags; aContext: Pointer): TFunctionCallCallback;
  262. CreateCallbackMethod: function(aHandler: TFunctionCallMethod; aCallConv: TCallConv; aArgs: array of PTypeInfo; aResultType: PTypeInfo; aFlags: TFunctionCallFlags; aContext: Pointer): TFunctionCallCallback;
  263. FreeCallback: procedure(aCallback: TFunctionCallCallback; aCallConv: TCallConv);
  264. end;
  265. TFunctionCallManagerArray = array[TCallConv] of TFunctionCallManager;
  266. TCallConvSet = set of TCallConv;
  267. procedure SetFunctionCallManager(aCallConv: TCallConv; constref aFuncCallMgr: TFunctionCallManager; out aOldFuncCallMgr: TFunctionCallManager);
  268. procedure SetFunctionCallManager(aCallConv: TCallConv; constref aFuncCallMgr: TFunctionCallManager);
  269. procedure SetFunctionCallManager(aCallConvs: TCallConvSet; constref aFuncCallMgr: TFunctionCallManager; out aOldFuncCallMgrs: TFunctionCallManagerArray);
  270. procedure SetFunctionCallManager(aCallConvs: TCallConvSet; constref aFuncCallMgr: TFunctionCallManager);
  271. procedure SetFunctionCallManagers(aCallConvs: TCallConvSet; constref aFuncCallMgrs: TFunctionCallManagerArray; out aOldFuncCallMgrs: TFunctionCallManagerArray);
  272. procedure SetFunctionCallManagers(aCallConvs: TCallConvSet; constref aFuncCallMgrs: TFunctionCallManagerArray);
  273. procedure SetFunctionCallManagers(constref aFuncCallMgrs: TFunctionCallManagerArray; out aOldFuncCallMgrs: TFunctionCallManagerArray);
  274. procedure SetFunctionCallManagers(constref aFuncCallMgrs: TFunctionCallManagerArray);
  275. procedure GetFunctionCallManager(aCallConv: TCallConv; out aFuncCallMgr: TFunctionCallManager);
  276. procedure GetFunctionCallManagers(aCallConvs: TCallConvSet; out aFuncCallMgrs: TFunctionCallManagerArray);
  277. procedure GetFunctionCallManagers(out aFuncCallMgrs: TFunctionCallManagerArray);
  278. function IsManaged(TypeInfo: PTypeInfo): boolean;
  279. { these resource strings are needed by units implementing function call managers }
  280. resourcestring
  281. SErrInvokeNotImplemented = 'Invoke functionality is not implemented';
  282. SErrInvokeFailed = 'Invoke call failed';
  283. SErrCallbackNotImplented = 'Callback functionality is not implemented';
  284. SErrCallConvNotSupported = 'Calling convention not supported: %s';
  285. SErrTypeKindNotSupported = 'Type kind is not supported: %s';
  286. SErrCallbackHandlerNil = 'Callback handler is Nil';
  287. implementation
  288. type
  289. { TRttiPool }
  290. TRttiPool = class
  291. private
  292. FTypesList: specialize TArray<TRttiType>;
  293. FTypeCount: LongInt;
  294. FLock: TRTLCriticalSection;
  295. public
  296. function GetTypes: specialize TArray<TRttiType>;
  297. function GetType(ATypeInfo: PTypeInfo): TRttiType;
  298. constructor Create;
  299. destructor Destroy; override;
  300. end;
  301. IPooltoken = interface
  302. ['{3CDB3CE9-AB55-CBAA-7B9D-2F3BB1CF5AF8}']
  303. function RttiPool: TRttiPool;
  304. end;
  305. { TPoolToken }
  306. TPoolToken = class(TInterfacedObject, IPooltoken)
  307. public
  308. constructor Create;
  309. destructor Destroy; override;
  310. function RttiPool: TRttiPool;
  311. end;
  312. { TValueDataIntImpl }
  313. TValueDataIntImpl = class(TInterfacedObject, IValueData)
  314. private
  315. FBuffer: Pointer;
  316. FDataSize: SizeInt;
  317. FTypeInfo: PTypeInfo;
  318. FIsCopy: Boolean;
  319. FUseAddRef: Boolean;
  320. public
  321. constructor CreateCopy(ACopyFromBuffer: Pointer; ALen: SizeInt; ATypeInfo: PTypeInfo; AAddRef: Boolean);
  322. constructor CreateRef(AData: Pointer; ATypeInfo: PTypeInfo; AAddRef: Boolean);
  323. destructor Destroy; override;
  324. procedure ExtractRawData(ABuffer: pointer);
  325. procedure ExtractRawDataNoCopy(ABuffer: pointer);
  326. function GetDataSize: SizeInt;
  327. function GetReferenceToRawData: pointer;
  328. end;
  329. resourcestring
  330. SErrUnableToGetValueForType = 'Unable to get value for type %s';
  331. SErrUnableToSetValueForType = 'Unable to set value for type %s';
  332. SErrInvalidTypecast = 'Invalid class typecast';
  333. var
  334. PoolRefCount : integer;
  335. GRttiPool : TRttiPool;
  336. FuncCallMgr: TFunctionCallManagerArray;
  337. procedure NoInvoke(aCodeAddress: CodePointer; const aArgs: TFunctionCallParameterArray; aCallConv: TCallConv;
  338. aResultType: PTypeInfo; out aResultValue: TValue; aFlags: TFunctionCallFlags);
  339. begin
  340. raise ENotImplemented.Create(SErrInvokeNotImplemented);
  341. end;
  342. function NoCreateCallbackProc(aFunc: TFunctionCallProc; aCallConv: TCallConv; aArgs: array of PTypeInfo; aResultType: PTypeInfo; aFlags: TFunctionCallFlags; aContext: Pointer): TFunctionCallCallback;
  343. begin
  344. Result := Nil;
  345. raise ENotImplemented.Create(SErrCallbackNotImplented);
  346. end;
  347. function NoCreateCallbackMethod(aFunc: TFunctionCallMethod; aCallConv: TCallConv; aArgs: array of PTypeInfo; aResultType: PTypeInfo; aFlags: TFunctionCallFlags; aContext: Pointer): TFunctionCallCallback;
  348. begin
  349. Result := Nil;
  350. raise ENotImplemented.Create(SErrCallbackNotImplented);
  351. end;
  352. procedure NoFreeCallback(aCallback: TFunctionCallCallback; aCallConv: TCallConv);
  353. begin
  354. raise ENotImplemented.Create(SErrCallbackNotImplented);
  355. end;
  356. const
  357. NoFunctionCallManager: TFunctionCallManager = (
  358. Invoke: @NoInvoke;
  359. CreateCallbackProc: @NoCreateCallbackProc;
  360. CreateCallbackMethod: @NoCreateCallbackMethod;
  361. FreeCallback: @NoFreeCallback
  362. );
  363. procedure SetFunctionCallManager(aCallConv: TCallConv; constref aFuncCallMgr: TFunctionCallManager;
  364. out aOldFuncCallMgr: TFunctionCallManager);
  365. begin
  366. aOldFuncCallMgr := FuncCallMgr[aCallConv];
  367. FuncCallMgr[aCallConv] := aFuncCallMgr;
  368. end;
  369. procedure SetFunctionCallManager(aCallConv: TCallConv; constref aFuncCallMgr: TFunctionCallManager);
  370. var
  371. dummy: TFunctionCallManager;
  372. begin
  373. SetFunctionCallManager(aCallConv, aFuncCallMgr, dummy);
  374. end;
  375. procedure SetFunctionCallManager(aCallConvs: TCallConvSet; constref aFuncCallMgr: TFunctionCallManager;
  376. out aOldFuncCallMgrs: TFunctionCallManagerArray);
  377. var
  378. cc: TCallConv;
  379. begin
  380. for cc := Low(TCallConv) to High(TCallConv) do
  381. if cc in aCallConvs then begin
  382. aOldFuncCallMgrs[cc] := FuncCallMgr[cc];
  383. FuncCallMgr[cc] := aFuncCallMgr;
  384. end else
  385. aOldFuncCallMgrs[cc] := Default(TFunctionCallManager);
  386. end;
  387. procedure SetFunctionCallManager(aCallConvs: TCallConvSet; constref aFuncCallMgr: TFunctionCallManager);
  388. var
  389. dummy: TFunctionCallManagerArray;
  390. begin
  391. SetFunctionCallManager(aCallConvs, aFuncCallMgr, dummy);
  392. end;
  393. procedure SetFunctionCallManagers(aCallConvs: TCallConvSet; constref aFuncCallMgrs: TFunctionCallManagerArray; out aOldFuncCallMgrs: TFunctionCallManagerArray);
  394. var
  395. cc: TCallConv;
  396. begin
  397. for cc := Low(TCallConv) to High(TCallConv) do
  398. if cc in aCallConvs then begin
  399. aOldFuncCallMgrs[cc] := FuncCallMgr[cc];
  400. FuncCallMgr[cc] := aFuncCallMgrs[cc];
  401. end else
  402. aOldFuncCallMgrs[cc] := Default(TFunctionCallManager);
  403. end;
  404. procedure SetFunctionCallManagers(aCallConvs: TCallConvSet; constref aFuncCallMgrs: TFunctionCallManagerArray);
  405. var
  406. dummy: TFunctionCallManagerArray;
  407. begin
  408. SetFunctionCallManagers(aCallConvs, aFuncCallMgrs, dummy);
  409. end;
  410. procedure SetFunctionCallManagers(constref aFuncCallMgrs: TFunctionCallManagerArray; out aOldFuncCallMgrs: TFunctionCallManagerArray);
  411. begin
  412. aOldFuncCallMgrs := FuncCallMgr;
  413. FuncCallMgr := aFuncCallMgrs;
  414. end;
  415. procedure SetFunctionCallManagers(constref aFuncCallMgrs: TFunctionCallManagerArray);
  416. var
  417. dummy: TFunctionCallManagerArray;
  418. begin
  419. SetFunctionCallManagers(aFuncCallMgrs, dummy);
  420. end;
  421. procedure GetFunctionCallManager(aCallConv: TCallConv; out aFuncCallMgr: TFunctionCallManager);
  422. begin
  423. aFuncCallMgr := FuncCallMgr[aCallConv];
  424. end;
  425. procedure GetFunctionCallManagers(aCallConvs: TCallConvSet; out aFuncCallMgrs: TFunctionCallManagerArray);
  426. var
  427. cc: TCallConv;
  428. begin
  429. for cc := Low(TCallConv) to High(TCallConv) do
  430. if cc in aCallConvs then
  431. aFuncCallMgrs[cc] := FuncCallMgr[cc]
  432. else
  433. aFuncCallMgrs[cc] := Default(TFunctionCallManager);
  434. end;
  435. procedure GetFunctionCallManagers(out aFuncCallMgrs: TFunctionCallManagerArray);
  436. begin
  437. aFuncCallMgrs := FuncCallMgr;
  438. end;
  439. procedure InitDefaultFunctionCallManager;
  440. var
  441. cc: TCallConv;
  442. begin
  443. for cc := Low(TCallConv) to High(TCallConv) do
  444. FuncCallMgr[cc] := NoFunctionCallManager;
  445. end;
  446. function IsManaged(TypeInfo: PTypeInfo): boolean;
  447. begin
  448. if Assigned(TypeInfo) then
  449. case TypeInfo^.Kind of
  450. tkAString,
  451. tkLString,
  452. tkWString,
  453. tkUString,
  454. tkInterface,
  455. tkVariant,
  456. tkDynArray : Result := true;
  457. tkArray : Result := IsManaged(GetTypeData(TypeInfo)^.ArrayData.ElType);
  458. tkRecord,
  459. tkObject :
  460. with GetTypeData(TypeInfo)^.RecInitData^ do
  461. Result := (ManagedFieldCount > 0) or Assigned(ManagementOp);
  462. else
  463. Result := false;
  464. end
  465. else
  466. Result := false;
  467. end;
  468. { TRttiPool }
  469. function TRttiPool.GetTypes: specialize TArray<TRttiType>;
  470. begin
  471. if not Assigned(FTypesList) then
  472. Exit(Nil);
  473. {$ifdef FPC_HAS_FEATURE_THREADING}
  474. EnterCriticalsection(FLock);
  475. {$endif}
  476. Result := Copy(FTypesList, 0, FTypeCount);
  477. {$ifdef FPC_HAS_FEATURE_THREADING}
  478. LeaveCriticalsection(FLock);
  479. {$endif}
  480. end;
  481. function TRttiPool.GetType(ATypeInfo: PTypeInfo): TRttiType;
  482. var
  483. i: integer;
  484. begin
  485. if not Assigned(ATypeInfo) then
  486. Exit(Nil);
  487. {$ifdef FPC_HAS_FEATURE_THREADING}
  488. EnterCriticalsection(FLock);
  489. {$endif}
  490. Result := Nil;
  491. for i := 0 to FTypeCount - 1 do
  492. begin
  493. if FTypesList[i].FTypeInfo = ATypeInfo then
  494. begin
  495. Result := FTypesList[i];
  496. Break;
  497. end;
  498. end;
  499. if not Assigned(Result) then
  500. begin
  501. if FTypeCount = Length(FTypesList) then
  502. begin
  503. SetLength(FTypesList, FTypeCount * 2);
  504. end;
  505. case ATypeInfo^.Kind of
  506. tkClass : Result := TRttiInstanceType.Create(ATypeInfo);
  507. tkSString,
  508. tkLString,
  509. tkAString,
  510. tkUString,
  511. tkWString : Result := TRttiStringType.Create(ATypeInfo);
  512. tkFloat : Result := TRttiFloatType.Create(ATypeInfo);
  513. else
  514. Result := TRttiType.Create(ATypeInfo);
  515. end;
  516. FTypesList[FTypeCount] := Result;
  517. Inc(FTypeCount);
  518. end;
  519. {$ifdef FPC_HAS_FEATURE_THREADING}
  520. LeaveCriticalsection(FLock);
  521. {$endif}
  522. end;
  523. constructor TRttiPool.Create;
  524. begin
  525. {$ifdef FPC_HAS_FEATURE_THREADING}
  526. InitCriticalSection(FLock);
  527. {$endif}
  528. SetLength(FTypesList, 32);
  529. end;
  530. destructor TRttiPool.Destroy;
  531. var
  532. i: LongInt;
  533. begin
  534. for i := 0 to length(FTypesList)-1 do
  535. FTypesList[i].Free;
  536. {$ifdef FPC_HAS_FEATURE_THREADING}
  537. DoneCriticalsection(FLock);
  538. {$endif}
  539. inherited Destroy;
  540. end;
  541. { TPoolToken }
  542. constructor TPoolToken.Create;
  543. begin
  544. inherited Create;
  545. if InterlockedIncrement(PoolRefCount)=1 then
  546. GRttiPool := TRttiPool.Create;
  547. end;
  548. destructor TPoolToken.Destroy;
  549. begin
  550. if InterlockedDecrement(PoolRefCount)=0 then
  551. GRttiPool.Free;
  552. inherited;
  553. end;
  554. function TPoolToken.RttiPool: TRttiPool;
  555. begin
  556. result := GRttiPool;
  557. end;
  558. { TValueDataIntImpl }
  559. procedure IntFinalize(APointer, ATypeInfo: Pointer);
  560. external name 'FPC_FINALIZE';
  561. procedure IntInitialize(APointer, ATypeInfo: Pointer);
  562. external name 'FPC_INITIALIZE';
  563. procedure IntAddRef(APointer, ATypeInfo: Pointer);
  564. external name 'FPC_ADDREF';
  565. function IntCopy(ASource, ADest, ATypeInfo: Pointer): SizeInt;
  566. external name 'FPC_COPY';
  567. constructor TValueDataIntImpl.CreateCopy(ACopyFromBuffer: Pointer; ALen: SizeInt; ATypeInfo: PTypeInfo; AAddRef: Boolean);
  568. begin
  569. FTypeInfo := ATypeInfo;
  570. FDataSize:=ALen;
  571. if ALen>0 then
  572. begin
  573. Getmem(FBuffer,FDataSize);
  574. if Assigned(ACopyFromBuffer) then
  575. system.move(ACopyFromBuffer^,FBuffer^,FDataSize)
  576. else
  577. FillChar(FBuffer^, FDataSize, 0);
  578. end;
  579. FIsCopy := True;
  580. FUseAddRef := AAddRef;
  581. if AAddRef and (ALen > 0) then begin
  582. if Assigned(ACopyFromBuffer) then
  583. IntAddRef(FBuffer, FTypeInfo)
  584. else
  585. IntInitialize(FBuffer, FTypeInfo);
  586. end;
  587. end;
  588. constructor TValueDataIntImpl.CreateRef(AData: Pointer; ATypeInfo: PTypeInfo; AAddRef: Boolean);
  589. begin
  590. FTypeInfo := ATypeInfo;
  591. FDataSize := SizeOf(Pointer);
  592. if Assigned(AData) then
  593. FBuffer := PPointer(AData)^
  594. else
  595. FBuffer := Nil;
  596. FIsCopy := False;
  597. FUseAddRef := AAddRef;
  598. if AAddRef and Assigned(AData) then
  599. IntAddRef(@FBuffer, FTypeInfo);
  600. end;
  601. destructor TValueDataIntImpl.Destroy;
  602. begin
  603. if Assigned(FBuffer) then begin
  604. if FUseAddRef then
  605. if FIsCopy then
  606. IntFinalize(FBuffer, FTypeInfo)
  607. else
  608. IntFinalize(@FBuffer, FTypeInfo);
  609. if FIsCopy then
  610. Freemem(FBuffer);
  611. end;
  612. inherited Destroy;
  613. end;
  614. procedure TValueDataIntImpl.ExtractRawData(ABuffer: pointer);
  615. begin
  616. if FDataSize = 0 then
  617. Exit;
  618. if FIsCopy then
  619. System.Move(FBuffer^, ABuffer^, FDataSize)
  620. else
  621. System.Move(FBuffer{!}, ABuffer^, FDataSize);
  622. if FUseAddRef then
  623. IntAddRef(ABuffer, FTypeInfo);
  624. end;
  625. procedure TValueDataIntImpl.ExtractRawDataNoCopy(ABuffer: pointer);
  626. begin
  627. if FDataSize = 0 then
  628. Exit;
  629. if FIsCopy then
  630. system.move(FBuffer^, ABuffer^, FDataSize)
  631. else
  632. System.Move(FBuffer{!}, ABuffer^, FDataSize);
  633. end;
  634. function TValueDataIntImpl.GetDataSize: SizeInt;
  635. begin
  636. result := FDataSize;
  637. end;
  638. function TValueDataIntImpl.GetReferenceToRawData: pointer;
  639. begin
  640. if FIsCopy then
  641. result := FBuffer
  642. else
  643. result := @FBuffer;
  644. end;
  645. { TRttiFloatType }
  646. function TRttiFloatType.GetFloatType: TFloatType;
  647. begin
  648. result := FTypeData^.FloatType;
  649. end;
  650. { TValue }
  651. class function TValue.Empty: TValue;
  652. begin
  653. result.FData.FTypeInfo := nil;
  654. {$if SizeOf(TMethod) > SizeOf(QWord)}
  655. Result.FData.FAsMethod.Code := Nil;
  656. Result.FData.FAsMethod.Data := Nil;
  657. {$else}
  658. Result.FData.FAsUInt64 := 0;
  659. {$endif}
  660. end;
  661. class procedure TValue.Make(ABuffer: pointer; ATypeInfo: PTypeInfo; out result: TValue);
  662. type
  663. PBoolean16 = ^Boolean16;
  664. PBoolean32 = ^Boolean32;
  665. PBoolean64 = ^Boolean64;
  666. PByteBool = ^ByteBool;
  667. PQWordBool = ^QWordBool;
  668. PMethod = ^TMethod;
  669. var
  670. td: PTypeData;
  671. size: SizeInt;
  672. begin
  673. result.FData.FTypeInfo:=ATypeInfo;
  674. { resets the whole variant part; FValueData is already Nil }
  675. {$if SizeOf(TMethod) > SizeOf(QWord)}
  676. Result.FData.FAsMethod.Code := Nil;
  677. Result.FData.FAsMethod.Data := Nil;
  678. {$else}
  679. Result.FData.FAsUInt64 := 0;
  680. {$endif}
  681. if not Assigned(ATypeInfo) then
  682. Exit;
  683. { first handle those types that need a TValueData implementation }
  684. case ATypeInfo^.Kind of
  685. tkSString : begin
  686. if Assigned(ABuffer) then
  687. size := Length(PShortString(ABuffer)^) + 1
  688. else
  689. size := 256;
  690. result.FData.FValueData := TValueDataIntImpl.CreateCopy(ABuffer, size, ATypeInfo, True);
  691. end;
  692. tkWString,
  693. tkUString,
  694. tkAString : result.FData.FValueData := TValueDataIntImpl.CreateRef(ABuffer, ATypeInfo, True);
  695. tkDynArray : result.FData.FValueData := TValueDataIntImpl.CreateRef(ABuffer, ATypeInfo, True);
  696. tkArray : result.FData.FValueData := TValueDataIntImpl.CreateCopy(ABuffer, Result.TypeData^.ArrayData.Size, ATypeInfo, False);
  697. tkObject,
  698. tkRecord : result.FData.FValueData := TValueDataIntImpl.CreateCopy(ABuffer, Result.TypeData^.RecSize, ATypeInfo, False);
  699. tkInterface: result.FData.FValueData := TValueDataIntImpl.CreateRef(ABuffer, ATypeInfo, True);
  700. end;
  701. if not Assigned(ABuffer) then
  702. Exit;
  703. { now handle those that are happy with the variant part of FData }
  704. case ATypeInfo^.Kind of
  705. tkSString,
  706. tkWString,
  707. tkUString,
  708. tkAString,
  709. tkDynArray,
  710. tkArray,
  711. tkObject,
  712. tkRecord,
  713. tkInterface:
  714. { ignore }
  715. ;
  716. tkClass : result.FData.FAsObject := PPointer(ABuffer)^;
  717. tkClassRef : result.FData.FAsClass := PClass(ABuffer)^;
  718. tkInterfaceRaw : result.FData.FAsPointer := PPointer(ABuffer)^;
  719. tkInt64 : result.FData.FAsSInt64 := PInt64(ABuffer)^;
  720. tkQWord : result.FData.FAsUInt64 := PQWord(ABuffer)^;
  721. tkProcVar : result.FData.FAsMethod.Code := PCodePointer(ABuffer)^;
  722. tkMethod : result.FData.FAsMethod := PMethod(ABuffer)^;
  723. tkPointer : result.FData.FAsPointer := PPointer(ABuffer)^;
  724. tkSet : begin
  725. td := GetTypeData(ATypeInfo);
  726. case td^.OrdType of
  727. otUByte: begin
  728. { this can either really be 1 Byte or a set > 32-bit, so
  729. check the underlying type }
  730. if not (td^.CompType^.Kind in [tkInteger,tkEnumeration]) then
  731. raise Exception.CreateFmt(SErrUnableToGetValueForType,[ATypeInfo^.Name]);
  732. case td^.SetSize of
  733. 0, 1:
  734. Result.FData.FAsUByte := PByte(ABuffer)^;
  735. { these two cases shouldn't happen, but better safe than sorry... }
  736. 2:
  737. Result.FData.FAsUWord := PWord(ABuffer)^;
  738. 3, 4:
  739. Result.FData.FAsULong := PLongWord(ABuffer)^;
  740. { maybe we should also allow storage as otUQWord? }
  741. 5..8:
  742. Result.FData.FAsUInt64 := PQWord(ABuffer)^;
  743. else
  744. Result.FData.FValueData := TValueDataIntImpl.CreateCopy(ABuffer, td^.SetSize, ATypeInfo, False);
  745. end;
  746. end;
  747. otUWord:
  748. Result.FData.FAsUWord := PWord(ABuffer)^;
  749. otULong:
  750. Result.FData.FAsULong := PLongWord(ABuffer)^;
  751. else
  752. { ehm... Panic? }
  753. raise Exception.CreateFmt(SErrUnableToGetValueForType,[ATypeInfo^.Name]);
  754. end;
  755. end;
  756. tkEnumeration,
  757. tkInteger : begin
  758. case GetTypeData(ATypeInfo)^.OrdType of
  759. otSByte: result.FData.FAsSByte := PShortInt(ABuffer)^;
  760. otUByte: result.FData.FAsUByte := PByte(ABuffer)^;
  761. otSWord: result.FData.FAsSWord := PSmallInt(ABuffer)^;
  762. otUWord: result.FData.FAsUWord := PWord(ABuffer)^;
  763. otSLong: result.FData.FAsSLong := PLongInt(ABuffer)^;
  764. otULong: result.FData.FAsULong := PLongWord(ABuffer)^;
  765. end;
  766. end;
  767. tkBool : begin
  768. case GetTypeData(ATypeInfo)^.OrdType of
  769. otUByte: result.FData.FAsSByte := ShortInt(PBoolean(ABuffer)^);
  770. otUWord: result.FData.FAsUWord := Byte(PBoolean16(ABuffer)^);
  771. otULong: result.FData.FAsULong := SmallInt(PBoolean32(ABuffer)^);
  772. otUQWord: result.FData.FAsUInt64 := QWord(PBoolean64(ABuffer)^);
  773. otSByte: result.FData.FAsSByte := Word(PByteBool(ABuffer)^);
  774. otSWord: result.FData.FAsSWord := LongInt(PWordBool(ABuffer)^);
  775. otSLong: result.FData.FAsSLong := LongWord(PLongBool(ABuffer)^);
  776. otSQWord: result.FData.FAsSInt64 := Int64(PQWordBool(ABuffer)^);
  777. end;
  778. end;
  779. tkFloat : begin
  780. case GetTypeData(ATypeInfo)^.FloatType of
  781. ftCurr : result.FData.FAsCurr := PCurrency(ABuffer)^;
  782. ftSingle : result.FData.FAsSingle := PSingle(ABuffer)^;
  783. ftDouble : result.FData.FAsDouble := PDouble(ABuffer)^;
  784. ftExtended: result.FData.FAsExtended := PExtended(ABuffer)^;
  785. ftComp : result.FData.FAsComp := PComp(ABuffer)^;
  786. end;
  787. end;
  788. else
  789. raise Exception.CreateFmt(SErrUnableToGetValueForType,[ATypeInfo^.Name]);
  790. end;
  791. end;
  792. {$ifndef NoGenericMethods}
  793. generic class function TValue.From<T>(constref aValue: T): TValue;
  794. begin
  795. TValue.Make(@aValue, System.TypeInfo(T), Result);
  796. end;
  797. {$endif}
  798. function TValue.GetTypeDataProp: PTypeData;
  799. begin
  800. result := GetTypeData(FData.FTypeInfo);
  801. end;
  802. function TValue.GetDataSize: SizeInt;
  803. begin
  804. if Assigned(FData.FValueData) and (Kind <> tkSString) then
  805. Result := FData.FValueData.GetDataSize
  806. else begin
  807. Result := 0;
  808. case Kind of
  809. tkEnumeration,
  810. tkBool,
  811. tkInt64,
  812. tkQWord,
  813. tkInteger:
  814. case TypeData^.OrdType of
  815. otSByte,
  816. otUByte:
  817. Result := SizeOf(Byte);
  818. otSWord,
  819. otUWord:
  820. Result := SizeOf(Word);
  821. otSLong,
  822. otULong:
  823. Result := SizeOf(LongWord);
  824. otSQWord,
  825. otUQWord:
  826. Result := SizeOf(QWord);
  827. end;
  828. tkChar:
  829. Result := SizeOf(AnsiChar);
  830. tkFloat:
  831. case TypeData^.FloatType of
  832. ftSingle:
  833. Result := SizeOf(Single);
  834. ftDouble:
  835. Result := SizeOf(Double);
  836. ftExtended:
  837. Result := SizeOf(Extended);
  838. ftComp:
  839. Result := SizeOf(Comp);
  840. ftCurr:
  841. Result := SizeOf(Currency);
  842. end;
  843. tkSet:
  844. Result := TypeData^.SetSize;
  845. tkMethod:
  846. Result := SizeOf(TMethod);
  847. tkSString:
  848. { ShortString can hold max. 254 characters as [0] is Length and [255] is #0 }
  849. Result := SizeOf(ShortString) - 2;
  850. tkVariant:
  851. Result := SizeOf(Variant);
  852. tkProcVar:
  853. Result := SizeOf(CodePointer);
  854. tkWChar:
  855. Result := SizeOf(WideChar);
  856. tkUChar:
  857. Result := SizeOf(UnicodeChar);
  858. tkFile:
  859. { ToDo }
  860. Result := SizeOf(TTextRec);
  861. tkAString,
  862. tkWString,
  863. tkUString,
  864. tkInterface,
  865. tkDynArray,
  866. tkClass,
  867. tkHelper,
  868. tkClassRef,
  869. tkInterfaceRaw,
  870. tkPointer:
  871. Result := SizeOf(Pointer);
  872. tkObject,
  873. tkRecord:
  874. Result := TypeData^.RecSize;
  875. tkArray:
  876. Result := TypeData^.ArrayData.Size;
  877. tkUnknown,
  878. tkLString:
  879. Assert(False);
  880. end;
  881. end;
  882. end;
  883. function TValue.GetTypeInfo: PTypeInfo;
  884. begin
  885. result := FData.FTypeInfo;
  886. end;
  887. function TValue.GetTypeKind: TTypeKind;
  888. begin
  889. if not Assigned(FData.FTypeInfo) then
  890. Result := tkUnknown
  891. else
  892. result := FData.FTypeInfo^.Kind;
  893. end;
  894. function TValue.GetIsEmpty: boolean;
  895. begin
  896. result := (FData.FTypeInfo=nil) or
  897. ((Kind in [tkSString, tkObject, tkRecord, tkArray]) and not Assigned(FData.FValueData)) or
  898. ((Kind in [tkClass, tkClassRef, tkInterfaceRaw]) and not Assigned(FData.FAsPointer));
  899. end;
  900. function TValue.IsArray: boolean;
  901. begin
  902. result := kind in [tkArray, tkDynArray];
  903. end;
  904. function TValue.AsString: string;
  905. begin
  906. if System.GetTypeKind(String) = tkUString then
  907. Result := String(AsUnicodeString)
  908. else
  909. Result := String(AsAnsiString);
  910. end;
  911. function TValue.AsUnicodeString: UnicodeString;
  912. begin
  913. if (Kind in [tkSString, tkAString, tkUString, tkWString]) and not Assigned(FData.FValueData) then
  914. Result := ''
  915. else
  916. case Kind of
  917. tkSString:
  918. Result := UnicodeString(PShortString(FData.FValueData.GetReferenceToRawData)^);
  919. tkAString:
  920. Result := UnicodeString(PAnsiString(FData.FValueData.GetReferenceToRawData)^);
  921. tkWString:
  922. Result := UnicodeString(PWideString(FData.FValueData.GetReferenceToRawData)^);
  923. tkUString:
  924. Result := UnicodeString(PUnicodeString(FData.FValueData.GetReferenceToRawData)^);
  925. else
  926. raise EInvalidCast.Create(SErrInvalidTypecast);
  927. end;
  928. end;
  929. function TValue.AsAnsiString: AnsiString;
  930. begin
  931. if (Kind in [tkSString, tkAString, tkUString, tkWString]) and not Assigned(FData.FValueData) then
  932. Result := ''
  933. else
  934. case Kind of
  935. tkSString:
  936. Result := AnsiString(PShortString(FData.FValueData.GetReferenceToRawData)^);
  937. tkAString:
  938. Result := AnsiString(PAnsiString(FData.FValueData.GetReferenceToRawData)^);
  939. tkWString:
  940. Result := AnsiString(PWideString(FData.FValueData.GetReferenceToRawData)^);
  941. tkUString:
  942. Result := AnsiString(PUnicodeString(FData.FValueData.GetReferenceToRawData)^);
  943. else
  944. raise EInvalidCast.Create(SErrInvalidTypecast);
  945. end;
  946. end;
  947. function TValue.AsExtended: Extended;
  948. begin
  949. if Kind = tkFloat then
  950. begin
  951. case TypeData^.FloatType of
  952. ftSingle : result := FData.FAsSingle;
  953. ftDouble : result := FData.FAsDouble;
  954. ftExtended : result := FData.FAsExtended;
  955. else
  956. raise EInvalidCast.Create(SErrInvalidTypecast);
  957. end;
  958. end
  959. else
  960. raise EInvalidCast.Create(SErrInvalidTypecast);
  961. end;
  962. function TValue.AsObject: TObject;
  963. begin
  964. if IsObject or (IsClass and not Assigned(FData.FAsObject)) then
  965. result := TObject(FData.FAsObject)
  966. else
  967. raise EInvalidCast.Create(SErrInvalidTypecast);
  968. end;
  969. function TValue.IsObject: boolean;
  970. begin
  971. result := (Kind = tkClass) or ((Kind = tkUnknown) and not Assigned(FData.FAsObject));
  972. end;
  973. function TValue.IsClass: boolean;
  974. begin
  975. result := (Kind = tkClassRef) or ((Kind in [tkClass,tkUnknown]) and not Assigned(FData.FAsObject));
  976. end;
  977. function TValue.AsClass: TClass;
  978. begin
  979. if IsClass then
  980. result := FData.FAsClass
  981. else
  982. raise EInvalidCast.Create(SErrInvalidTypecast);
  983. end;
  984. function TValue.IsOrdinal: boolean;
  985. begin
  986. result := (Kind in [tkInteger, tkInt64, tkQWord, tkBool]) or
  987. ((Kind in [tkClass, tkClassRef, tkInterfaceRaw, tkUnknown]) and not Assigned(FData.FAsPointer));
  988. end;
  989. function TValue.AsBoolean: boolean;
  990. begin
  991. if (Kind = tkBool) then
  992. case TypeData^.OrdType of
  993. otSByte: Result := ByteBool(FData.FAsSByte);
  994. otUByte: Result := Boolean(FData.FAsUByte);
  995. otSWord: Result := WordBool(FData.FAsSWord);
  996. otUWord: Result := Boolean16(FData.FAsUWord);
  997. otSLong: Result := LongBool(FData.FAsSLong);
  998. otULong: Result := Boolean32(FData.FAsULong);
  999. otSQWord: Result := QWordBool(FData.FAsSInt64);
  1000. otUQWord: Result := Boolean64(FData.FAsUInt64);
  1001. end
  1002. else
  1003. raise EInvalidCast.Create(SErrInvalidTypecast);
  1004. end;
  1005. function TValue.AsOrdinal: Int64;
  1006. begin
  1007. if IsOrdinal then
  1008. if Kind in [tkClass, tkClassRef, tkInterfaceRaw, tkUnknown] then
  1009. Result := 0
  1010. else
  1011. case TypeData^.OrdType of
  1012. otSByte: Result := FData.FAsSByte;
  1013. otUByte: Result := FData.FAsUByte;
  1014. otSWord: Result := FData.FAsSWord;
  1015. otUWord: Result := FData.FAsUWord;
  1016. otSLong: Result := FData.FAsSLong;
  1017. otULong: Result := FData.FAsULong;
  1018. otSQWord: Result := FData.FAsSInt64;
  1019. otUQWord: Result := FData.FAsUInt64;
  1020. end
  1021. else
  1022. raise EInvalidCast.Create(SErrInvalidTypecast);
  1023. end;
  1024. function TValue.AsCurrency: Currency;
  1025. begin
  1026. if (Kind = tkFloat) and (TypeData^.FloatType=ftCurr) then
  1027. result := FData.FAsCurr
  1028. else
  1029. raise EInvalidCast.Create(SErrInvalidTypecast);
  1030. end;
  1031. function TValue.AsInteger: Integer;
  1032. begin
  1033. if Kind in [tkInteger, tkInt64, tkQWord] then
  1034. case TypeData^.OrdType of
  1035. otSByte: Result := FData.FAsSByte;
  1036. otUByte: Result := FData.FAsUByte;
  1037. otSWord: Result := FData.FAsSWord;
  1038. otUWord: Result := FData.FAsUWord;
  1039. otSLong: Result := FData.FAsSLong;
  1040. otULong: Result := FData.FAsULong;
  1041. otSQWord: Result := FData.FAsSInt64;
  1042. otUQWord: Result := FData.FAsUInt64;
  1043. end
  1044. else
  1045. raise EInvalidCast.Create(SErrInvalidTypecast);
  1046. end;
  1047. function TValue.AsInt64: Int64;
  1048. begin
  1049. if Kind in [tkInteger, tkInt64, tkQWord] then
  1050. case TypeData^.OrdType of
  1051. otSByte: Result := FData.FAsSByte;
  1052. otUByte: Result := FData.FAsUByte;
  1053. otSWord: Result := FData.FAsSWord;
  1054. otUWord: Result := FData.FAsUWord;
  1055. otSLong: Result := FData.FAsSLong;
  1056. otULong: Result := FData.FAsULong;
  1057. otSQWord: Result := FData.FAsSInt64;
  1058. otUQWord: Result := FData.FAsUInt64;
  1059. end;
  1060. end;
  1061. function TValue.AsUInt64: QWord;
  1062. begin
  1063. if Kind in [tkInteger, tkInt64, tkQWord] then
  1064. case TypeData^.OrdType of
  1065. otSByte: Result := FData.FAsSByte;
  1066. otUByte: Result := FData.FAsUByte;
  1067. otSWord: Result := FData.FAsSWord;
  1068. otUWord: Result := FData.FAsUWord;
  1069. otSLong: Result := FData.FAsSLong;
  1070. otULong: Result := FData.FAsULong;
  1071. otSQWord: Result := FData.FAsSInt64;
  1072. otUQWord: Result := FData.FAsUInt64;
  1073. end;
  1074. end;
  1075. function TValue.AsInterface: IInterface;
  1076. begin
  1077. if Kind = tkInterface then
  1078. Result := PInterface(FData.FValueData.GetReferenceToRawData)^
  1079. else if (Kind in [tkClass, tkClassRef, tkUnknown]) and not Assigned(FData.FAsPointer) then
  1080. Result := Nil
  1081. else
  1082. raise EInvalidCast.Create(SErrInvalidTypecast);
  1083. end;
  1084. function TValue.ToString: String;
  1085. begin
  1086. case Kind of
  1087. tkSString,
  1088. tkAString : result := AsString;
  1089. tkInteger : result := IntToStr(AsInteger);
  1090. tkBool : result := BoolToStr(AsBoolean, True);
  1091. else
  1092. result := '';
  1093. end;
  1094. end;
  1095. function TValue.GetArrayLength: SizeInt;
  1096. begin
  1097. if not IsArray then
  1098. raise EInvalidCast.Create(SErrInvalidTypecast);
  1099. if Kind = tkDynArray then
  1100. Result := DynArraySize(PPointer(FData.FValueData.GetReferenceToRawData)^)
  1101. else
  1102. Result := TypeData^.ArrayData.ElCount;
  1103. end;
  1104. function TValue.GetArrayElement(AIndex: SizeInt): TValue;
  1105. var
  1106. data: Pointer;
  1107. eltype: PTypeInfo;
  1108. td: PTypeData;
  1109. begin
  1110. if not IsArray then
  1111. raise EInvalidCast.Create(SErrInvalidTypecast);
  1112. if Kind = tkDynArray then begin
  1113. data := DynArrayIndex(PPointer(FData.FValueData.GetReferenceToRawData)^, [AIndex], FData.FTypeInfo);
  1114. eltype := TypeData^.elType2;
  1115. end else begin
  1116. td := TypeData;
  1117. eltype := td^.ArrayData.ElType;
  1118. data := PByte(FData.FValueData.GetReferenceToRawData) + AIndex * (td^.ArrayData.Size div td^.ArrayData.ElCount);
  1119. end;
  1120. { MakeWithoutCopy? }
  1121. Make(data, eltype, Result);
  1122. end;
  1123. procedure TValue.SetArrayElement(AIndex: SizeInt; constref AValue: TValue);
  1124. var
  1125. data: Pointer;
  1126. eltype: PTypeInfo;
  1127. td, tdv: PTypeData;
  1128. begin
  1129. if not IsArray then
  1130. raise EInvalidCast.Create(SErrInvalidTypecast);
  1131. if Kind = tkDynArray then begin
  1132. data := DynArrayIndex(PPointer(FData.FValueData.GetReferenceToRawData)^, [AIndex], FData.FTypeInfo);
  1133. eltype := TypeData^.elType2;
  1134. end else begin
  1135. td := TypeData;
  1136. eltype := td^.ArrayData.ElType;
  1137. data := PByte(FData.FValueData.GetReferenceToRawData) + AIndex * (td^.ArrayData.Size div td^.ArrayData.ElCount);
  1138. end;
  1139. { maybe we'll later on allow some typecasts, but for now be restrictive }
  1140. if eltype^.Kind <> AValue.Kind then
  1141. raise EInvalidCast.Create(SErrInvalidTypecast);
  1142. td := GetTypeData(eltype);
  1143. tdv := AValue.TypeData;
  1144. if ((eltype^.Kind in [tkInteger, tkBool, tkEnumeration, tkSet]) and (td^.OrdType <> tdv^.OrdType)) or
  1145. ((eltype^.Kind = tkFloat) and (td^.FloatType <> tdv^.FloatType)) then
  1146. raise EInvalidCast.Create(SErrInvalidTypecast);
  1147. if Assigned(AValue.FData.FValueData) and (eltype^.Kind <> tkSString) then
  1148. IntCopy(AValue.FData.FValueData.GetReferenceToRawData, data, eltype)
  1149. else
  1150. Move(AValue.GetReferenceToRawData^, data^, AValue.DataSize);
  1151. end;
  1152. function TValue.IsType(ATypeInfo: PTypeInfo): boolean;
  1153. begin
  1154. result := ATypeInfo = TypeInfo;
  1155. end;
  1156. function TValue.TryAsOrdinal(out AResult: int64): boolean;
  1157. begin
  1158. result := IsOrdinal;
  1159. if result then
  1160. AResult := AsOrdinal;
  1161. end;
  1162. function TValue.GetReferenceToRawData: Pointer;
  1163. begin
  1164. if IsEmpty then
  1165. Result := Nil
  1166. else if Assigned(FData.FValueData) then
  1167. Result := FData.FValueData.GetReferenceToRawData
  1168. else begin
  1169. Result := Nil;
  1170. case Kind of
  1171. tkInteger,
  1172. tkEnumeration,
  1173. tkInt64,
  1174. tkQWord,
  1175. tkBool:
  1176. case TypeData^.OrdType of
  1177. otSByte:
  1178. Result := @FData.FAsSByte;
  1179. otUByte:
  1180. Result := @FData.FAsUByte;
  1181. otSWord:
  1182. Result := @FData.FAsSWord;
  1183. otUWord:
  1184. Result := @FData.FAsUWord;
  1185. otSLong:
  1186. Result := @FData.FAsSLong;
  1187. otULong:
  1188. Result := @FData.FAsULong;
  1189. otSQWord:
  1190. Result := @FData.FAsSInt64;
  1191. otUQWord:
  1192. Result := @FData.FAsUInt64;
  1193. end;
  1194. tkSet: begin
  1195. case TypeData^.OrdType of
  1196. otUByte: begin
  1197. case TypeData^.SetSize of
  1198. 1:
  1199. Result := @FData.FAsUByte;
  1200. 2:
  1201. Result := @FData.FAsUWord;
  1202. 3, 4:
  1203. Result := @FData.FAsULong;
  1204. 5..8:
  1205. Result := @FData.FAsUInt64;
  1206. else
  1207. { this should have gone through FAsValueData :/ }
  1208. Result := Nil;
  1209. end;
  1210. end;
  1211. otUWord:
  1212. Result := @FData.FAsUWord;
  1213. otULong:
  1214. Result := @FData.FAsULong;
  1215. else
  1216. Result := Nil;
  1217. end;
  1218. end;
  1219. tkChar:
  1220. Result := @FData.FAsUByte;
  1221. tkFloat:
  1222. case TypeData^.FloatType of
  1223. ftSingle:
  1224. Result := @FData.FAsSingle;
  1225. ftDouble:
  1226. Result := @FData.FAsDouble;
  1227. ftExtended:
  1228. Result := @FData.FAsExtended;
  1229. ftComp:
  1230. Result := @FData.FAsComp;
  1231. ftCurr:
  1232. Result := @FData.FAsCurr;
  1233. end;
  1234. tkMethod:
  1235. Result := @FData.FAsMethod;
  1236. tkClass:
  1237. Result := @FData.FAsObject;
  1238. tkWChar:
  1239. Result := @FData.FAsUWord;
  1240. tkInterfaceRaw:
  1241. Result := @FData.FAsPointer;
  1242. tkProcVar:
  1243. Result := @FData.FAsMethod.Code;
  1244. tkUChar:
  1245. Result := @FData.FAsUWord;
  1246. tkFile:
  1247. Result := @FData.FAsPointer;
  1248. tkClassRef:
  1249. Result := @FData.FAsClass;
  1250. tkPointer:
  1251. Result := @FData.FAsPointer;
  1252. tkVariant,
  1253. tkDynArray,
  1254. tkArray,
  1255. tkObject,
  1256. tkRecord,
  1257. tkInterface,
  1258. tkSString,
  1259. tkLString,
  1260. tkAString,
  1261. tkUString,
  1262. tkWString:
  1263. Assert(false, 'Managed/complex type not handled through IValueData');
  1264. end;
  1265. end;
  1266. end;
  1267. class operator TValue.:=(const AValue: String): TValue;
  1268. begin
  1269. Make(@AValue, System.TypeInfo(AValue), Result);
  1270. end;
  1271. class operator TValue.:=(AValue: LongInt): TValue;
  1272. begin
  1273. Make(@AValue, System.TypeInfo(AValue), Result);
  1274. end;
  1275. class operator TValue.:=(AValue: Single): TValue;
  1276. begin
  1277. Make(@AValue, System.TypeInfo(AValue), Result);
  1278. end;
  1279. class operator TValue.:=(AValue: Double): TValue;
  1280. begin
  1281. Make(@AValue, System.TypeInfo(AValue), Result);
  1282. end;
  1283. {$ifdef FPC_HAS_TYPE_EXTENDED}
  1284. class operator TValue.:=(AValue: Extended): TValue;
  1285. begin
  1286. Make(@AValue, System.TypeInfo(AValue), Result);
  1287. end;
  1288. {$endif}
  1289. class operator TValue.:=(AValue: Currency): TValue;
  1290. begin
  1291. Make(@AValue, System.TypeInfo(AValue), Result);
  1292. end;
  1293. class operator TValue.:=(AValue: Int64): TValue;
  1294. begin
  1295. Make(@AValue, System.TypeInfo(AValue), Result);
  1296. end;
  1297. class operator TValue.:=(AValue: QWord): TValue;
  1298. begin
  1299. Make(@AValue, System.TypeInfo(AValue), Result);
  1300. end;
  1301. class operator TValue.:=(AValue: TObject): TValue;
  1302. begin
  1303. Make(@AValue, System.TypeInfo(AValue), Result);
  1304. end;
  1305. class operator TValue.:=(AValue: TClass): TValue;
  1306. begin
  1307. Make(@AValue, System.TypeInfo(AValue), Result);
  1308. end;
  1309. class operator TValue.:=(AValue: Boolean): TValue;
  1310. begin
  1311. Make(@AValue, System.TypeInfo(AValue), Result);
  1312. end;
  1313. { TRttiStringType }
  1314. function TRttiStringType.GetStringKind: TRttiStringKind;
  1315. begin
  1316. case TypeKind of
  1317. tkSString : result := skShortString;
  1318. tkLString : result := skAnsiString;
  1319. tkAString : result := skAnsiString;
  1320. tkUString : result := skUnicodeString;
  1321. tkWString : result := skWideString;
  1322. end;
  1323. end;
  1324. { TRttiInstanceType }
  1325. function TRttiInstanceType.GetMetaClassType: TClass;
  1326. begin
  1327. result := FTypeData^.ClassType;
  1328. end;
  1329. function TRttiInstanceType.GetDeclaringUnitName: string;
  1330. begin
  1331. result := FTypeData^.UnitName;
  1332. end;
  1333. function TRttiInstanceType.GetBaseType: TRttiType;
  1334. var
  1335. AContext: TRttiContext;
  1336. begin
  1337. AContext := TRttiContext.Create;
  1338. try
  1339. result := AContext.GetType(FTypeData^.ParentInfo);
  1340. finally
  1341. AContext.Free;
  1342. end;
  1343. end;
  1344. function TRttiInstanceType.GetIsInstance: boolean;
  1345. begin
  1346. Result:=True;
  1347. end;
  1348. function TRttiInstanceType.GetTypeSize: integer;
  1349. begin
  1350. Result:=sizeof(TObject);
  1351. end;
  1352. { TRttiMember }
  1353. function TRttiMember.GetVisibility: TMemberVisibility;
  1354. begin
  1355. result := mvPublished;
  1356. end;
  1357. constructor TRttiMember.create(AParent: TRttiType);
  1358. begin
  1359. inherited create();
  1360. FParent := AParent;
  1361. end;
  1362. { TRttiProperty }
  1363. function TRttiProperty.GetPropertyType: TRttiType;
  1364. begin
  1365. result := GRttiPool.GetType(FPropInfo^.PropType);
  1366. end;
  1367. function TRttiProperty.GetIsReadable: boolean;
  1368. begin
  1369. result := assigned(FPropInfo^.GetProc);
  1370. end;
  1371. function TRttiProperty.GetIsWritable: boolean;
  1372. begin
  1373. result := assigned(FPropInfo^.SetProc);
  1374. end;
  1375. function TRttiProperty.GetVisibility: TMemberVisibility;
  1376. begin
  1377. // At this moment only pulished rtti-property-info is supported by fpc
  1378. result := mvPublished;
  1379. end;
  1380. function TRttiProperty.GetName: string;
  1381. begin
  1382. Result:=FPropInfo^.Name;
  1383. end;
  1384. constructor TRttiProperty.create(AParent: TRttiType; APropInfo: PPropInfo);
  1385. begin
  1386. inherited create(AParent);
  1387. FPropInfo := APropInfo;
  1388. end;
  1389. function TRttiProperty.GetValue(Instance: pointer): TValue;
  1390. procedure ValueFromBool(value: Int64);
  1391. var
  1392. b8: Boolean;
  1393. b16: Boolean16;
  1394. b32: Boolean32;
  1395. bb: ByteBool;
  1396. bw: WordBool;
  1397. bl: LongBool;
  1398. td: PTypeData;
  1399. p: Pointer;
  1400. begin
  1401. td := GetTypeData(FPropInfo^.PropType);
  1402. case td^.OrdType of
  1403. otUByte:
  1404. begin
  1405. b8 := Boolean(value);
  1406. p := @b8;
  1407. end;
  1408. otUWord:
  1409. begin
  1410. b16 := Boolean16(value);
  1411. p := @b16;
  1412. end;
  1413. otULong:
  1414. begin
  1415. b32 := Boolean32(value);
  1416. p := @b32;
  1417. end;
  1418. otSByte:
  1419. begin
  1420. bb := ByteBool(value);
  1421. p := @bb;
  1422. end;
  1423. otSWord:
  1424. begin
  1425. bw := WordBool(value);
  1426. p := @bw;
  1427. end;
  1428. otSLong:
  1429. begin
  1430. bl := LongBool(value);
  1431. p := @bl;
  1432. end;
  1433. end;
  1434. TValue.Make(p, FPropInfo^.PropType, result);
  1435. end;
  1436. procedure ValueFromInt(value: Int64);
  1437. var
  1438. i8: UInt8;
  1439. i16: UInt16;
  1440. i32: UInt32;
  1441. td: PTypeData;
  1442. p: Pointer;
  1443. begin
  1444. td := GetTypeData(FPropInfo^.PropType);
  1445. case td^.OrdType of
  1446. otUByte,
  1447. otSByte:
  1448. begin
  1449. i8 := value;
  1450. p := @i8;
  1451. end;
  1452. otUWord,
  1453. otSWord:
  1454. begin
  1455. i16 := value;
  1456. p := @i16;
  1457. end;
  1458. otULong,
  1459. otSLong:
  1460. begin
  1461. i32 := value;
  1462. p := @i32;
  1463. end;
  1464. end;
  1465. TValue.Make(p, FPropInfo^.PropType, result);
  1466. end;
  1467. var
  1468. s: string;
  1469. ss: ShortString;
  1470. i: int64;
  1471. c: Char;
  1472. wc: WideChar;
  1473. begin
  1474. case FPropinfo^.PropType^.Kind of
  1475. tkSString:
  1476. begin
  1477. ss := GetStrProp(TObject(Instance), FPropInfo);
  1478. TValue.Make(@ss, FPropInfo^.PropType, result);
  1479. end;
  1480. tkAString:
  1481. begin
  1482. s := GetStrProp(TObject(Instance), FPropInfo);
  1483. TValue.Make(@s, FPropInfo^.PropType, result);
  1484. end;
  1485. tkBool:
  1486. begin
  1487. i := GetOrdProp(TObject(Instance), FPropInfo);
  1488. ValueFromBool(i);
  1489. end;
  1490. tkInteger:
  1491. begin
  1492. i := GetOrdProp(TObject(Instance), FPropInfo);
  1493. ValueFromInt(i);
  1494. end;
  1495. tkChar:
  1496. begin
  1497. c := AnsiChar(GetOrdProp(TObject(Instance), FPropInfo));
  1498. TValue.Make(@c, FPropInfo^.PropType, result);
  1499. end;
  1500. tkWChar:
  1501. begin
  1502. wc := WideChar(GetOrdProp(TObject(Instance), FPropInfo));
  1503. TValue.Make(@wc, FPropInfo^.PropType, result);
  1504. end;
  1505. tkInt64,
  1506. tkQWord:
  1507. begin
  1508. i := GetOrdProp(TObject(Instance), FPropInfo);
  1509. TValue.Make(@i, FPropInfo^.PropType, result);
  1510. end;
  1511. else
  1512. result := TValue.Empty;
  1513. end
  1514. end;
  1515. procedure TRttiProperty.SetValue(Instance: pointer; const AValue: TValue);
  1516. begin
  1517. case FPropinfo^.PropType^.Kind of
  1518. tkSString,
  1519. tkAString:
  1520. SetStrProp(TObject(Instance), FPropInfo, AValue.AsString);
  1521. tkInteger,
  1522. tkInt64,
  1523. tkQWord,
  1524. tkChar,
  1525. tkBool,
  1526. tkWChar:
  1527. SetOrdProp(TObject(Instance), FPropInfo, AValue.AsOrdinal);
  1528. else
  1529. raise exception.createFmt(SErrUnableToSetValueForType, [PropertyType.Name]);
  1530. end
  1531. end;
  1532. function TRttiType.GetIsInstance: boolean;
  1533. begin
  1534. result := false;
  1535. end;
  1536. function TRttiType.GetIsManaged: boolean;
  1537. begin
  1538. result := Rtti.IsManaged(FTypeInfo);
  1539. end;
  1540. function TRttiType.GetIsOrdinal: boolean;
  1541. begin
  1542. result := false;
  1543. end;
  1544. function TRttiType.GetIsRecord: boolean;
  1545. begin
  1546. result := false;
  1547. end;
  1548. function TRttiType.GetIsSet: boolean;
  1549. begin
  1550. result := false;
  1551. end;
  1552. function TRttiType.GetAsInstance: TRttiInstanceType;
  1553. begin
  1554. // This is a ridicoulous design, but Delphi-compatible...
  1555. result := TRttiInstanceType(self);
  1556. end;
  1557. function TRttiType.GetBaseType: TRttiType;
  1558. begin
  1559. result := nil;
  1560. end;
  1561. function TRttiType.GetTypeKind: TTypeKind;
  1562. begin
  1563. result := FTypeInfo^.Kind;
  1564. end;
  1565. function TRttiType.GetTypeSize: integer;
  1566. begin
  1567. result := -1;
  1568. end;
  1569. function TRttiType.GetName: string;
  1570. begin
  1571. Result:=FTypeInfo^.Name;
  1572. end;
  1573. constructor TRttiType.create(ATypeInfo: PTypeInfo);
  1574. begin
  1575. inherited create();
  1576. FTypeInfo:=ATypeInfo;
  1577. if assigned(FTypeInfo) then
  1578. FTypeData:=GetTypeData(ATypeInfo);
  1579. end;
  1580. function aligntoptr(p : pointer) : pointer;inline;
  1581. begin
  1582. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  1583. result:=align(p,sizeof(p));
  1584. {$else FPC_REQUIRES_PROPER_ALIGNMENT}
  1585. result:=p;
  1586. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  1587. end;
  1588. function aligntoqword(p : pointer) : pointer;inline;
  1589. type
  1590. TAlignCheck = record
  1591. b : byte;
  1592. q : qword;
  1593. end;
  1594. begin
  1595. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  1596. result:=align(p,PtrInt(@TAlignCheck(nil^).q))
  1597. {$else FPC_REQUIRES_PROPER_ALIGNMENT}
  1598. result:=p;
  1599. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  1600. end;
  1601. function TRttiType.GetProperties: specialize TArray<TRttiProperty>;
  1602. type
  1603. PPropData = ^TPropData;
  1604. var
  1605. TypeInfo: PTypeInfo;
  1606. TypeRttiType: TRttiType;
  1607. TD: PTypeData;
  1608. PPD: PPropData;
  1609. TP: PPropInfo;
  1610. Count: longint;
  1611. begin
  1612. if not FPropertiesResolved then
  1613. begin
  1614. TypeInfo := FTypeInfo;
  1615. // Get the total properties count
  1616. SetLength(FProperties,FTypeData^.PropCount);
  1617. // Clear list
  1618. FillChar(FProperties[0],FTypeData^.PropCount*sizeof(TRttiProperty),0);
  1619. TypeRttiType:= self;
  1620. repeat
  1621. TD:=GetTypeData(TypeInfo);
  1622. // published properties count for this object
  1623. // skip the attribute-info if available
  1624. PPD := aligntoptr(PPropData(pointer(@TD^.UnitName)+PByte(@TD^.UnitName)^+1));
  1625. Count:=PPD^.PropCount;
  1626. // Now point TP to first propinfo record.
  1627. TP:=PPropInfo(@PPD^.PropList);
  1628. While Count>0 do
  1629. begin
  1630. // Don't overwrite properties with the same name
  1631. if FProperties[TP^.NameIndex]=nil then
  1632. FProperties[TP^.NameIndex]:=TRttiProperty.Create(TypeRttiType, TP);
  1633. // Point to TP next propinfo record.
  1634. // Located at Name[Length(Name)+1] !
  1635. TP:=aligntoptr(PPropInfo(pointer(@TP^.Name)+PByte(@TP^.Name)^+1));
  1636. Dec(Count);
  1637. end;
  1638. TypeInfo:=TD^.Parentinfo;
  1639. TypeRttiType:= GRttiPool.GetType(TypeInfo);
  1640. until TypeInfo=nil;
  1641. end;
  1642. result := FProperties;
  1643. end;
  1644. function TRttiType.GetProperty(const AName: string): TRttiProperty;
  1645. var
  1646. FPropList: specialize TArray<TRttiProperty>;
  1647. i: Integer;
  1648. begin
  1649. result := nil;
  1650. FPropList := GetProperties;
  1651. for i := 0 to length(FPropList)-1 do
  1652. if sametext(FPropList[i].Name,AName) then
  1653. begin
  1654. result := FPropList[i];
  1655. break;
  1656. end;
  1657. end;
  1658. destructor TRttiType.Destroy;
  1659. var
  1660. i: Integer;
  1661. begin
  1662. for i := 0 to high(FProperties) do
  1663. FProperties[i].Free;
  1664. inherited destroy;
  1665. end;
  1666. { TRttiNamedObject }
  1667. function TRttiNamedObject.GetName: string;
  1668. begin
  1669. result := '';
  1670. end;
  1671. { TRttiContext }
  1672. class function TRttiContext.Create: TRttiContext;
  1673. begin
  1674. result.FContextToken := nil;
  1675. end;
  1676. procedure TRttiContext.Free;
  1677. begin
  1678. FContextToken := nil;
  1679. end;
  1680. function TRttiContext.GetType(ATypeInfo: PTypeInfo): TRttiType;
  1681. begin
  1682. if not assigned(FContextToken) then
  1683. FContextToken := TPoolToken.Create;
  1684. result := (FContextToken as IPooltoken).RttiPool.GetType(ATypeInfo);
  1685. end;
  1686. function TRttiContext.GetType(AClass: TClass): TRttiType;
  1687. begin
  1688. if assigned(AClass) then
  1689. result := GetType(PTypeInfo(AClass.ClassInfo))
  1690. else
  1691. result := nil;
  1692. end;
  1693. {function TRttiContext.GetTypes: specialize TArray<TRttiType>;
  1694. begin
  1695. if not assigned(FContextToken) then
  1696. FContextToken := TPoolToken.Create;
  1697. result := (FContextToken as IPooltoken).RttiPool.GetTypes;
  1698. end;}
  1699. initialization
  1700. PoolRefCount := 0;
  1701. InitDefaultFunctionCallManager;
  1702. end.