objpas.inc 58 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2000 by the Free Pascal development team
  4. This unit makes Free Pascal as much as possible Delphi compatible
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. {$ifdef FPC_HAS_FEATURE_VARIANTS}
  12. procedure DoDispCallByIDError(res : Pointer; const disp : IDispatch;desc : PDispDesc; params : Pointer);
  13. begin
  14. handleerroraddrframeind(RuntimeErrorExitCodes[reVarDispatch],
  15. get_pc_addr,get_frame);
  16. end;
  17. procedure fpc_dispatch_by_id(Result: Pointer; const Dispatch: pointer;
  18. DispDesc: Pointer; Params: Pointer); compilerproc;
  19. type
  20. TDispProc = procedure(res : Pointer; const disp : IDispatch;desc : PDispDesc; params : Pointer);
  21. begin
  22. TDispProc(DispCallByIDProc)(Result,IDispatch(Dispatch),DispDesc,Params);
  23. end;
  24. {$endif FPC_HAS_FEATURE_VARIANTS}
  25. {****************************************************************************
  26. Internal Routines called from the Compiler
  27. ****************************************************************************}
  28. { the reverse order of the parameters make code generation easier }
  29. function fpc_do_is(aclass : tclass;aobject : tobject) : boolean;[public,alias: 'FPC_DO_IS']; compilerproc;
  30. begin
  31. fpc_do_is:=assigned(aobject) and assigned(aclass) and
  32. aobject.inheritsfrom(aclass);
  33. end;
  34. { the reverse order of the parameters make code generation easier }
  35. function fpc_do_as(aclass : tclass;aobject : tobject): tobject;[public,alias: 'FPC_DO_AS']; compilerproc;
  36. begin
  37. if assigned(aobject) and not(aobject.inheritsfrom(aclass)) then
  38. handleerroraddrframeInd(219,get_pc_addr,get_frame);
  39. result := aobject;
  40. end;
  41. { interface helpers }
  42. procedure fpc_intf_decr_ref(var i: pointer);[public,alias: 'FPC_INTF_DECR_REF']; compilerproc;
  43. var
  44. iFetch: pointer;
  45. begin
  46. iFetch:=i;
  47. if assigned(iFetch) then
  48. begin
  49. i:=nil;
  50. IUnknown(iFetch)._Release;
  51. end;
  52. end;
  53. { local declaration for intf_decr_ref for local access }
  54. procedure intf_decr_ref(var i: pointer); [external name 'FPC_INTF_DECR_REF'];
  55. procedure fpc_intf_incr_ref(i: pointer);[public,alias: 'FPC_INTF_INCR_REF']; compilerproc;
  56. begin
  57. if assigned(i) then
  58. IUnknown(i)._AddRef;
  59. end;
  60. { local declaration of intf_incr_ref for local access }
  61. procedure intf_incr_ref(i: pointer); [external name 'FPC_INTF_INCR_REF'];
  62. procedure fpc_intf_assign(var D: pointer; const S: pointer);[public,alias: 'FPC_INTF_ASSIGN']; compilerproc;
  63. begin
  64. if assigned(S) then
  65. IUnknown(S)._AddRef;
  66. if assigned(D) then
  67. IUnknown(D)._Release;
  68. D:=S;
  69. end;
  70. procedure fpc_intf_assign(var D: pointer; const s: pointer); [external name 'FPC_INTF_ASSIGN'];
  71. {procedure fpc_intf_assign_by_iid(var D: pointer; const S: pointer; const iid: TGUID);[public,alias: 'FPC_INTF_ASSIGN2']; compilerproc;
  72. var
  73. tmp : pointer;
  74. begin
  75. if assigned(S) then
  76. begin
  77. tmp:=nil;
  78. if IUnknown(S).QueryInterface(iid,tmp)<>S_OK then
  79. handleerror(219);
  80. if assigned(D) then
  81. IUnknown(D)._Release;
  82. D:=tmp;
  83. end
  84. else
  85. begin
  86. if assigned(D) then
  87. IUnknown(D)._Release;
  88. D:=nil;
  89. end;
  90. end;}
  91. function fpc_intf_is(const S: pointer; const iid: TGUID): Boolean;[public,alias: 'FPC_INTF_IS']; compilerproc;
  92. var
  93. tmpi: pointer;
  94. begin
  95. tmpi:=nil;
  96. fpc_intf_is:=Assigned(S) and (IUnknown(S).QueryInterface(iid,tmpi)=S_OK);
  97. if Assigned(tmpi) then
  98. IUnknown(tmpi)._Release;
  99. end;
  100. function fpc_intf_is_class(const S: pointer; const aclass: tclass): Boolean;[public,alias: 'FPC_INTF_IS_CLASS']; compilerproc;
  101. var
  102. tmpo: tobject;
  103. begin
  104. fpc_intf_is_class:=Assigned(S) and (IUnknown(S).QueryInterface(IObjectInstance,tmpo)=S_OK) and tmpo.InheritsFrom(aclass);
  105. end;
  106. function fpc_class_is_intf(const S: pointer; const iid: TGUID): Boolean;[public,alias: 'FPC_CLASS_IS_INTF']; compilerproc;
  107. var
  108. tmpi: pointer;
  109. tmpi2: pointer; // weak!
  110. begin
  111. tmpi:=nil;
  112. tmpi2:=nil;
  113. fpc_class_is_intf:=Assigned(S) and ((TObject(S).GetInterfaceWeak(IUnknown,tmpi2) and (IUnknown(tmpi2).QueryInterface(IID,tmpi)=S_OK)) or
  114. TObject(S).GetInterface(IID,tmpi));
  115. if Assigned(tmpi) then
  116. IUnknown(tmpi)._Release;
  117. end;
  118. function fpc_class_is_corbaintf(const S: pointer; const iid: Shortstring): Boolean;[public,alias: 'FPC_CLASS_IS_CORBAINTF']; compilerproc;
  119. begin
  120. fpc_class_is_corbaintf:=Assigned(S) and Assigned(TObject(S).GetInterfaceEntryByStr(iid));
  121. end;
  122. function fpc_intf_cast(const S: pointer; const iid: TGUID): IInterface;[public,alias: 'FPC_INTF_CAST']; compilerproc;
  123. var
  124. tmpi: pointer;
  125. begin
  126. tmpi:=nil;
  127. if Assigned(S) and (IUnknown(S).QueryInterface(iid,tmpi)=S_OK) then
  128. pointer(fpc_intf_cast):=tmpi
  129. else
  130. fpc_intf_cast:= nil;
  131. end;
  132. function fpc_intf_cast_class(const S: pointer; const aclass: tclass): pointer;[public,alias: 'FPC_INTF_CAST_CLASS']; compilerproc;
  133. var
  134. tmpo: tobject;
  135. begin
  136. if Assigned(S) and (IUnknown(S).QueryInterface(IObjectInstance,tmpo)=S_OK) and tmpo.InheritsFrom(aclass) then
  137. fpc_intf_cast_class:=tmpo
  138. else
  139. fpc_intf_cast_class:=nil;
  140. end;
  141. function fpc_class_cast_intf(const S: pointer; const iid: TGUID): IInterface;[public,alias: 'FPC_CLASS_CAST_INTF']; compilerproc;
  142. var
  143. tmpi: pointer;
  144. tmpi2: pointer; // weak!
  145. begin
  146. tmpi:=nil;
  147. tmpi2:=nil;
  148. if Assigned(S) and ((TObject(S).GetInterfaceWeak(IUnknown,tmpi2) and (IUnknown(tmpi2).QueryInterface(IID,tmpi)=S_OK)) or
  149. TObject(S).GetInterface(IID,tmpi)) then
  150. begin
  151. // decrease reference count
  152. fpc_class_cast_intf:=nil;
  153. pointer(fpc_class_cast_intf):=tmpi
  154. end
  155. else
  156. fpc_class_cast_intf:=nil;
  157. end;
  158. function fpc_class_cast_corbaintf(const S: pointer; const iid: Shortstring): Pointer;[public,alias: 'FPC_CLASS_CAST_CORBAINTF']; compilerproc;
  159. var
  160. tmpi: pointer;
  161. begin
  162. if Assigned(S) and TObject(S).GetInterface(iid,tmpi) then
  163. fpc_class_cast_corbaintf:=tmpi
  164. else
  165. fpc_class_cast_corbaintf:=nil;
  166. end;
  167. function fpc_intf_as(const S: pointer; const iid: TGUID): IInterface;[public,alias: 'FPC_INTF_AS']; compilerproc;
  168. var
  169. tmpi: pointer; // _AddRef before _Release
  170. begin
  171. if assigned(S) then
  172. begin
  173. tmpi:=nil;
  174. if IUnknown(S).QueryInterface(iid,tmpi)<>S_OK then
  175. handleerror(219);
  176. // decrease reference count
  177. fpc_intf_as:=nil;
  178. pointer(fpc_intf_as):=tmpi;
  179. end
  180. else
  181. fpc_intf_as:=nil;
  182. end;
  183. function fpc_intf_as_class(const S: pointer; const aclass: tclass): pointer;[public,alias: 'FPC_INTF_AS_CLASS']; compilerproc;
  184. var
  185. tmpo: tobject;
  186. begin
  187. if assigned(S) then
  188. begin
  189. if not ((IUnknown(S).QueryInterface(IObjectInstance,tmpo)=S_OK) and tmpo.inheritsfrom(aclass)) then
  190. handleerror(219);
  191. fpc_intf_as_class:=tmpo;
  192. end
  193. else
  194. fpc_intf_as_class:=nil;
  195. end;
  196. function fpc_class_as_intf(const S: pointer; const iid: TGUID): IInterface;[public,alias: 'FPC_CLASS_AS_INTF']; compilerproc;
  197. var
  198. tmpi: pointer; // _AddRef before _Release
  199. tmpi2: pointer; // weak!
  200. begin
  201. if assigned(S) then
  202. begin
  203. tmpi:=nil;
  204. tmpi2:=nil;
  205. if not ((TObject(S).GetInterfaceWeak(IUnknown,tmpi2) and (IUnknown(tmpi2).QueryInterface(IID,tmpi)=S_OK)) or TObject(S).GetInterface(IID,tmpi)) then
  206. handleerror(219);
  207. // decrease reference count
  208. fpc_class_as_intf:=nil;
  209. pointer(fpc_class_as_intf):=tmpi;
  210. end
  211. else
  212. fpc_class_as_intf:=nil;
  213. end;
  214. function fpc_class_as_corbaintf(const S: pointer; const iid: Shortstring): Pointer;[public,alias: 'FPC_CLASS_AS_CORBAINTF']; compilerproc;
  215. var
  216. tmpi: pointer; // _AddRef before _Release
  217. begin
  218. if assigned(S) then
  219. begin
  220. tmpi:=nil;
  221. if not TObject(S).GetInterface(iid,tmpi) then
  222. handleerror(219);
  223. fpc_class_as_corbaintf:=tmpi;
  224. end
  225. else
  226. fpc_class_as_corbaintf:=nil;
  227. end;
  228. {****************************************************************************
  229. TVMT
  230. ****************************************************************************}
  231. function TVmt.GetvParent: PVmt;
  232. begin
  233. if Assigned(vParentRef) then
  234. GetvParent:=vParentRef^
  235. else
  236. GetvParent:=Nil;
  237. end;
  238. {****************************************************************************
  239. TGUID
  240. ****************************************************************************}
  241. class operator TGUID.=(const aLeft, aRight: TGUID): Boolean;
  242. var
  243. P1,P2 : ^Cardinal;
  244. begin
  245. P1:=PCardinal(@aLeft);
  246. P2:=PCardinal(@aRight);
  247. Result:=(P1[0]=P2[0]) and (P1[1]=P2[1]) and (P1[2]=P2[2]) and (P1[3]=P2[3]);
  248. end;
  249. class operator TGUID.<>(const aLeft, aRight: TGUID): Boolean;
  250. begin
  251. Result:=Not (aLeft=aRight);
  252. end;
  253. class function TGUID.Empty: TGUID; static;
  254. begin
  255. Result:=Default(TGUID);
  256. end;
  257. class function TGUID.Create(const aData; aBigEndian: Boolean = False): TGUID; overload; static;
  258. begin
  259. Result:=Create(PByte(@aData),aBigEndian);
  260. end;
  261. class function TGUID.Create(const aData : PByte; aBigEndian: Boolean = False): TGUID; overload; static;
  262. const
  263. SysBigendian = {$IFDEF FPC_LITTLE_ENDIAN} false {$ELSE} true {$ENDIF};
  264. begin
  265. Result := PGuid(aData)^;
  266. if (aBigEndian=SysBigEndian) then
  267. exit;
  268. Result.D1:=SwapEndian(Result.D1);
  269. Result.D2:=SwapEndian(Result.D2);
  270. Result.D3:=SwapEndian(Result.D3);
  271. end;
  272. class function TGUID.Create(const aData: array of Byte; aStartIndex: Cardinal; aBigEndian: Boolean = False): TGUID; overload; static;
  273. begin
  274. if ((Length(aData)-aStartIndex)<16) then
  275. Result:=Empty
  276. else
  277. Result:=Create(PByte(@aData[aStartIndex]),aBigEndian);
  278. end;
  279. function TGUID.IsEmpty: Boolean;
  280. var
  281. P : ^Cardinal;
  282. begin
  283. P:=PCardinal(@Self);
  284. Result:=(P[0]=0) and (P[1]=0) and (P[2]=0) and (P[3]=0)
  285. end;
  286. {****************************************************************************
  287. TINTERFACEENTRY
  288. ****************************************************************************}
  289. function tinterfaceentry.GetIID: pguid;
  290. begin
  291. if Assigned(IIDRef) then
  292. GetIID:=IIDRef^
  293. else
  294. GetIID:=Nil;
  295. end;
  296. function tinterfaceentry.GetIIDStr: pshortstring;
  297. begin
  298. if Assigned(IIDStrRef) then
  299. GetIIDStr:=IIDStrRef^
  300. else
  301. GetIIDStr:=Nil;
  302. end;
  303. {****************************************************************************
  304. TOBJECT
  305. ****************************************************************************}
  306. constructor TObject.Create;
  307. begin
  308. end;
  309. destructor TObject.Destroy;
  310. begin
  311. end;
  312. procedure TObject.Free;
  313. begin
  314. // the call via self avoids a warning
  315. if self<>nil then
  316. self.destroy;
  317. end;
  318. class function TObject.InstanceSize : SizeInt;
  319. begin
  320. InstanceSize := PVmt(Self)^.vInstanceSize;
  321. end;
  322. procedure InitInterfacePointers(objclass: tclass;instance : pointer);
  323. var
  324. ovmt: PVmt;
  325. i: longint;
  326. intftable: pinterfacetable;
  327. Res: pinterfaceentry;
  328. begin
  329. ovmt := PVmt(objclass);
  330. while assigned(ovmt) and assigned(ovmt^.vIntfTable) do
  331. begin
  332. intftable:=ovmt^.vIntfTable;
  333. i:=intftable^.EntryCount;
  334. Res:=@intftable^.Entries[0];
  335. while i>0 do begin
  336. if Res^.IType = etStandard then
  337. ppointer(@(pbyte(instance)[Res^.IOffset]))^:=
  338. pointer(Res^.VTable);
  339. inc(Res);
  340. dec(i);
  341. end;
  342. ovmt:=ovmt^.vParent;
  343. end;
  344. end;
  345. class function TObject.InitInstance(instance : pointer) : tobject;
  346. var
  347. vmt : PVmt;
  348. inittable : pointer;
  349. {$ifdef FPC_HAS_FEATURE_RTTI}
  350. mopinittable : PRTTIRecordOpOffsetTable;
  351. {$endif def FPC_HAS_FEATURE_RTTI}
  352. i : longint;
  353. begin
  354. { the size is saved at offset 0 }
  355. fillchar(instance^, InstanceSize, 0);
  356. { insert VMT pointer into the new created memory area }
  357. { (in class methods self contains the VMT!) }
  358. {$IFNDEF SYSTEM_HAS_FEATURE_MONITOR}
  359. ppointer(instance)^:=pointer(self);
  360. {$ELSE}
  361. {$IFDEF VER3_2}
  362. // In 3.2.x Compiler (used during bootstrap) still inserts VMT at offset...
  363. ppointer(PByte(instance)+SizeOf(Pointer))^:=pointer(self);
  364. {$ELSE}
  365. // As of 3.3.x compiler forces insert of VMT at first pos.
  366. ppointer(instance)^:=pointer(self);
  367. {$ENDIF}
  368. {$ENDIF}
  369. if assigned(PVmt(self)^.vIntfTable) then
  370. InitInterfacePointers(self,instance);
  371. {$ifdef FPC_HAS_FEATURE_RTTI}
  372. { for management operators like initialize call int_initialize }
  373. vmt := PVmt(self);
  374. if assigned(vmt) then
  375. begin
  376. inittable:=vmt^.vInitTable;
  377. if assigned(inittable) then
  378. begin
  379. mopinittable:=RTTIRecordMopInitTable(inittable);
  380. if assigned(mopinittable) then
  381. begin
  382. {$push}
  383. { ensure that no range check errors pop up with the [0..0] array }
  384. {$R-}
  385. for i:=0 to mopinittable^.Count-1 do
  386. TRTTIRecVarOp(mopinittable^.Entries[i].ManagmentOperator)(PByte(Instance)+mopinittable^.Entries[i].FieldOffset);
  387. {$pop}
  388. end;
  389. end;
  390. end;
  391. {$endif def FPC_HAS_FEATURE_RTTI}
  392. InitInstance:=TObject(Instance);
  393. end;
  394. class function TObject.ClassParent : tclass;
  395. begin
  396. { type of self is class of tobject => it points to the vmt }
  397. { the parent vmt is saved at offset vmtParent }
  398. classparent:=tclass(PVmt(Self)^.vParent);
  399. end;
  400. class function TObject.NewInstance : tobject;
  401. var
  402. p : pointer;
  403. begin
  404. getmem(p, InstanceSize);
  405. if p <> nil then
  406. InitInstance(p);
  407. NewInstance:=TObject(p);
  408. end;
  409. procedure TObject.FreeInstance;
  410. begin
  411. CleanupInstance;
  412. FreeMem(Pointer(Self));
  413. end;
  414. class function TObject.ClassType : TClass;
  415. begin
  416. ClassType:=TClass(Pointer(Self))
  417. end;
  418. type
  419. {$PUSH}
  420. {$PACKRECORDS NORMAL}
  421. tmethodnamerec =
  422. {$IFNDEF FPC_REQUIRES_PROPER_ALIGNMENT}
  423. packed
  424. {$ENDIF FPC_REQUIRES_PROPER_ALIGNMENT}
  425. record
  426. name : pshortstring;
  427. addr : codepointer;
  428. end;
  429. tmethodnametable =
  430. {$IFNDEF FPC_REQUIRES_PROPER_ALIGNMENT}
  431. packed
  432. {$ENDIF FPC_REQUIRES_PROPER_ALIGNMENT}
  433. record
  434. count : dword;
  435. entries : packed array[0..0] of tmethodnamerec;
  436. end;
  437. {$POP}
  438. pmethodnametable = ^tmethodnametable;
  439. class function TObject.MethodAddress(const name : shortstring) : codepointer;
  440. var
  441. methodtable : pmethodnametable;
  442. i : longint; // in case count=0
  443. ovmt : PVmt;
  444. begin
  445. ovmt:=PVmt(self);
  446. while assigned(ovmt) do
  447. begin
  448. methodtable:=pmethodnametable(ovmt^.vMethodTable);
  449. if assigned(methodtable) then
  450. begin
  451. for i:=0 to methodtable^.count-1 do
  452. if ShortCompareText(methodtable^.entries[i].name^, name)=0 then
  453. begin
  454. MethodAddress:=methodtable^.entries[i].addr;
  455. exit;
  456. end;
  457. end;
  458. ovmt := ovmt^.vParent;
  459. end;
  460. MethodAddress:=nil;
  461. end;
  462. class function TObject.MethodName(address : codepointer) : shortstring;
  463. var
  464. methodtable : pmethodnametable;
  465. i : longint; // in case count=0
  466. ovmt : PVmt;
  467. begin
  468. ovmt:=PVmt(self);
  469. while assigned(ovmt) do
  470. begin
  471. methodtable:=pmethodnametable(ovmt^.vMethodTable);
  472. if assigned(methodtable) then
  473. begin
  474. for i:=0 to methodtable^.count-1 do
  475. if methodtable^.entries[i].addr=address then
  476. begin
  477. MethodName:=methodtable^.entries[i].name^;
  478. exit;
  479. end;
  480. end;
  481. ovmt := ovmt^.vParent;
  482. end;
  483. MethodName:='';
  484. end;
  485. function TObject.FieldAddress(const name : shortstring) : pointer;
  486. {The following is copied to the typinfo unit. If it is changed here, change it there as well ! }
  487. type
  488. {$PUSH}
  489. {$PACKRECORDS NORMAL}
  490. PFieldInfo = ^TFieldInfo;
  491. TFieldInfo =
  492. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  493. packed
  494. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  495. record
  496. FieldOffset: SizeUInt;
  497. ClassTypeIndex: Word;
  498. Name: ShortString;
  499. end;
  500. PFieldTable = ^TFieldTable;
  501. TFieldTable =
  502. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  503. packed
  504. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  505. record
  506. FieldCount: Word;
  507. ClassTable: Pointer;
  508. { should be array[Word] of TFieldInfo; but
  509. Elements have variant size! force at least proper alignment }
  510. Fields: array[0..0] of TFieldInfo
  511. end;
  512. {$POP}
  513. var
  514. ovmt: PVmt;
  515. FieldTable: PFieldTable;
  516. FieldInfo: PFieldInfo;
  517. i: longint;
  518. begin
  519. if Length(name) > 0 then
  520. begin
  521. ovmt := PVmt(ClassType);
  522. while ovmt <> nil do
  523. begin
  524. FieldTable := PFieldTable(ovmt^.vFieldTable);
  525. if FieldTable <> nil then
  526. begin
  527. FieldInfo := @FieldTable^.Fields[0];
  528. for i := 0 to FieldTable^.FieldCount - 1 do
  529. begin
  530. if ShortCompareText(FieldInfo^.Name, name) = 0 then
  531. begin
  532. fieldaddress := Pointer(Self) + FieldInfo^.FieldOffset;
  533. exit;
  534. end;
  535. FieldInfo := PFieldInfo(PByte(@FieldInfo^.Name) + 1 + Length(FieldInfo^.Name));
  536. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  537. { align to largest field of TFieldInfo }
  538. FieldInfo := Align(FieldInfo, SizeOf(PtrUInt));
  539. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  540. end;
  541. end;
  542. { Try again with the parent class type }
  543. ovmt:=ovmt^.vParent;
  544. end;
  545. end;
  546. fieldaddress:=nil;
  547. end;
  548. function TObject.SafeCallException(exceptobject : tobject;
  549. exceptaddr : codepointer) : HResult;
  550. begin
  551. safecallexception:=E_UNEXPECTED;
  552. end;
  553. class function TObject.ClassInfo : pointer;
  554. begin
  555. ClassInfo := PVmt(Self)^.vTypeInfo;
  556. end;
  557. class function TObject.ClassName : ShortString;
  558. begin
  559. ClassName := PVmt(Self)^.vClassName^;
  560. end;
  561. class function TObject.ClassNameIs(const name : RTLString) : boolean;
  562. var
  563. SS : ShortString;
  564. begin
  565. SS:=ShortString(Name);
  566. ClassNameIs:=ShortCompareText(PVmt(Self)^.vClassName^, SS) = 0;
  567. end;
  568. class function TObject.InheritsFrom(aclass : TClass) : Boolean;
  569. var
  570. vmt: PVmt;
  571. begin
  572. if assigned(aclass) then
  573. begin
  574. vmt:=PVmt(self);
  575. while assigned(vmt) and (vmt <> PVmt(aclass)) do
  576. vmt := vmt^.vParent;
  577. InheritsFrom := (vmt = PVmt(aclass));
  578. end
  579. else
  580. inheritsFrom := False;
  581. end;
  582. class function TObject.stringmessagetable : pstringmessagetable;
  583. begin
  584. stringmessagetable:=PVmt(Self)^.vMsgStrPtr;
  585. end;
  586. type
  587. tmessagehandler = procedure(var msg) of object;
  588. procedure TObject.Dispatch(var message);
  589. type
  590. {$PUSH}
  591. {$PACKRECORDS NORMAL}
  592. PMsgIntTable = ^TMsgIntTable;
  593. TMsgIntTable = record
  594. index : dword;
  595. method : codepointer;
  596. end;
  597. PMsgInt = ^TMsgInt;
  598. TMsgInt = record
  599. count : longint;
  600. msgs : array[0..0] of TMsgIntTable;
  601. end;
  602. {$POP}
  603. var
  604. index : dword;
  605. count,i : longint;
  606. msgtable : PMsgIntTable;
  607. p : PMsgInt;
  608. ovmt : PVmt;
  609. msghandler : tmessagehandler;
  610. begin
  611. index:=dword(message);
  612. ovmt := PVmt(ClassType);
  613. while assigned(ovmt) do
  614. begin
  615. // See if we have messages at all in this class.
  616. p:=PMsgInt(ovmt^.vDynamicTable);
  617. If Assigned(p) then
  618. begin
  619. msgtable:=@p^.msgs;
  620. count:=p^.count;
  621. end
  622. else
  623. Count:=0;
  624. { later, we can implement a binary search here }
  625. for i:=0 to count-1 do
  626. begin
  627. if index=msgtable[i].index then
  628. begin
  629. TMethod(msghandler).Code:=msgtable[i].method;
  630. TMethod(msghandler).Data:=self;
  631. msghandler(message);
  632. exit;
  633. end;
  634. end;
  635. ovmt:=ovmt^.vParent;
  636. end;
  637. DefaultHandler(message);
  638. end;
  639. procedure TObject.DispatchStr(var message);
  640. var
  641. name : shortstring;
  642. count,i : longint;
  643. msgstrtable : pmsgstrtable;
  644. p: pstringmessagetable;
  645. ovmt : PVmt;
  646. msghandler : tmessagehandler;
  647. begin
  648. name:=pshortstring(@message)^;
  649. ovmt:=PVmt(ClassType);
  650. while assigned(ovmt) do
  651. begin
  652. p := ovmt^.vMsgStrPtr;
  653. if (P<>Nil) and (p^.count<>0) then
  654. begin
  655. count:=p^.count;
  656. msgstrtable:=@p^.msgstrtable;
  657. end
  658. else
  659. Count:=0;
  660. { later, we can implement a binary search here }
  661. for i:=0 to count-1 do
  662. begin
  663. if name=msgstrtable[i].name^ then
  664. begin
  665. TMethod(msghandler).Code:=msgstrtable[i].method;
  666. TMethod(msghandler).Data:=self;
  667. msghandler(message);
  668. exit;
  669. end;
  670. end;
  671. ovmt:=ovmt^.vParent;
  672. end;
  673. DefaultHandlerStr(message);
  674. end;
  675. procedure TObject.DefaultHandler(var message);
  676. begin
  677. end;
  678. procedure TObject.DefaultHandlerStr(var message);
  679. begin
  680. end;
  681. procedure TObject.CleanupInstance;
  682. var
  683. vmt : PVmt;
  684. temp : pointer;
  685. begin
  686. vmt := PVmt(ClassType);
  687. while vmt<>nil do
  688. begin
  689. Temp:= vmt^.vInitTable;
  690. {$ifdef FPC_HAS_FEATURE_RTTI}
  691. { The RTTI format matches one for records, except the type is tkClass.
  692. Since RecordRTTI does not check the type, calling it yields the desired result. }
  693. if Assigned(Temp) then
  694. RecordRTTI(Self,aligntoqword(Temp+2+PByte(Temp)[1]),@int_finalize);
  695. {$endif def FPC_HAS_FEATURE_RTTI}
  696. vmt:= vmt^.vParent;
  697. end;
  698. {$IFDEF SYSTEM_HAS_FEATURE_MONITOR}
  699. if Assigned(_MonitorData) then
  700. TMonitor.FreeMonitorData(_MonitorData);
  701. {$ENDIF}
  702. end;
  703. procedure TObject.AfterConstruction;
  704. begin
  705. end;
  706. procedure TObject.BeforeDestruction;
  707. begin
  708. end;
  709. function IsGUIDEqual(const guid1, guid2: tguid): boolean;
  710. begin
  711. IsGUIDEqual:=
  712. (guid1.D1=guid2.D1) and
  713. (PDWORD(@guid1.D2)^=PDWORD(@guid2.D2)^) and
  714. (PDWORD(@guid1.D4[0])^=PDWORD(@guid2.D4[0])^) and
  715. (PDWORD(@guid1.D4[4])^=PDWORD(@guid2.D4[4])^);
  716. end;
  717. // Use of managed types should be avoided here; implicit _Addref/_Release
  718. // will end up in unpredictable behaviour if called on CORBA interfaces.
  719. type
  720. TInterfaceGetter = procedure(out Obj) of object;
  721. TClassGetter = function: TObject of object;
  722. function GetInterfaceByEntry(Instance: pointer; IEntry: pinterfaceentry; out obj): boolean;
  723. var
  724. Getter: TMethod;
  725. begin
  726. Pointer(Obj) := nil;
  727. Getter.Data := Instance;
  728. if Assigned(IEntry) and Assigned(Instance) then
  729. begin
  730. case IEntry^.IType of
  731. etStandard:
  732. Pointer(Obj) := PByte(instance)+IEntry^.IOffset;
  733. etFieldValue, etFieldValueClass:
  734. Pointer(obj) := PPointer(PByte(Instance)+IEntry^.IOffset)^;
  735. etVirtualMethodResult:
  736. begin
  737. // IOffset is relative to the VMT, not to instance.
  738. Getter.code := PCodePointer(PByte(PPointer(Instance)^) + IEntry^.IOffset)^;
  739. TInterfaceGetter(Getter)(obj);
  740. end;
  741. etVirtualMethodClass:
  742. begin
  743. // IOffset is relative to the VMT, not to instance.
  744. Getter.code := PCodePointer(PByte(PPointer(Instance)^) + IEntry^.IOffset)^;
  745. TObject(obj) := TClassGetter(Getter)();
  746. end;
  747. etStaticMethodResult:
  748. begin
  749. Getter.code := IEntry^.IOffsetAsCodePtr;
  750. TInterfaceGetter(Getter)(obj);
  751. end;
  752. etStaticMethodClass:
  753. begin
  754. Getter.code := IEntry^.IOffsetAsCodePtr;
  755. TObject(obj) := TClassGetter(Getter)();
  756. end;
  757. end;
  758. end;
  759. result := assigned(pointer(obj));
  760. end;
  761. function TObject.GetInterface(const iid : tguid;out obj) : boolean;
  762. var
  763. IEntry: PInterfaceEntry;
  764. Instance: TObject;
  765. begin
  766. if IsGUIDEqual(IObjectInstance,iid) then
  767. begin
  768. TObject(Obj) := Self;
  769. Result := True;
  770. Exit;
  771. end;
  772. Instance := self;
  773. repeat
  774. IEntry := Instance.GetInterfaceEntry(iid);
  775. result := GetInterfaceByEntry(Instance, IEntry, obj);
  776. if (not result) or
  777. (IEntry^.IType in [etStandard, etFieldValue,
  778. etStaticMethodResult, etVirtualMethodResult]) then
  779. Break;
  780. { if interface is implemented by a class-type property or field,
  781. continue search }
  782. Instance := TObject(obj);
  783. until False;
  784. { Getter function will normally AddRef, so adding another reference here
  785. will cause memleak. }
  786. if result and (IEntry^.IType in [etStandard, etFieldValue]) then
  787. IInterface(obj)._AddRef;
  788. end;
  789. function TObject.GetInterfaceWeak(const iid : tguid; out obj) : boolean;
  790. var
  791. IEntry: PInterfaceEntry;
  792. Instance: TObject;
  793. begin
  794. if IsGUIDEqual(IObjectInstance,iid) then
  795. begin
  796. TObject(Obj) := Self;
  797. Result := True;
  798. Exit;
  799. end;
  800. Instance := self;
  801. repeat
  802. IEntry := Instance.GetInterfaceEntry(iid);
  803. result := GetInterfaceByEntry(Instance, IEntry, obj);
  804. if (not result) or
  805. (IEntry^.IType in [etStandard, etFieldValue,
  806. etStaticMethodResult, etVirtualMethodResult]) then
  807. Break;
  808. { if interface is implemented by a class-type property or field,
  809. continue search }
  810. Instance := TObject(obj);
  811. until False;
  812. { Getter function will normally AddRef, so we have to release it,
  813. else the ref is not weak. }
  814. if result and not (IEntry^.IType in [etStandard, etFieldValue]) then
  815. IInterface(obj)._Release;
  816. end;
  817. function TObject.GetInterfaceByStr(const iidstr : shortstring;out obj) : boolean;
  818. var
  819. IEntry: PInterfaceEntry;
  820. Instance: TObject;
  821. begin
  822. Instance := self;
  823. repeat
  824. IEntry := Instance.GetInterfaceEntryByStr(iidstr);
  825. result := GetInterfaceByEntry(Instance, IEntry, obj);
  826. if (not result) or
  827. (IEntry^.IType in [etStandard, etFieldValue,
  828. etStaticMethodResult, etVirtualMethodResult]) then
  829. Break;
  830. { if interface is implemented by a class-type property or field,
  831. continue search }
  832. Instance := TObject(obj);
  833. until False;
  834. { Getter function will normally AddRef, so adding another reference here
  835. will cause memleak. (com interfaces only!) }
  836. if result and Assigned(IEntry^.IID) and (IEntry^.IType in [etStandard, etFieldValue]) then
  837. IInterface(obj)._AddRef;
  838. end;
  839. function TObject.GetInterface(const iidstr : shortstring;out obj) : boolean;
  840. begin
  841. Result := GetInterfaceByStr(iidstr,obj);
  842. end;
  843. class function TObject.GetInterfaceEntry(const iid : tguid) : pinterfaceentry;
  844. var
  845. i: longint;
  846. intftable: pinterfacetable;
  847. ovmt: PVmt;
  848. begin
  849. ovmt := PVmt(Self);
  850. while Assigned(ovmt) and Assigned(ovmt^.vIntftable) do
  851. begin
  852. intftable:=ovmt^.vIntfTable;
  853. for i:=0 to intftable^.EntryCount-1 do
  854. begin
  855. result:=@intftable^.Entries[i];
  856. if assigned(Result^.iid) and IsGUIDEqual(Result^.iid^,iid) then
  857. Exit;
  858. end;
  859. ovmt := ovmt^.vParent;
  860. end;
  861. result := nil;
  862. end;
  863. class function TObject.GetInterfaceEntryByStr(const iidstr : shortstring) : pinterfaceentry;
  864. var
  865. i: longint;
  866. intftable: pinterfacetable;
  867. ovmt: PVmt;
  868. begin
  869. ovmt := PVmt(Self);
  870. while Assigned(ovmt) and Assigned(ovmt^.vIntfTable) do
  871. begin
  872. intftable:=ovmt^.vIntfTable;
  873. for i:=0 to intftable^.EntryCount-1 do
  874. begin
  875. result:=@intftable^.Entries[i];
  876. if assigned(result^.iidstr) and (result^.iidstr^ = iidstr) then
  877. Exit;
  878. end;
  879. ovmt := ovmt^.vParent;
  880. end;
  881. result:=nil;
  882. end;
  883. class function TObject.GetInterfaceTable : pinterfacetable;
  884. begin
  885. getinterfacetable:=PVmt(Self)^.vIntfTable;
  886. end;
  887. class function TObject.UnitName : RTLString;
  888. {$ifdef FPC_HAS_FEATURE_RTTI}
  889. type
  890. TClassTypeInfo = {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}packed{$endif}record
  891. Attributes: Pointer;
  892. case TTypeKind of
  893. tkClass: (
  894. ClassType: TClass;
  895. ParentInfo: Pointer;
  896. PropCount: SmallInt;
  897. UnitName: ShortString;
  898. );
  899. { include for proper alignment }
  900. tkInt64: (
  901. Dummy: Int64;
  902. );
  903. end;
  904. PClassTypeInfo = ^TClassTypeInfo;
  905. var
  906. classtypeinfo: PClassTypeInfo;
  907. begin
  908. classtypeinfo:=ClassInfo;
  909. if Assigned(classtypeinfo) then
  910. begin
  911. // offset PTypeInfo by Length(Name) + 2 (ShortString length byte + SizeOf(Kind))
  912. inc(Pointer(classtypeinfo), PByte(Pointer(classtypeinfo)+1)^ + 2);
  913. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  914. classtypeinfo:=aligntoqword(classtypeinfo);
  915. {$endif}
  916. result:=classtypeinfo^.UnitName;
  917. end
  918. else
  919. result:='';
  920. end;
  921. {$else not FPC_HAS_FEATURE_RTTI}
  922. begin
  923. result:='';
  924. end;
  925. {$endif ndef FPC_HAS_FEATURE_RTTI}
  926. class function TObject.QualifiedClassName: RTLString;
  927. var
  928. uname: RTLString;
  929. begin
  930. uname := UnitName; //TODO: change 'UnitName' to 'UnitScope' as soon as RTL implement it
  931. if uname='' then
  932. result:=ClassName
  933. else
  934. result:=Concat(uname, '.', ClassName);
  935. end;
  936. function TObject.Equals(Obj: TObject) : boolean;
  937. begin
  938. result:=Obj=Self;
  939. end;
  940. function TObject.GetHashCode: PtrInt;
  941. begin
  942. result:=PtrInt(Self);
  943. end;
  944. function TObject.ToString: RTLString;
  945. begin
  946. result:=ClassName;
  947. end;
  948. procedure TObject.DisposeOf;
  949. begin
  950. Free;
  951. end;
  952. function TObject.GetDisposed : Boolean;
  953. begin
  954. Result:=False;
  955. end;
  956. procedure TObject.CheckDisposed;
  957. begin
  958. // Do nothing since we have no reference count.
  959. end;
  960. {$IFDEF SYSTEM_HAS_FEATURE_MONITOR}
  961. function TObject.SetMonitorData(aData,aCheckOld : Pointer) : Pointer;
  962. begin
  963. Result:=InterlockedCompareExchange(_MonitorData,aData,aCheckOld);
  964. end;
  965. function TObject.GetMonitorData: Pointer;
  966. begin
  967. Result:=_MonitorData;
  968. end;
  969. {$ENDIF}
  970. {****************************************************************************
  971. TINTERFACEDOBJECT
  972. ****************************************************************************}
  973. function TInterfacedObject.QueryInterface(
  974. {$IFDEF FPC_HAS_CONSTREF}constref{$ELSE}const{$ENDIF} iid : tguid;out obj) : longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
  975. begin
  976. if getinterface(iid,obj) then
  977. result:=S_OK
  978. else
  979. result:=longint(E_NOINTERFACE);
  980. end;
  981. function TInterfacedObject._AddRef : longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
  982. begin
  983. _addref:=frefcount;
  984. if _addref<>0 then
  985. begin
  986. if _addref>0 then
  987. _addref:=interlockedincrement(frefcount);
  988. exit;
  989. end;
  990. frefcount:=1; { Work non-atomically in the common case of refcount = 0 (typical state after the complete object construction). }
  991. _addref:=1;
  992. end;
  993. function TInterfacedObject._Release : longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
  994. begin
  995. _Release:=frefcount;
  996. if _Release<>1 then
  997. begin
  998. if _Release<=0 then { -1 means recursive call from destructor... 0 is impossible. }
  999. exit;
  1000. _Release:=interlockeddecrement(frefcount);
  1001. if _Release>0 then
  1002. exit;
  1003. end
  1004. else
  1005. _Release:=0; { Work non-atomically in the common case of refcount = 1 (typical state for the last owner... which is often the only owner). }
  1006. frefcount:=-1; { Prevent recursive _Release from destroying twice (bug 32168). }
  1007. self.destroy;
  1008. end;
  1009. destructor TInterfacedObject.Destroy;
  1010. begin
  1011. // We must explicitly reset. Bug ID 32353
  1012. FRefCount:=0;
  1013. inherited Destroy;
  1014. end;
  1015. procedure TInterfacedObject.AfterConstruction;
  1016. begin
  1017. { we need to fix the refcount we forced in newinstance }
  1018. { further, it must be done in a thread safe way }
  1019. if frefcount=1 then
  1020. frefcount:=0 { Work non-atomically in the common case of refcount = 1 (usual state before AfterConstruction). }
  1021. else
  1022. declocked(frefcount);
  1023. end;
  1024. procedure TInterfacedObject.BeforeDestruction;
  1025. begin
  1026. if frefcount>0 then { Legitimate values: -1 if destroying by _Release, 0 if destroying manually. }
  1027. HandleError(204);
  1028. end;
  1029. class function TInterfacedObject.NewInstance : TObject;
  1030. begin
  1031. NewInstance:=inherited NewInstance;
  1032. if NewInstance<>nil then
  1033. TInterfacedObject(NewInstance).frefcount:=1;
  1034. end;
  1035. {****************************************************************************
  1036. TAGGREGATEDOBJECT
  1037. ****************************************************************************}
  1038. constructor TAggregatedObject.Create(const aController: IUnknown);
  1039. begin
  1040. inherited Create;
  1041. { do not keep a counted reference to the controller! }
  1042. fcontroller := Pointer(aController);
  1043. end;
  1044. function TAggregatedObject.QueryInterface(
  1045. {$IFDEF FPC_HAS_CONSTREF}constref{$ELSE}const{$ENDIF} iid : tguid;out obj) : longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
  1046. begin
  1047. Result := IUnknown(fcontroller).QueryInterface(iid, obj);
  1048. end;
  1049. function TAggregatedObject._AddRef : longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
  1050. begin
  1051. Result := IUnknown(fcontroller)._AddRef;
  1052. end;
  1053. function TAggregatedObject._Release : longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
  1054. begin
  1055. Result := IUnknown(fcontroller)._Release;
  1056. end;
  1057. function TAggregatedObject.GetController : IUnknown;
  1058. begin
  1059. Result := IUnknown(fcontroller);
  1060. end;
  1061. {****************************************************************************
  1062. TContainedOBJECT
  1063. ****************************************************************************}
  1064. function TContainedObject.QueryInterface(
  1065. {$IFDEF FPC_HAS_CONSTREF}constref{$ELSE}const{$ENDIF} iid : tguid;out obj) : longint; {$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
  1066. begin
  1067. if getinterface(iid,obj) then
  1068. result:=S_OK
  1069. else
  1070. result:=longint(E_NOINTERFACE);
  1071. end;
  1072. {****************************************************************************
  1073. TNoRefCountObject
  1074. ****************************************************************************}
  1075. function TNoRefCountObject.QueryInterface( {$IFDEF FPC_HAS_CONSTREF}constref{$ELSE}const{$ENDIF} iid : tguid;out obj) : longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
  1076. begin
  1077. if getinterface(iid,obj) then
  1078. result:=S_OK
  1079. else
  1080. result:=longint(E_NOINTERFACE);
  1081. end;
  1082. function TNoRefCountObject._AddRef : longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
  1083. begin
  1084. Result:=-1;
  1085. end;
  1086. function TNoRefCountObject._Release : longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
  1087. begin
  1088. Result:=-1;
  1089. end;
  1090. {****************************************************************************
  1091. TCustomAttribute
  1092. ****************************************************************************}
  1093. constructor TCustomAttribute.Create;
  1094. begin
  1095. inherited;
  1096. end;
  1097. {****************************************************************************
  1098. TUnimplementedAttribute
  1099. ****************************************************************************}
  1100. constructor TUnimplementedAttribute.Create;
  1101. begin
  1102. inherited;
  1103. end;
  1104. {****************************************************************************
  1105. TCustomStoredAttribute
  1106. ****************************************************************************}
  1107. constructor StoredAttribute.Create;
  1108. begin
  1109. end;
  1110. constructor StoredAttribute.Create(Const aFlag : Boolean);
  1111. begin
  1112. FFlag:=aFlag;
  1113. end;
  1114. constructor StoredAttribute.Create(Const aName : shortstring);
  1115. begin
  1116. FName:=aName;
  1117. end;
  1118. {****************************************************************************
  1119. TInterfaceThunk
  1120. ****************************************************************************}
  1121. Constructor TInterfaceThunk.Create(aCallback : TThunkCallback);
  1122. begin
  1123. FCallBack:=aCallBack;
  1124. end;
  1125. Procedure TInterfaceThunk.Thunk(aMethod: Longint; aCount : Longint; aData : PArgData);
  1126. begin
  1127. if Assigned(FCallBack) then
  1128. FCallBack(Self,aMethod,aCount,aData);
  1129. end;
  1130. function TInterfaceThunk.QueryInterface({$IFDEF FPC_HAS_CONSTREF}constref{$ELSE}const{$ENDIF} iid : tguid;out obj) : longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
  1131. begin
  1132. result:=longint(E_NOINTERFACE);
  1133. if (TMethod(FCallBack).Data<>Nil) then
  1134. // Query the object that created us, this is normally TVirtualInterface
  1135. // Take care: do not call QueryInterface, that would create a never-ending loop !!
  1136. if TObject(TMethod(FCallBack).Data).GetInterface(iid,obj) then
  1137. result:=S_OK;
  1138. if (Result<>S_OK) then
  1139. Result:=Inherited QueryInterface(iid,obj);
  1140. end;
  1141. function TInterfaceThunk.InterfaceVMTOffset : word;
  1142. begin
  1143. Result:=0;
  1144. end;
  1145. {****************************************************************************
  1146. Exception Support
  1147. ****************************************************************************}
  1148. {$ifdef FPC_HAS_FEATURE_EXCEPTIONS}
  1149. {$if defined(FPC_WASM_NATIVE_EXCEPTIONS)}
  1150. {$I except_native.inc}
  1151. {$elseif defined(FPC_WASM_BRANCHFUL_EXCEPTIONS)}
  1152. {$I except_branchful.inc}
  1153. {$else}
  1154. {$i except.inc}
  1155. {$endif}
  1156. {$endif FPC_HAS_FEATURE_EXCEPTIONS}
  1157. {****************************************************************************
  1158. Various Delphi constructs
  1159. ****************************************************************************}
  1160. class operator TMethod.=(const aLeft, aRight: TMethod): Boolean; inline;
  1161. begin
  1162. Result:=(aLeft.Data=aRight.Data) and (aLeft.Code=aRight.Code);
  1163. end;
  1164. class operator TMethod.<>(const aLeft, aRight: TMethod): Boolean; inline;
  1165. begin
  1166. Result:=(aLeft.Data<>aRight.Data) or (aLeft.Code<>aRight.Code);
  1167. end;
  1168. class operator TMethod.>(const aLeft, aRight: TMethod): Boolean; inline;
  1169. begin
  1170. Result:=(PtrUInt(aLeft.Data)>PtrUInt(aRight.Data))
  1171. or
  1172. ((aLeft.Data=aRight.Data) and (PtrUInt(aLeft.Code)>PtrUint(aRight.Code)));
  1173. end;
  1174. class operator TMethod.>=(const aLeft, aRight: TMethod): Boolean; inline;
  1175. begin
  1176. Result:=(aLeft>aRight) or (aLeft=aRight);
  1177. end;
  1178. class operator TMethod.<(const aLeft, aRight: TMethod): Boolean; inline;
  1179. begin
  1180. Result:=(PtrUInt(aLeft.Data)<PtrUInt(aRight.Data))
  1181. or
  1182. ((aLeft.Data=aRight.Data) and (PtrUInt(aLeft.Code)<PtrUint(aRight.Code)));
  1183. end;
  1184. class operator TMethod.<=(const aLeft, aRight: TMethod): Boolean; inline;
  1185. begin
  1186. Result:=(aLeft<aRight) or (aLeft=aRight);
  1187. end;
  1188. function TPtrWrapper.ToPointer: Pointer;
  1189. begin
  1190. Result:=FValue;
  1191. end;
  1192. class function TPtrWrapper.GetNilValue: TPtrWrapper;
  1193. begin
  1194. Result.FValue:=Nil;
  1195. end;
  1196. constructor TPtrWrapper.Create(AValue: PtrInt);
  1197. begin
  1198. FValue:=Pointer(aValue);
  1199. end;
  1200. constructor TPtrWrapper.Create(AValue: Pointer);
  1201. begin
  1202. FValue:=aValue;
  1203. end;
  1204. function TPtrWrapper.ToInteger: PtrInt;
  1205. begin
  1206. Result:=PtrInt(FValue);
  1207. end;
  1208. class operator TPtrWrapper.=(Left, Right: TPtrWrapper): Boolean;
  1209. begin
  1210. Result:=Left.FValue=Right.FValue;
  1211. end;
  1212. constructor TMarshal.Create;
  1213. begin
  1214. System.Error(reInvalidPtr);
  1215. end;
  1216. class function TMarshal.AllocMem(Size: SizeInt): TPtrWrapper;
  1217. begin
  1218. Result.Value := System.AllocMem(Size);
  1219. end;
  1220. class function TMarshal.ReallocMem(OldPtr: TPtrWrapper; NewSize: SizeInt): TPtrWrapper;
  1221. var
  1222. P: Pointer;
  1223. begin
  1224. P := OldPtr.Value;
  1225. Result.Value := System.ReallocMem(P, NewSize);
  1226. end;
  1227. class procedure TMarshal.FreeMem(Ptr: TPtrWrapper);
  1228. begin
  1229. System.FreeMem(Ptr.Value);
  1230. end;
  1231. class procedure TMarshal.Move(Src, Dest: TPtrWrapper; Count: SizeInt); static;
  1232. begin
  1233. System.Move(Src.Value^, Dest.Value^, Count);
  1234. end;
  1235. class function TMarshal.UnsafeAddrOf(var Value): TPtrWrapper;
  1236. begin
  1237. Result.Value := @Value;
  1238. end;
  1239. class procedure TMarshal.Copy(const Src: TUint8Array; StartIndex: SizeInt; Dest: TPtrWrapper; Count: SizeInt);
  1240. begin
  1241. System.Move(PUInt8(Src)[StartIndex], Dest.Value^, Count * SizeOf(UInt8));
  1242. end;
  1243. class procedure TMarshal.Copy(Src: TPtrWrapper; var Dest: TUint8Array; StartIndex: SizeInt; Count: SizeInt);
  1244. begin
  1245. System.Move(Src.Value^, PUInt8(Dest)[StartIndex], Count * SizeOf(UInt8));
  1246. end;
  1247. class procedure TMarshal.Copy(const Src: TInt8Array; StartIndex: SizeInt; Dest: TPtrWrapper; Count: SizeInt);
  1248. begin
  1249. System.Move(PInt8(Src)[StartIndex], Dest.Value^, Count * SizeOf(Int8));
  1250. end;
  1251. class procedure TMarshal.Copy(Src: TPtrWrapper; var Dest: TInt8Array ; StartIndex: SizeInt; Count: SizeInt);
  1252. begin
  1253. System.Move(Src.Value^, PInt8(Dest)[StartIndex], Count * SizeOf(Int8));
  1254. end;
  1255. class procedure TMarshal.Copy(const Src: TUInt16Array; StartIndex: SizeInt; Dest: TPtrWrapper; Count: SizeInt);
  1256. begin
  1257. System.Move(PUInt16(Src)[StartIndex], Dest.Value^, Count * SizeOf(UInt16));
  1258. end;
  1259. class procedure TMarshal.Copy(Src: TPtrWrapper; var Dest: TUint16Array; StartIndex: SizeInt; Count: SizeInt);
  1260. begin
  1261. System.Move(Src.Value^, PUInt16(Dest)[StartIndex], Count * SizeOf(UInt16));
  1262. end;
  1263. class procedure TMarshal.Copy(const Src: TInt16Array; StartIndex: SizeInt; Dest: TPtrWrapper; Count: SizeInt);
  1264. begin
  1265. System.Move(PInt16(Src)[StartIndex], Dest.Value^, Count * SizeOf(Int16));
  1266. end;
  1267. class procedure TMarshal.Copy(Src: TPtrWrapper; var Dest: TInt16Array; StartIndex: SizeInt; Count: SizeInt);
  1268. begin
  1269. System.Move(Src.Value^, PInt16(Dest)[StartIndex], Count * SizeOf(Int16));
  1270. end;
  1271. class procedure TMarshal.Copy(const Src: TInt32Array; StartIndex: SizeInt; Dest: TPtrWrapper; Count: SizeInt);
  1272. begin
  1273. System.Move(PInt32(Src)[StartIndex], Dest.Value^, Count * SizeOf(Int32));
  1274. end;
  1275. class procedure TMarshal.Copy(Src: TPtrWrapper; var Dest: TInt32Array; StartIndex: SizeInt; Count: SizeInt);
  1276. begin
  1277. System.Move(Src.Value^, PInt32(Dest)[StartIndex], Count * SizeOf(Int32));
  1278. end;
  1279. class procedure TMarshal.Copy(const Src: TInt64Array; StartIndex: SizeInt; Dest: TPtrWrapper; Count: SizeInt);
  1280. begin
  1281. System.Move(PInt64(Src)[StartIndex], Dest.Value^, Count * SizeOf(Int64));
  1282. end;
  1283. class procedure TMarshal.Copy(Src: TPtrWrapper; var Dest: TInt64Array; StartIndex: SizeInt; Count: SizeInt);
  1284. begin
  1285. System.Move(Src.Value^, PInt64(Dest)[StartIndex], Count * SizeOf(Int64));
  1286. end;
  1287. class procedure TMarshal.Copy(const Src: TPtrWrapperArray; StartIndex: SizeInt; Dest: TPtrWrapper; Count: SizeInt);
  1288. begin
  1289. System.Move(PPointer(Src)[StartIndex], Dest.Value^, Count * SizeOf(TPtrWrapper));
  1290. end;
  1291. class procedure TMarshal.Copy(Src: TPtrWrapper; var Dest: TPtrWrapperArray; StartIndex: SizeInt; Count: SizeInt);
  1292. begin
  1293. System.Move(Src.Value^, PPointer(Dest)[StartIndex], Count * SizeOf(TPtrWrapper));
  1294. end;
  1295. generic class function TMarshal.FixArray<T>(const Arr: specialize TArray<T>): TPtrWrapper;
  1296. begin
  1297. Result.Value := nil;
  1298. specialize TArray<T>(Result) := Arr;
  1299. end;
  1300. generic class procedure TMarshal.UnfixArray<T>(ArrPtr: TPtrWrapper);
  1301. begin
  1302. Finalize(specialize TArray<T>(ArrPtr));
  1303. end;
  1304. class function TMarshal.ReadByte(Ptr: TPtrWrapper; Ofs: SizeInt = 0): Byte;
  1305. begin
  1306. Result := PByte(Ptr.Value + Ofs)^;
  1307. end;
  1308. class procedure TMarshal.WriteByte(Ptr: TPtrWrapper; Ofs: SizeInt; Value: Byte);
  1309. begin
  1310. PByte(Ptr.Value + Ofs)^ := Value;
  1311. end;
  1312. class procedure TMarshal.WriteByte(Ptr: TPtrWrapper; Value: Byte);
  1313. begin
  1314. PByte(Ptr.Value)^ := Value;
  1315. end;
  1316. class function TMarshal.ReadInt16(Ptr: TPtrWrapper; Ofs: SizeInt = 0): Int16;
  1317. begin
  1318. Result := PInt16(Ptr.Value + Ofs)^;
  1319. end;
  1320. class procedure TMarshal.WriteInt16(Ptr: TPtrWrapper; Ofs: SizeInt; Value: Int16);
  1321. begin
  1322. PInt16(Ptr.Value + Ofs)^ := Value;
  1323. end;
  1324. class procedure TMarshal.WriteInt16(Ptr: TPtrWrapper; Value: Int16);
  1325. begin
  1326. PInt16(Ptr.Value)^ := Value;
  1327. end;
  1328. class function TMarshal.ReadInt32(Ptr: TPtrWrapper; Ofs: SizeInt = 0): Int32;
  1329. begin
  1330. Result := PInt32(Ptr.Value + Ofs)^;
  1331. end;
  1332. class procedure TMarshal.WriteInt32(Ptr: TPtrWrapper; Ofs: SizeInt; Value: Int32);
  1333. begin
  1334. PInt32(Ptr.Value + Ofs)^ := Value;
  1335. end;
  1336. class procedure TMarshal.WriteInt32(Ptr: TPtrWrapper; Value: Int32);
  1337. begin
  1338. PInt32(Ptr.Value)^ := Value;
  1339. end;
  1340. class function TMarshal.ReadInt64(Ptr: TPtrWrapper; Ofs: SizeInt = 0): Int64;
  1341. begin
  1342. Result := PInt64(Ptr.Value + Ofs)^;
  1343. end;
  1344. class procedure TMarshal.WriteInt64(Ptr: TPtrWrapper; Ofs: SizeInt; Value: Int64);
  1345. begin
  1346. PInt64(Ptr.Value + Ofs)^ := Value;
  1347. end;
  1348. class procedure TMarshal.WriteInt64(Ptr: TPtrWrapper; Value: Int64);
  1349. begin
  1350. PInt64(Ptr.Value)^ := Value;
  1351. end;
  1352. class function TMarshal.ReadPtr(Ptr: TPtrWrapper; Ofs: SizeInt = 0): TPtrWrapper;
  1353. begin
  1354. Result.Value := PPointer(Ptr.Value + Ofs)^;
  1355. end;
  1356. class procedure TMarshal.WritePtr(Ptr: TPtrWrapper; Ofs: SizeInt; Value: TPtrWrapper);
  1357. begin
  1358. PPointer(Ptr.Value + Ofs)^ := Value.Value;
  1359. end;
  1360. class procedure TMarshal.WritePtr(Ptr, Value: TPtrWrapper);
  1361. begin
  1362. PPointer(Ptr.Value)^ := Value.Value;
  1363. end;
  1364. {$IFDEF FPC_HAS_FEATURE_UNICODESTRINGS}
  1365. class function TMarshal.AsAnsi(const S: UnicodeString): AnsiString;
  1366. begin
  1367. Result := AnsiString(S);
  1368. end;
  1369. class function TMarshal.AsAnsi(S: PUnicodeChar): AnsiString;
  1370. begin
  1371. result := AnsiString(S);
  1372. end;
  1373. class function TMarshal.InOutString(const S: UnicodeString): PUnicodeChar;
  1374. begin
  1375. Result := PUnicodeChar(S);
  1376. end;
  1377. class function TMarshal.InString(const S: UnicodeString): PUnicodeChar;
  1378. begin
  1379. Result := PUnicodeChar(S);
  1380. end;
  1381. class function TMarshal.OutString(const S: UnicodeString): PUnicodeChar;
  1382. begin
  1383. Result := PUnicodeChar(S);
  1384. end;
  1385. class function TMarshal.FixString(var Str: UnicodeString): TPtrWrapper;
  1386. begin
  1387. UniqueString(Str);
  1388. Result := UnsafeFixString(Str);
  1389. end;
  1390. class procedure TMarshal.UnfixString(Ptr: TPtrWrapper);
  1391. begin
  1392. if Ptr.Value <> PUnicodeChar('') then
  1393. Finalize(UnicodeString(Ptr));
  1394. end;
  1395. class function TMarshal.UnsafeFixString(const Str: UnicodeString): TPtrWrapper;
  1396. begin
  1397. if Length(Str) = 0 then
  1398. begin
  1399. Result.Value := PUnicodeChar('');
  1400. Exit;
  1401. end;
  1402. Result.Value := nil;
  1403. UnicodeString(Result) := Str;
  1404. end;
  1405. class function TMarshal.AllocStringAsAnsi(const Str: UnicodeString): TPtrWrapper;
  1406. begin
  1407. Result := AllocStringAsAnsi(PUnicodeChar(Pointer(Str)), Length(Str), DefaultSystemCodePage);
  1408. end;
  1409. class function TMarshal.AllocStringAsAnsi(const Str: UnicodeString; CodePage: Word): TPtrWrapper;
  1410. begin
  1411. Result := AllocStringAsAnsi(PUnicodeChar(Pointer(Str)), Length(Str), CodePage);
  1412. end;
  1413. class function TMarshal.AllocStringAsAnsi(S: PUnicodeChar): TPtrWrapper;
  1414. begin
  1415. Result := AllocStringAsAnsi(S, Length(S), DefaultSystemCodePage);
  1416. end;
  1417. class function TMarshal.AllocStringAsAnsi(S: PUnicodeChar; CodePage: Word): TPtrWrapper;
  1418. begin
  1419. Result := AllocStringAsAnsi(S, Length(S), CodePage);
  1420. end;
  1421. class function TMarshal.AllocStringAsUnicode(const Str: UnicodeString): TPtrWrapper;
  1422. var
  1423. NBytes: SizeUint;
  1424. begin
  1425. NBytes := (Length(Str) + 1) * SizeOf(UnicodeChar);
  1426. Result.Value := System.GetMem(NBytes);
  1427. System.Move(PUnicodeChar(Str)^, Result.Value^, NBytes);
  1428. end;
  1429. class function TMarshal.AllocStringAsUtf8(const Str: UnicodeString): TPtrWrapper;
  1430. begin
  1431. Result := AllocStringAsAnsi(PUnicodeChar(Pointer(Str)), Length(Str), CP_UTF8);
  1432. end;
  1433. class function TMarshal.AllocStringAsUtf8(S: PUnicodeChar): TPtrWrapper;
  1434. begin
  1435. Result := AllocStringAsAnsi(S, Length(S), CP_UTF8);
  1436. end;
  1437. class function TMarshal.AllocStringAsAnsi(S: PUnicodeChar; Len: SizeInt; CodePage: Word): TPtrWrapper;
  1438. var
  1439. U2ARes: AnsiString;
  1440. NBytes: SizeInt;
  1441. begin
  1442. U2ARes := ''; { Suppress warning. }
  1443. WideStringManager.Unicode2AnsiMoveProc(S, U2ARes, CodePage, Len);
  1444. if Length(U2ARes) = 0 then
  1445. begin
  1446. Result.Value := nil;
  1447. Exit;
  1448. end;
  1449. { Could instead avoid the second allocation, assuming U2ARes.RefCount = 1:
  1450. System.Move(Pointer(U2ARes)^, (Pointer(U2ARes) - AnsiStringHeaderSize)^, (Length(U2ARes) + 1) * SizeOf(AnsiChar));
  1451. Result.FValue := Pointer(U2ARes) - AnsiStringHeaderSize;
  1452. Pointer(U2ARes) := nil; }
  1453. NBytes := (Length(U2ARes) + 1) * SizeOf(AnsiChar);
  1454. Result.Value := System.GetMem(NBytes);
  1455. System.Move(PAnsiChar(U2ARes)^, Result.Value^, NBytes);
  1456. end;
  1457. class procedure TMarshal.Copy(const Src: TUnicodeCharArray; StartIndex: SizeInt; Dest: TPtrWrapper; Count: SizeInt);
  1458. begin
  1459. System.Move(PUnicodeChar(Src)[StartIndex], Dest.Value^, Count * SizeOf(UnicodeChar));
  1460. end;
  1461. class procedure TMarshal.Copy(Src: TPtrWrapper; var Dest: TUnicodeCharArray; StartIndex: SizeInt; Count: SizeInt);
  1462. begin
  1463. System.Move(Src.Value^, PUnicodeChar(Dest)[StartIndex], Count * SizeOf(UnicodeChar));
  1464. end;
  1465. class function TMarshal.ReadStringAsAnsi(Ptr: TPtrWrapper; Len: SizeInt = -1): UnicodeString;
  1466. begin
  1467. Result := ReadStringAsAnsi(DefaultSystemCodePage, Ptr, Len);
  1468. end;
  1469. class function TMarshal.ReadStringAsAnsi(CodePage: Word; Ptr: TPtrWrapper; Len: SizeInt = -1): UnicodeString;
  1470. begin
  1471. { Here and below, IndexByte/Word assume that, when Len >= 0, either:
  1472. - Up to Len characters are accessible in Ptr;
  1473. - IndexByte/Word cannot access invalid memory past the searched character
  1474. (e.g. i386.inc and x86_64.inc IndexByte/Word versions are specifically designed not to). }
  1475. if Len < 0 then
  1476. Len := IndexByte(Ptr.Value^, Len, 0);
  1477. Result := ''; { Suppress warning. }
  1478. WideStringManager.Ansi2UnicodeMoveProc(Ptr.Value, CodePage, Result, Len);
  1479. end;
  1480. class function TMarshal.ReadStringAsAnsiUpTo(CodePage: Word; Ptr: TPtrWrapper; MaxLen: SizeInt): UnicodeString;
  1481. var
  1482. Len: SizeInt;
  1483. begin
  1484. Len := IndexByte(Ptr.Value^, MaxLen, 0);
  1485. if Len < 0 then
  1486. Len := MaxLen;
  1487. Result := ReadStringAsAnsi(CodePage, Ptr, Len);
  1488. end;
  1489. class procedure TMarshal.WriteStringAsAnsi(Ptr: TPtrWrapper; const Value: UnicodeString; MaxCharsIncNull: SizeInt);
  1490. begin
  1491. WriteStringAsAnsi(Ptr, 0, Value, MaxCharsIncNull, DefaultSystemCodePage);
  1492. end;
  1493. class procedure TMarshal.WriteStringAsAnsi(Ptr: TPtrWrapper; const Value: UnicodeString; MaxCharsIncNull: SizeInt; CodePage: Word);
  1494. begin
  1495. WriteStringAsAnsi(Ptr, 0, Value, MaxCharsIncNull, CodePage);
  1496. end;
  1497. class procedure TMarshal.WriteStringAsAnsi(Ptr: TPtrWrapper; Ofs: SizeInt; const Value: UnicodeString; MaxCharsIncNull: SizeInt);
  1498. begin
  1499. WriteStringAsAnsi(Ptr, Ofs, Value, MaxCharsIncNull, DefaultSystemCodePage);
  1500. end;
  1501. class procedure TMarshal.WriteStringAsAnsi(Ptr: TPtrWrapper; Ofs: SizeInt; const Value: UnicodeString; MaxCharsIncNull: SizeInt; CodePage: Word);
  1502. var
  1503. U2ARes: AnsiString;
  1504. ValueLen, U2AResLen: SizeInt;
  1505. begin
  1506. U2ARes := ''; { Suppress warning. }
  1507. ValueLen := Length(Value);
  1508. { Delphi null-terminates iff MaxCharsIncNull < 0, so MaxCharsIncNull is actually just MaxChars. }
  1509. if (MaxCharsIncNull > 0) and (MaxCharsIncNull < ValueLen) then
  1510. ValueLen := MaxCharsIncNull; { UTF-16 → ANSI should never shrink element count, so limit the number of characters analyzed. }
  1511. WideStringManager.Unicode2AnsiMoveProc(PUnicodeChar(Pointer(Value)), U2ARes, CodePage, ValueLen);
  1512. U2AResLen := Length(U2ARes);
  1513. if (MaxCharsIncNull >= 0) and (MaxCharsIncNull < U2AResLen) then
  1514. U2AResLen := MaxCharsIncNull;
  1515. System.Move(PAnsiChar(Pointer(U2ARes))^, (Ptr.Value + Ofs)^, U2AResLen * SizeOf(AnsiChar));
  1516. if MaxCharsIncNull < 0 then
  1517. PAnsiChar(Ptr.Value + Ofs)[U2AResLen] := #0;
  1518. end;
  1519. class function TMarshal.ReadStringAsUnicode(Ptr: TPtrWrapper; Len: SizeInt = -1): UnicodeString;
  1520. begin
  1521. if Len < 0 then
  1522. Len := Length(PUnicodeChar(Ptr.Value));
  1523. Result := ''; { Suppress warning. }
  1524. SetLength(Result, Len);
  1525. System.Move(Ptr.Value^, Pointer(Result)^, Len * SizeOf(UnicodeChar));
  1526. end;
  1527. class function TMarshal.ReadStringAsUnicodeUpTo(Ptr: TPtrWrapper; MaxLen: SizeInt): UnicodeString;
  1528. var
  1529. Len: SizeInt;
  1530. begin
  1531. Len := IndexWord(Ptr.Value^, MaxLen, 0);
  1532. if Len < 0 then
  1533. Len := MaxLen;
  1534. Result := ReadStringAsUnicode(Ptr, Len);
  1535. end;
  1536. class procedure TMarshal.WriteStringAsUnicode(Ptr: TPtrWrapper; const Value: UnicodeString; MaxCharsIncNull: SizeInt);
  1537. begin
  1538. WriteStringAsUnicode(Ptr, 0, Value, MaxCharsIncNull);
  1539. end;
  1540. class procedure TMarshal.WriteStringAsUnicode(Ptr: TPtrWrapper; Ofs: SizeInt; const Value: UnicodeString; MaxCharsIncNull: SizeInt);
  1541. var
  1542. Len: SizeInt;
  1543. begin
  1544. { Again, Delphi null-terminates iff MaxCharsIncNull < 0, so MaxCharsIncNull is actually just MaxChars. }
  1545. Len := Length(Value);
  1546. if (MaxCharsIncNull >= 0) and (MaxCharsIncNull < Len) then
  1547. Len := MaxCharsIncNull;
  1548. System.Move(Pointer(Value)^, (Ptr.Value + Ofs)^, Len * SizeOf(UnicodeChar));
  1549. if MaxCharsIncNull < 0 then
  1550. PUnicodeChar(Ptr.Value + Ofs)[Len] := #0;
  1551. end;
  1552. class function TMarshal.ReadStringAsUtf8(Ptr: TPtrWrapper; Len: SizeInt = -1): UnicodeString;
  1553. begin
  1554. Result := ReadStringAsAnsi(CP_UTF8, Ptr, Len);
  1555. end;
  1556. class function TMarshal.ReadStringAsUtf8UpTo(Ptr: TPtrWrapper; MaxLen: SizeInt): UnicodeString;
  1557. begin
  1558. Result := ReadStringAsAnsiUpTo(CP_UTF8, Ptr, MaxLen);
  1559. end;
  1560. class procedure TMarshal.WriteStringAsUtf8(Ptr: TPtrWrapper; const Value: UnicodeString; MaxCharsIncNull: SizeInt);
  1561. begin
  1562. WriteStringAsAnsi(Ptr, Value, MaxCharsIncNull, CP_UTF8);
  1563. end;
  1564. class procedure TMarshal.WriteStringAsUtf8(Ptr: TPtrWrapper; Ofs: SizeInt; const Value: UnicodeString; MaxCharsIncNull: SizeInt);
  1565. begin
  1566. WriteStringAsAnsi(Ptr, Ofs, Value, MaxCharsIncNull, CP_UTF8);
  1567. end;
  1568. {$ENDIF}
  1569. {$IFDEF SYSTEM_HAS_FEATURE_MONITOR}
  1570. {$i monitor.inc}
  1571. {$ENDIF}