objpas.inc 58 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917
  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. I:=instancesize;
  355. { the size is saved at offset 0 }
  356. fillchar(instance^, InstanceSize, 0);
  357. { insert VMT pointer into the new created memory area }
  358. { (in class methods self contains the VMT!) }
  359. {$IFNDEF SYSTEM_HAS_FEATURE_MONITOR}
  360. ppointer(instance)^:=pointer(self);
  361. {$ELSE}
  362. {$IFDEF VER3_2}
  363. // In 3.2.x Compiler (used during bootstrap) still inserts VMT at offset...
  364. ppointer(PByte(instance)+SizeOf(Pointer))^:=pointer(self);
  365. {$ELSE}
  366. // As of 3.3.x compiler forces insert of VMT at first pos.
  367. ppointer(instance)^:=pointer(self);
  368. {$ENDIF}
  369. {$ENDIF}
  370. if assigned(PVmt(self)^.vIntfTable) then
  371. InitInterfacePointers(self,instance);
  372. {$ifdef FPC_HAS_FEATURE_RTTI}
  373. { for management operators like initialize call int_initialize }
  374. vmt := PVmt(self);
  375. if assigned(vmt) then
  376. begin
  377. inittable:=vmt^.vInitTable;
  378. if assigned(inittable) then
  379. begin
  380. mopinittable:=RTTIRecordMopInitTable(inittable);
  381. if assigned(mopinittable) then
  382. begin
  383. {$push}
  384. { ensure that no range check errors pop up with the [0..0] array }
  385. {$R-}
  386. for i:=0 to mopinittable^.Count-1 do
  387. TRTTIRecVarOp(mopinittable^.Entries[i].ManagmentOperator)(PByte(Instance)+mopinittable^.Entries[i].FieldOffset);
  388. {$pop}
  389. end;
  390. end;
  391. end;
  392. {$endif def FPC_HAS_FEATURE_RTTI}
  393. InitInstance:=TObject(Instance);
  394. end;
  395. class function TObject.ClassParent : tclass;
  396. begin
  397. { type of self is class of tobject => it points to the vmt }
  398. { the parent vmt is saved at offset vmtParent }
  399. classparent:=tclass(PVmt(Self)^.vParent);
  400. end;
  401. class function TObject.NewInstance : tobject;
  402. var
  403. p : pointer;
  404. begin
  405. getmem(p, InstanceSize);
  406. if p <> nil then
  407. InitInstance(p);
  408. NewInstance:=TObject(p);
  409. end;
  410. procedure TObject.FreeInstance;
  411. begin
  412. CleanupInstance;
  413. FreeMem(Pointer(Self));
  414. end;
  415. class function TObject.ClassType : TClass;
  416. begin
  417. ClassType:=TClass(Pointer(Self))
  418. end;
  419. type
  420. {$PUSH}
  421. {$PACKRECORDS NORMAL}
  422. tmethodnamerec =
  423. {$IFNDEF FPC_REQUIRES_PROPER_ALIGNMENT}
  424. packed
  425. {$ENDIF FPC_REQUIRES_PROPER_ALIGNMENT}
  426. record
  427. name : pshortstring;
  428. addr : codepointer;
  429. end;
  430. tmethodnametable =
  431. {$IFNDEF FPC_REQUIRES_PROPER_ALIGNMENT}
  432. packed
  433. {$ENDIF FPC_REQUIRES_PROPER_ALIGNMENT}
  434. record
  435. count : dword;
  436. entries : packed array[0..0] of tmethodnamerec;
  437. end;
  438. {$POP}
  439. pmethodnametable = ^tmethodnametable;
  440. class function TObject.MethodAddress(const name : shortstring) : codepointer;
  441. var
  442. methodtable : pmethodnametable;
  443. i : longint; // in case count=0
  444. ovmt : PVmt;
  445. begin
  446. ovmt:=PVmt(self);
  447. while assigned(ovmt) do
  448. begin
  449. methodtable:=pmethodnametable(ovmt^.vMethodTable);
  450. if assigned(methodtable) then
  451. begin
  452. for i:=0 to methodtable^.count-1 do
  453. if ShortCompareText(methodtable^.entries[i].name^, name)=0 then
  454. begin
  455. MethodAddress:=methodtable^.entries[i].addr;
  456. exit;
  457. end;
  458. end;
  459. ovmt := ovmt^.vParent;
  460. end;
  461. MethodAddress:=nil;
  462. end;
  463. class function TObject.MethodName(address : codepointer) : shortstring;
  464. var
  465. methodtable : pmethodnametable;
  466. i : longint; // in case count=0
  467. ovmt : PVmt;
  468. begin
  469. ovmt:=PVmt(self);
  470. while assigned(ovmt) do
  471. begin
  472. methodtable:=pmethodnametable(ovmt^.vMethodTable);
  473. if assigned(methodtable) then
  474. begin
  475. for i:=0 to methodtable^.count-1 do
  476. if methodtable^.entries[i].addr=address then
  477. begin
  478. MethodName:=methodtable^.entries[i].name^;
  479. exit;
  480. end;
  481. end;
  482. ovmt := ovmt^.vParent;
  483. end;
  484. MethodName:='';
  485. end;
  486. function TObject.FieldAddress(const name : shortstring) : pointer;
  487. {The following is copied to the typinfo unit. If it is changed here, change it there as well ! }
  488. type
  489. {$PUSH}
  490. {$PACKRECORDS NORMAL}
  491. PFieldInfo = ^TFieldInfo;
  492. TFieldInfo =
  493. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  494. packed
  495. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  496. record
  497. FieldOffset: SizeUInt;
  498. ClassTypeIndex: Word;
  499. Name: ShortString;
  500. end;
  501. PFieldTable = ^TFieldTable;
  502. TFieldTable =
  503. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  504. packed
  505. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  506. record
  507. FieldCount: Word;
  508. ClassTable: Pointer;
  509. { should be array[Word] of TFieldInfo; but
  510. Elements have variant size! force at least proper alignment }
  511. Fields: array[0..0] of TFieldInfo
  512. end;
  513. {$POP}
  514. var
  515. ovmt: PVmt;
  516. FieldTable: PFieldTable;
  517. FieldInfo: PFieldInfo;
  518. i: longint;
  519. begin
  520. if Length(name) > 0 then
  521. begin
  522. ovmt := PVmt(ClassType);
  523. while ovmt <> nil do
  524. begin
  525. FieldTable := PFieldTable(ovmt^.vFieldTable);
  526. if FieldTable <> nil then
  527. begin
  528. FieldInfo := @FieldTable^.Fields[0];
  529. for i := 0 to FieldTable^.FieldCount - 1 do
  530. begin
  531. if ShortCompareText(FieldInfo^.Name, name) = 0 then
  532. begin
  533. fieldaddress := Pointer(Self) + FieldInfo^.FieldOffset;
  534. exit;
  535. end;
  536. FieldInfo := PFieldInfo(PByte(@FieldInfo^.Name) + 1 + Length(FieldInfo^.Name));
  537. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  538. { align to largest field of TFieldInfo }
  539. FieldInfo := Align(FieldInfo, SizeOf(PtrUInt));
  540. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  541. end;
  542. end;
  543. { Try again with the parent class type }
  544. ovmt:=ovmt^.vParent;
  545. end;
  546. end;
  547. fieldaddress:=nil;
  548. end;
  549. function TObject.SafeCallException(exceptobject : tobject;
  550. exceptaddr : codepointer) : HResult;
  551. begin
  552. safecallexception:=E_UNEXPECTED;
  553. end;
  554. class function TObject.ClassInfo : pointer;
  555. begin
  556. ClassInfo := PVmt(Self)^.vTypeInfo;
  557. end;
  558. class function TObject.ClassName : ShortString;
  559. begin
  560. ClassName := PVmt(Self)^.vClassName^;
  561. end;
  562. class function TObject.ClassNameIs(const name : RTLString) : boolean;
  563. var
  564. SS : ShortString;
  565. begin
  566. SS:=ShortString(Name);
  567. ClassNameIs:=ShortCompareText(PVmt(Self)^.vClassName^, SS) = 0;
  568. end;
  569. class function TObject.InheritsFrom(aclass : TClass) : Boolean;
  570. var
  571. vmt: PVmt;
  572. begin
  573. if assigned(aclass) then
  574. begin
  575. vmt:=PVmt(self);
  576. while assigned(vmt) and (vmt <> PVmt(aclass)) do
  577. vmt := vmt^.vParent;
  578. InheritsFrom := (vmt = PVmt(aclass));
  579. end
  580. else
  581. inheritsFrom := False;
  582. end;
  583. class function TObject.stringmessagetable : pstringmessagetable;
  584. begin
  585. stringmessagetable:=PVmt(Self)^.vMsgStrPtr;
  586. end;
  587. type
  588. tmessagehandler = procedure(var msg) of object;
  589. procedure TObject.Dispatch(var message);
  590. type
  591. {$PUSH}
  592. {$PACKRECORDS NORMAL}
  593. PMsgIntTable = ^TMsgIntTable;
  594. TMsgIntTable = record
  595. index : dword;
  596. method : codepointer;
  597. end;
  598. PMsgInt = ^TMsgInt;
  599. TMsgInt = record
  600. count : longint;
  601. msgs : array[0..0] of TMsgIntTable;
  602. end;
  603. {$POP}
  604. var
  605. index : dword;
  606. count,i : longint;
  607. msgtable : PMsgIntTable;
  608. p : PMsgInt;
  609. ovmt : PVmt;
  610. msghandler : tmessagehandler;
  611. begin
  612. index:=dword(message);
  613. ovmt := PVmt(ClassType);
  614. while assigned(ovmt) do
  615. begin
  616. // See if we have messages at all in this class.
  617. p:=PMsgInt(ovmt^.vDynamicTable);
  618. If Assigned(p) then
  619. begin
  620. msgtable:=@p^.msgs;
  621. count:=p^.count;
  622. end
  623. else
  624. Count:=0;
  625. { later, we can implement a binary search here }
  626. for i:=0 to count-1 do
  627. begin
  628. if index=msgtable[i].index then
  629. begin
  630. TMethod(msghandler).Code:=msgtable[i].method;
  631. TMethod(msghandler).Data:=self;
  632. msghandler(message);
  633. exit;
  634. end;
  635. end;
  636. ovmt:=ovmt^.vParent;
  637. end;
  638. DefaultHandler(message);
  639. end;
  640. procedure TObject.DispatchStr(var message);
  641. var
  642. name : shortstring;
  643. count,i : longint;
  644. msgstrtable : pmsgstrtable;
  645. p: pstringmessagetable;
  646. ovmt : PVmt;
  647. msghandler : tmessagehandler;
  648. begin
  649. name:=pshortstring(@message)^;
  650. ovmt:=PVmt(ClassType);
  651. while assigned(ovmt) do
  652. begin
  653. p := ovmt^.vMsgStrPtr;
  654. if (P<>Nil) and (p^.count<>0) then
  655. begin
  656. count:=p^.count;
  657. msgstrtable:=@p^.msgstrtable;
  658. end
  659. else
  660. Count:=0;
  661. { later, we can implement a binary search here }
  662. for i:=0 to count-1 do
  663. begin
  664. if name=msgstrtable[i].name^ then
  665. begin
  666. TMethod(msghandler).Code:=msgstrtable[i].method;
  667. TMethod(msghandler).Data:=self;
  668. msghandler(message);
  669. exit;
  670. end;
  671. end;
  672. ovmt:=ovmt^.vParent;
  673. end;
  674. DefaultHandlerStr(message);
  675. end;
  676. procedure TObject.DefaultHandler(var message);
  677. begin
  678. end;
  679. procedure TObject.DefaultHandlerStr(var message);
  680. begin
  681. end;
  682. procedure TObject.CleanupInstance;
  683. var
  684. vmt : PVmt;
  685. temp : pointer;
  686. begin
  687. vmt := PVmt(ClassType);
  688. while vmt<>nil do
  689. begin
  690. Temp:= vmt^.vInitTable;
  691. {$ifdef FPC_HAS_FEATURE_RTTI}
  692. { The RTTI format matches one for records, except the type is tkClass.
  693. Since RecordRTTI does not check the type, calling it yields the desired result. }
  694. if Assigned(Temp) then
  695. RecordRTTI(Self,aligntoqword(Temp+2+PByte(Temp)[1]),@int_finalize);
  696. {$endif def FPC_HAS_FEATURE_RTTI}
  697. vmt:= vmt^.vParent;
  698. end;
  699. {$IFDEF SYSTEM_HAS_FEATURE_MONITOR}
  700. if Assigned(_MonitorData) then
  701. TMonitor.FreeMonitorData(_MonitorData);
  702. {$ENDIF}
  703. end;
  704. procedure TObject.AfterConstruction;
  705. begin
  706. end;
  707. procedure TObject.BeforeDestruction;
  708. begin
  709. end;
  710. function IsGUIDEqual(const guid1, guid2: tguid): boolean;
  711. begin
  712. IsGUIDEqual:=
  713. (guid1.D1=guid2.D1) and
  714. (PDWORD(@guid1.D2)^=PDWORD(@guid2.D2)^) and
  715. (PDWORD(@guid1.D4[0])^=PDWORD(@guid2.D4[0])^) and
  716. (PDWORD(@guid1.D4[4])^=PDWORD(@guid2.D4[4])^);
  717. end;
  718. // Use of managed types should be avoided here; implicit _Addref/_Release
  719. // will end up in unpredictable behaviour if called on CORBA interfaces.
  720. type
  721. TInterfaceGetter = procedure(out Obj) of object;
  722. TClassGetter = function: TObject of object;
  723. function GetInterfaceByEntry(Instance: pointer; IEntry: pinterfaceentry; out obj): boolean;
  724. var
  725. Getter: TMethod;
  726. begin
  727. Pointer(Obj) := nil;
  728. Getter.Data := Instance;
  729. if Assigned(IEntry) and Assigned(Instance) then
  730. begin
  731. case IEntry^.IType of
  732. etStandard:
  733. Pointer(Obj) := PByte(instance)+IEntry^.IOffset;
  734. etFieldValue, etFieldValueClass:
  735. Pointer(obj) := PPointer(PByte(Instance)+IEntry^.IOffset)^;
  736. etVirtualMethodResult:
  737. begin
  738. // IOffset is relative to the VMT, not to instance.
  739. Getter.code := PCodePointer(PByte(PPointer(Instance)^) + IEntry^.IOffset)^;
  740. TInterfaceGetter(Getter)(obj);
  741. end;
  742. etVirtualMethodClass:
  743. begin
  744. // IOffset is relative to the VMT, not to instance.
  745. Getter.code := PCodePointer(PByte(PPointer(Instance)^) + IEntry^.IOffset)^;
  746. TObject(obj) := TClassGetter(Getter)();
  747. end;
  748. etStaticMethodResult:
  749. begin
  750. Getter.code := IEntry^.IOffsetAsCodePtr;
  751. TInterfaceGetter(Getter)(obj);
  752. end;
  753. etStaticMethodClass:
  754. begin
  755. Getter.code := IEntry^.IOffsetAsCodePtr;
  756. TObject(obj) := TClassGetter(Getter)();
  757. end;
  758. end;
  759. end;
  760. result := assigned(pointer(obj));
  761. end;
  762. function TObject.GetInterface(const iid : tguid;out obj) : boolean;
  763. var
  764. IEntry: PInterfaceEntry;
  765. Instance: TObject;
  766. begin
  767. if IsGUIDEqual(IObjectInstance,iid) then
  768. begin
  769. TObject(Obj) := Self;
  770. Result := True;
  771. Exit;
  772. end;
  773. Instance := self;
  774. repeat
  775. IEntry := Instance.GetInterfaceEntry(iid);
  776. result := GetInterfaceByEntry(Instance, IEntry, obj);
  777. if (not result) or
  778. (IEntry^.IType in [etStandard, etFieldValue,
  779. etStaticMethodResult, etVirtualMethodResult]) then
  780. Break;
  781. { if interface is implemented by a class-type property or field,
  782. continue search }
  783. Instance := TObject(obj);
  784. until False;
  785. { Getter function will normally AddRef, so adding another reference here
  786. will cause memleak. }
  787. if result and (IEntry^.IType in [etStandard, etFieldValue]) then
  788. IInterface(obj)._AddRef;
  789. end;
  790. function TObject.GetInterfaceWeak(const iid : tguid; out obj) : boolean;
  791. var
  792. IEntry: PInterfaceEntry;
  793. Instance: TObject;
  794. begin
  795. if IsGUIDEqual(IObjectInstance,iid) then
  796. begin
  797. TObject(Obj) := Self;
  798. Result := True;
  799. Exit;
  800. end;
  801. Instance := self;
  802. repeat
  803. IEntry := Instance.GetInterfaceEntry(iid);
  804. result := GetInterfaceByEntry(Instance, IEntry, obj);
  805. if (not result) or
  806. (IEntry^.IType in [etStandard, etFieldValue,
  807. etStaticMethodResult, etVirtualMethodResult]) then
  808. Break;
  809. { if interface is implemented by a class-type property or field,
  810. continue search }
  811. Instance := TObject(obj);
  812. until False;
  813. { Getter function will normally AddRef, so we have to release it,
  814. else the ref is not weak. }
  815. if result and not (IEntry^.IType in [etStandard, etFieldValue]) then
  816. IInterface(obj)._Release;
  817. end;
  818. function TObject.GetInterfaceByStr(const iidstr : shortstring;out obj) : boolean;
  819. var
  820. IEntry: PInterfaceEntry;
  821. Instance: TObject;
  822. begin
  823. Instance := self;
  824. repeat
  825. IEntry := Instance.GetInterfaceEntryByStr(iidstr);
  826. result := GetInterfaceByEntry(Instance, IEntry, obj);
  827. if (not result) or
  828. (IEntry^.IType in [etStandard, etFieldValue,
  829. etStaticMethodResult, etVirtualMethodResult]) then
  830. Break;
  831. { if interface is implemented by a class-type property or field,
  832. continue search }
  833. Instance := TObject(obj);
  834. until False;
  835. { Getter function will normally AddRef, so adding another reference here
  836. will cause memleak. (com interfaces only!) }
  837. if result and Assigned(IEntry^.IID) and (IEntry^.IType in [etStandard, etFieldValue]) then
  838. IInterface(obj)._AddRef;
  839. end;
  840. function TObject.GetInterface(const iidstr : shortstring;out obj) : boolean;
  841. begin
  842. Result := GetInterfaceByStr(iidstr,obj);
  843. end;
  844. class function TObject.GetInterfaceEntry(const iid : tguid) : pinterfaceentry;
  845. var
  846. i: longint;
  847. intftable: pinterfacetable;
  848. ovmt: PVmt;
  849. begin
  850. ovmt := PVmt(Self);
  851. while Assigned(ovmt) and Assigned(ovmt^.vIntftable) do
  852. begin
  853. intftable:=ovmt^.vIntfTable;
  854. for i:=0 to intftable^.EntryCount-1 do
  855. begin
  856. result:=@intftable^.Entries[i];
  857. if assigned(Result^.iid) and IsGUIDEqual(Result^.iid^,iid) then
  858. Exit;
  859. end;
  860. ovmt := ovmt^.vParent;
  861. end;
  862. result := nil;
  863. end;
  864. class function TObject.GetInterfaceEntryByStr(const iidstr : shortstring) : pinterfaceentry;
  865. var
  866. i: longint;
  867. intftable: pinterfacetable;
  868. ovmt: PVmt;
  869. begin
  870. ovmt := PVmt(Self);
  871. while Assigned(ovmt) and Assigned(ovmt^.vIntfTable) do
  872. begin
  873. intftable:=ovmt^.vIntfTable;
  874. for i:=0 to intftable^.EntryCount-1 do
  875. begin
  876. result:=@intftable^.Entries[i];
  877. if assigned(result^.iidstr) and (result^.iidstr^ = iidstr) then
  878. Exit;
  879. end;
  880. ovmt := ovmt^.vParent;
  881. end;
  882. result:=nil;
  883. end;
  884. class function TObject.GetInterfaceTable : pinterfacetable;
  885. begin
  886. getinterfacetable:=PVmt(Self)^.vIntfTable;
  887. end;
  888. class function TObject.UnitName : RTLString;
  889. {$ifdef FPC_HAS_FEATURE_RTTI}
  890. type
  891. TClassTypeInfo = {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}packed{$endif}record
  892. Attributes: Pointer;
  893. case TTypeKind of
  894. tkClass: (
  895. ClassType: TClass;
  896. ParentInfo: Pointer;
  897. PropCount: SmallInt;
  898. UnitName: ShortString;
  899. );
  900. { include for proper alignment }
  901. tkInt64: (
  902. Dummy: Int64;
  903. );
  904. end;
  905. PClassTypeInfo = ^TClassTypeInfo;
  906. var
  907. classtypeinfo: PClassTypeInfo;
  908. begin
  909. classtypeinfo:=ClassInfo;
  910. if Assigned(classtypeinfo) then
  911. begin
  912. // offset PTypeInfo by Length(Name) + 2 (ShortString length byte + SizeOf(Kind))
  913. inc(Pointer(classtypeinfo), PByte(Pointer(classtypeinfo)+1)^ + 2);
  914. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  915. classtypeinfo:=aligntoqword(classtypeinfo);
  916. {$endif}
  917. result:=classtypeinfo^.UnitName;
  918. end
  919. else
  920. result:='';
  921. end;
  922. {$else not FPC_HAS_FEATURE_RTTI}
  923. begin
  924. result:='';
  925. end;
  926. {$endif ndef FPC_HAS_FEATURE_RTTI}
  927. class function TObject.QualifiedClassName: RTLString;
  928. var
  929. uname: RTLString;
  930. begin
  931. uname := UnitName; //TODO: change 'UnitName' to 'UnitScope' as soon as RTL implement it
  932. if uname='' then
  933. result:=ClassName
  934. else
  935. result:=Concat(uname, '.', ClassName);
  936. end;
  937. function TObject.Equals(Obj: TObject) : boolean;
  938. begin
  939. result:=Obj=Self;
  940. end;
  941. function TObject.GetHashCode: PtrInt;
  942. begin
  943. result:=PtrInt(Self);
  944. end;
  945. function TObject.ToString: RTLString;
  946. begin
  947. result:=ClassName;
  948. end;
  949. procedure TObject.DisposeOf;
  950. begin
  951. Free;
  952. end;
  953. function TObject.GetDisposed : Boolean;
  954. begin
  955. Result:=False;
  956. end;
  957. procedure TObject.CheckDisposed;
  958. begin
  959. // Do nothing since we have no reference count.
  960. end;
  961. {$IFDEF SYSTEM_HAS_FEATURE_MONITOR}
  962. function TObject.SetMonitorData(aData,aCheckOld : Pointer) : Pointer;
  963. begin
  964. Result:=InterlockedCompareExchange(_MonitorData,aData,aCheckOld);
  965. end;
  966. function TObject.GetMonitorData: Pointer;
  967. begin
  968. Result:=_MonitorData;
  969. end;
  970. {$ENDIF}
  971. {****************************************************************************
  972. TINTERFACEDOBJECT
  973. ****************************************************************************}
  974. function TInterfacedObject.QueryInterface(
  975. {$IFDEF FPC_HAS_CONSTREF}constref{$ELSE}const{$ENDIF} iid : tguid;out obj) : longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
  976. begin
  977. if getinterface(iid,obj) then
  978. result:=S_OK
  979. else
  980. result:=longint(E_NOINTERFACE);
  981. end;
  982. function TInterfacedObject._AddRef : longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
  983. begin
  984. _addref:=frefcount;
  985. if _addref<>0 then
  986. begin
  987. if _addref>0 then
  988. _addref:=interlockedincrement(frefcount);
  989. exit;
  990. end;
  991. frefcount:=1; { Work non-atomically in the common case of refcount = 0 (typical state after the complete object construction). }
  992. _addref:=1;
  993. end;
  994. function TInterfacedObject._Release : longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
  995. begin
  996. _Release:=frefcount;
  997. if _Release<>1 then
  998. begin
  999. if _Release<=0 then { -1 means recursive call from destructor... 0 is impossible. }
  1000. exit;
  1001. _Release:=interlockeddecrement(frefcount);
  1002. if _Release>0 then
  1003. exit;
  1004. end
  1005. else
  1006. _Release:=0; { Work non-atomically in the common case of refcount = 1 (typical state for the last owner... which is often the only owner). }
  1007. frefcount:=-1; { Prevent recursive _Release from destroying twice (bug 32168). }
  1008. self.destroy;
  1009. end;
  1010. destructor TInterfacedObject.Destroy;
  1011. begin
  1012. // We must explicitly reset. Bug ID 32353
  1013. FRefCount:=0;
  1014. inherited Destroy;
  1015. end;
  1016. procedure TInterfacedObject.AfterConstruction;
  1017. begin
  1018. { we need to fix the refcount we forced in newinstance }
  1019. { further, it must be done in a thread safe way }
  1020. if frefcount=1 then
  1021. frefcount:=0 { Work non-atomically in the common case of refcount = 1 (usual state before AfterConstruction). }
  1022. else
  1023. declocked(frefcount);
  1024. end;
  1025. procedure TInterfacedObject.BeforeDestruction;
  1026. begin
  1027. if frefcount>0 then { Legitimate values: -1 if destroying by _Release, 0 if destroying manually. }
  1028. HandleError(204);
  1029. end;
  1030. class function TInterfacedObject.NewInstance : TObject;
  1031. begin
  1032. NewInstance:=inherited NewInstance;
  1033. if NewInstance<>nil then
  1034. TInterfacedObject(NewInstance).frefcount:=1;
  1035. end;
  1036. {****************************************************************************
  1037. TAGGREGATEDOBJECT
  1038. ****************************************************************************}
  1039. constructor TAggregatedObject.Create(const aController: IUnknown);
  1040. begin
  1041. inherited Create;
  1042. { do not keep a counted reference to the controller! }
  1043. fcontroller := Pointer(aController);
  1044. end;
  1045. function TAggregatedObject.QueryInterface(
  1046. {$IFDEF FPC_HAS_CONSTREF}constref{$ELSE}const{$ENDIF} iid : tguid;out obj) : longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
  1047. begin
  1048. Result := IUnknown(fcontroller).QueryInterface(iid, obj);
  1049. end;
  1050. function TAggregatedObject._AddRef : longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
  1051. begin
  1052. Result := IUnknown(fcontroller)._AddRef;
  1053. end;
  1054. function TAggregatedObject._Release : longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
  1055. begin
  1056. Result := IUnknown(fcontroller)._Release;
  1057. end;
  1058. function TAggregatedObject.GetController : IUnknown;
  1059. begin
  1060. Result := IUnknown(fcontroller);
  1061. end;
  1062. {****************************************************************************
  1063. TContainedOBJECT
  1064. ****************************************************************************}
  1065. function TContainedObject.QueryInterface(
  1066. {$IFDEF FPC_HAS_CONSTREF}constref{$ELSE}const{$ENDIF} iid : tguid;out obj) : longint; {$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
  1067. begin
  1068. if getinterface(iid,obj) then
  1069. result:=S_OK
  1070. else
  1071. result:=longint(E_NOINTERFACE);
  1072. end;
  1073. {****************************************************************************
  1074. TNoRefCountObject
  1075. ****************************************************************************}
  1076. function TNoRefCountObject.QueryInterface( {$IFDEF FPC_HAS_CONSTREF}constref{$ELSE}const{$ENDIF} iid : tguid;out obj) : longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
  1077. begin
  1078. if getinterface(iid,obj) then
  1079. result:=S_OK
  1080. else
  1081. result:=longint(E_NOINTERFACE);
  1082. end;
  1083. function TNoRefCountObject._AddRef : longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
  1084. begin
  1085. Result:=-1;
  1086. end;
  1087. function TNoRefCountObject._Release : longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
  1088. begin
  1089. Result:=-1;
  1090. end;
  1091. {****************************************************************************
  1092. TCustomAttribute
  1093. ****************************************************************************}
  1094. constructor TCustomAttribute.Create;
  1095. begin
  1096. inherited;
  1097. end;
  1098. {****************************************************************************
  1099. TUnimplementedAttribute
  1100. ****************************************************************************}
  1101. constructor TUnimplementedAttribute.Create;
  1102. begin
  1103. inherited;
  1104. end;
  1105. {****************************************************************************
  1106. TCustomStoredAttribute
  1107. ****************************************************************************}
  1108. constructor StoredAttribute.Create;
  1109. begin
  1110. end;
  1111. constructor StoredAttribute.Create(Const aFlag : Boolean);
  1112. begin
  1113. FFlag:=aFlag;
  1114. end;
  1115. constructor StoredAttribute.Create(Const aName : shortstring);
  1116. begin
  1117. FName:=aName;
  1118. end;
  1119. {****************************************************************************
  1120. TInterfaceThunk
  1121. ****************************************************************************}
  1122. Constructor TInterfaceThunk.Create(aCallback : TThunkCallback);
  1123. begin
  1124. FCallBack:=aCallBack;
  1125. end;
  1126. Procedure TInterfaceThunk.Thunk(aMethod: Longint; aCount : Longint; aData : PArgData);
  1127. begin
  1128. if Assigned(FCallBack) then
  1129. FCallBack(Self,aMethod,aCount,aData);
  1130. end;
  1131. function TInterfaceThunk.QueryInterface({$IFDEF FPC_HAS_CONSTREF}constref{$ELSE}const{$ENDIF} iid : tguid;out obj) : longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
  1132. begin
  1133. result:=longint(E_NOINTERFACE);
  1134. if (TMethod(FCallBack).Data<>Nil) then
  1135. // Query the object that created us, this is normally TVirtualInterface
  1136. // Take care: do not call QueryInterface, that would create a never-ending loop !!
  1137. if TObject(TMethod(FCallBack).Data).GetInterface(iid,obj) then
  1138. result:=S_OK;
  1139. if (Result<>S_OK) then
  1140. Result:=Inherited QueryInterface(iid,obj);
  1141. end;
  1142. function TInterfaceThunk.InterfaceVMTOffset : word;
  1143. begin
  1144. Result:=0;
  1145. end;
  1146. {****************************************************************************
  1147. Exception Support
  1148. ****************************************************************************}
  1149. {$ifdef FPC_HAS_FEATURE_EXCEPTIONS}
  1150. {$if defined(FPC_WASM_NATIVE_EXCEPTIONS)}
  1151. {$I except_native.inc}
  1152. {$elseif defined(FPC_WASM_BRANCHFUL_EXCEPTIONS)}
  1153. {$I except_branchful.inc}
  1154. {$else}
  1155. {$i except.inc}
  1156. {$endif}
  1157. {$endif FPC_HAS_FEATURE_EXCEPTIONS}
  1158. {****************************************************************************
  1159. Various Delphi constructs
  1160. ****************************************************************************}
  1161. class operator TMethod.=(const aLeft, aRight: TMethod): Boolean; inline;
  1162. begin
  1163. Result:=(aLeft.Data=aRight.Data) and (aLeft.Code=aRight.Code);
  1164. end;
  1165. class operator TMethod.<>(const aLeft, aRight: TMethod): Boolean; inline;
  1166. begin
  1167. Result:=(aLeft.Data<>aRight.Data) or (aLeft.Code<>aRight.Code);
  1168. end;
  1169. class operator TMethod.>(const aLeft, aRight: TMethod): Boolean; inline;
  1170. begin
  1171. Result:=(PtrUInt(aLeft.Data)>PtrUInt(aRight.Data))
  1172. or
  1173. ((aLeft.Data=aRight.Data) and (PtrUInt(aLeft.Code)>PtrUint(aRight.Code)));
  1174. end;
  1175. class operator TMethod.>=(const aLeft, aRight: TMethod): Boolean; inline;
  1176. begin
  1177. Result:=(aLeft>aRight) or (aLeft=aRight);
  1178. end;
  1179. class operator TMethod.<(const aLeft, aRight: TMethod): Boolean; inline;
  1180. begin
  1181. Result:=(PtrUInt(aLeft.Data)<PtrUInt(aRight.Data))
  1182. or
  1183. ((aLeft.Data=aRight.Data) and (PtrUInt(aLeft.Code)<PtrUint(aRight.Code)));
  1184. end;
  1185. class operator TMethod.<=(const aLeft, aRight: TMethod): Boolean; inline;
  1186. begin
  1187. Result:=(aLeft<aRight) or (aLeft=aRight);
  1188. end;
  1189. function TPtrWrapper.ToPointer: Pointer;
  1190. begin
  1191. Result:=FValue;
  1192. end;
  1193. class function TPtrWrapper.GetNilValue: TPtrWrapper;
  1194. begin
  1195. Result.FValue:=Nil;
  1196. end;
  1197. constructor TPtrWrapper.Create(AValue: PtrInt);
  1198. begin
  1199. FValue:=Pointer(aValue);
  1200. end;
  1201. constructor TPtrWrapper.Create(AValue: Pointer);
  1202. begin
  1203. FValue:=aValue;
  1204. end;
  1205. function TPtrWrapper.ToInteger: PtrInt;
  1206. begin
  1207. Result:=PtrInt(FValue);
  1208. end;
  1209. class operator TPtrWrapper.=(Left, Right: TPtrWrapper): Boolean;
  1210. begin
  1211. Result:=Left.FValue=Right.FValue;
  1212. end;
  1213. constructor TMarshal.Create;
  1214. begin
  1215. System.Error(reInvalidPtr);
  1216. end;
  1217. class function TMarshal.AllocMem(Size: SizeInt): TPtrWrapper;
  1218. begin
  1219. Result.Value := System.AllocMem(Size);
  1220. end;
  1221. class function TMarshal.ReallocMem(OldPtr: TPtrWrapper; NewSize: SizeInt): TPtrWrapper;
  1222. var
  1223. P: Pointer;
  1224. begin
  1225. P := OldPtr.Value;
  1226. Result.Value := System.ReallocMem(P, NewSize);
  1227. end;
  1228. class procedure TMarshal.FreeMem(Ptr: TPtrWrapper);
  1229. begin
  1230. System.FreeMem(Ptr.Value);
  1231. end;
  1232. class procedure TMarshal.Move(Src, Dest: TPtrWrapper; Count: SizeInt); static;
  1233. begin
  1234. System.Move(Src.Value^, Dest.Value^, Count);
  1235. end;
  1236. class function TMarshal.UnsafeAddrOf(var Value): TPtrWrapper;
  1237. begin
  1238. Result.Value := @Value;
  1239. end;
  1240. class procedure TMarshal.Copy(const Src: TUint8Array; StartIndex: SizeInt; Dest: TPtrWrapper; Count: SizeInt);
  1241. begin
  1242. System.Move(PUInt8(Src)[StartIndex], Dest.Value^, Count * SizeOf(UInt8));
  1243. end;
  1244. class procedure TMarshal.Copy(Src: TPtrWrapper; var Dest: TUint8Array; StartIndex: SizeInt; Count: SizeInt);
  1245. begin
  1246. System.Move(Src.Value^, PUInt8(Dest)[StartIndex], Count * SizeOf(UInt8));
  1247. end;
  1248. class procedure TMarshal.Copy(const Src: TInt8Array; StartIndex: SizeInt; Dest: TPtrWrapper; Count: SizeInt);
  1249. begin
  1250. System.Move(PInt8(Src)[StartIndex], Dest.Value^, Count * SizeOf(Int8));
  1251. end;
  1252. class procedure TMarshal.Copy(Src: TPtrWrapper; var Dest: TInt8Array ; StartIndex: SizeInt; Count: SizeInt);
  1253. begin
  1254. System.Move(Src.Value^, PInt8(Dest)[StartIndex], Count * SizeOf(Int8));
  1255. end;
  1256. class procedure TMarshal.Copy(const Src: TUInt16Array; StartIndex: SizeInt; Dest: TPtrWrapper; Count: SizeInt);
  1257. begin
  1258. System.Move(PUInt16(Src)[StartIndex], Dest.Value^, Count * SizeOf(UInt16));
  1259. end;
  1260. class procedure TMarshal.Copy(Src: TPtrWrapper; var Dest: TUint16Array; StartIndex: SizeInt; Count: SizeInt);
  1261. begin
  1262. System.Move(Src.Value^, PUInt16(Dest)[StartIndex], Count * SizeOf(UInt16));
  1263. end;
  1264. class procedure TMarshal.Copy(const Src: TInt16Array; StartIndex: SizeInt; Dest: TPtrWrapper; Count: SizeInt);
  1265. begin
  1266. System.Move(PInt16(Src)[StartIndex], Dest.Value^, Count * SizeOf(Int16));
  1267. end;
  1268. class procedure TMarshal.Copy(Src: TPtrWrapper; var Dest: TInt16Array; StartIndex: SizeInt; Count: SizeInt);
  1269. begin
  1270. System.Move(Src.Value^, PInt16(Dest)[StartIndex], Count * SizeOf(Int16));
  1271. end;
  1272. class procedure TMarshal.Copy(const Src: TInt32Array; StartIndex: SizeInt; Dest: TPtrWrapper; Count: SizeInt);
  1273. begin
  1274. System.Move(PInt32(Src)[StartIndex], Dest.Value^, Count * SizeOf(Int32));
  1275. end;
  1276. class procedure TMarshal.Copy(Src: TPtrWrapper; var Dest: TInt32Array; StartIndex: SizeInt; Count: SizeInt);
  1277. begin
  1278. System.Move(Src.Value^, PInt32(Dest)[StartIndex], Count * SizeOf(Int32));
  1279. end;
  1280. class procedure TMarshal.Copy(const Src: TInt64Array; StartIndex: SizeInt; Dest: TPtrWrapper; Count: SizeInt);
  1281. begin
  1282. System.Move(PInt64(Src)[StartIndex], Dest.Value^, Count * SizeOf(Int64));
  1283. end;
  1284. class procedure TMarshal.Copy(Src: TPtrWrapper; var Dest: TInt64Array; StartIndex: SizeInt; Count: SizeInt);
  1285. begin
  1286. System.Move(Src.Value^, PInt64(Dest)[StartIndex], Count * SizeOf(Int64));
  1287. end;
  1288. class procedure TMarshal.Copy(const Src: TPtrWrapperArray; StartIndex: SizeInt; Dest: TPtrWrapper; Count: SizeInt);
  1289. begin
  1290. System.Move(PPointer(Src)[StartIndex], Dest.Value^, Count * SizeOf(TPtrWrapper));
  1291. end;
  1292. class procedure TMarshal.Copy(Src: TPtrWrapper; var Dest: TPtrWrapperArray; StartIndex: SizeInt; Count: SizeInt);
  1293. begin
  1294. System.Move(Src.Value^, PPointer(Dest)[StartIndex], Count * SizeOf(TPtrWrapper));
  1295. end;
  1296. generic class function TMarshal.FixArray<T>(const Arr: specialize TArray<T>): TPtrWrapper;
  1297. begin
  1298. Result.Value := nil;
  1299. specialize TArray<T>(Result) := Arr;
  1300. end;
  1301. generic class procedure TMarshal.UnfixArray<T>(ArrPtr: TPtrWrapper);
  1302. begin
  1303. Finalize(specialize TArray<T>(ArrPtr));
  1304. end;
  1305. class function TMarshal.ReadByte(Ptr: TPtrWrapper; Ofs: SizeInt = 0): Byte;
  1306. begin
  1307. Result := PByte(Ptr.Value + Ofs)^;
  1308. end;
  1309. class procedure TMarshal.WriteByte(Ptr: TPtrWrapper; Ofs: SizeInt; Value: Byte);
  1310. begin
  1311. PByte(Ptr.Value + Ofs)^ := Value;
  1312. end;
  1313. class procedure TMarshal.WriteByte(Ptr: TPtrWrapper; Value: Byte);
  1314. begin
  1315. PByte(Ptr.Value)^ := Value;
  1316. end;
  1317. class function TMarshal.ReadInt16(Ptr: TPtrWrapper; Ofs: SizeInt = 0): Int16;
  1318. begin
  1319. Result := PInt16(Ptr.Value + Ofs)^;
  1320. end;
  1321. class procedure TMarshal.WriteInt16(Ptr: TPtrWrapper; Ofs: SizeInt; Value: Int16);
  1322. begin
  1323. PInt16(Ptr.Value + Ofs)^ := Value;
  1324. end;
  1325. class procedure TMarshal.WriteInt16(Ptr: TPtrWrapper; Value: Int16);
  1326. begin
  1327. PInt16(Ptr.Value)^ := Value;
  1328. end;
  1329. class function TMarshal.ReadInt32(Ptr: TPtrWrapper; Ofs: SizeInt = 0): Int32;
  1330. begin
  1331. Result := PInt32(Ptr.Value + Ofs)^;
  1332. end;
  1333. class procedure TMarshal.WriteInt32(Ptr: TPtrWrapper; Ofs: SizeInt; Value: Int32);
  1334. begin
  1335. PInt32(Ptr.Value + Ofs)^ := Value;
  1336. end;
  1337. class procedure TMarshal.WriteInt32(Ptr: TPtrWrapper; Value: Int32);
  1338. begin
  1339. PInt32(Ptr.Value)^ := Value;
  1340. end;
  1341. class function TMarshal.ReadInt64(Ptr: TPtrWrapper; Ofs: SizeInt = 0): Int64;
  1342. begin
  1343. Result := PInt64(Ptr.Value + Ofs)^;
  1344. end;
  1345. class procedure TMarshal.WriteInt64(Ptr: TPtrWrapper; Ofs: SizeInt; Value: Int64);
  1346. begin
  1347. PInt64(Ptr.Value + Ofs)^ := Value;
  1348. end;
  1349. class procedure TMarshal.WriteInt64(Ptr: TPtrWrapper; Value: Int64);
  1350. begin
  1351. PInt64(Ptr.Value)^ := Value;
  1352. end;
  1353. class function TMarshal.ReadPtr(Ptr: TPtrWrapper; Ofs: SizeInt = 0): TPtrWrapper;
  1354. begin
  1355. Result.Value := PPointer(Ptr.Value + Ofs)^;
  1356. end;
  1357. class procedure TMarshal.WritePtr(Ptr: TPtrWrapper; Ofs: SizeInt; Value: TPtrWrapper);
  1358. begin
  1359. PPointer(Ptr.Value + Ofs)^ := Value.Value;
  1360. end;
  1361. class procedure TMarshal.WritePtr(Ptr, Value: TPtrWrapper);
  1362. begin
  1363. PPointer(Ptr.Value)^ := Value.Value;
  1364. end;
  1365. {$IFDEF FPC_HAS_FEATURE_UNICODESTRINGS}
  1366. class function TMarshal.AsAnsi(const S: UnicodeString): AnsiString;
  1367. begin
  1368. Result := AnsiString(S);
  1369. end;
  1370. class function TMarshal.AsAnsi(S: PUnicodeChar): AnsiString;
  1371. begin
  1372. result := AnsiString(S);
  1373. end;
  1374. class function TMarshal.InOutString(const S: UnicodeString): PUnicodeChar;
  1375. begin
  1376. Result := PUnicodeChar(S);
  1377. end;
  1378. class function TMarshal.InString(const S: UnicodeString): PUnicodeChar;
  1379. begin
  1380. Result := PUnicodeChar(S);
  1381. end;
  1382. class function TMarshal.OutString(const S: UnicodeString): PUnicodeChar;
  1383. begin
  1384. Result := PUnicodeChar(S);
  1385. end;
  1386. class function TMarshal.FixString(var Str: UnicodeString): TPtrWrapper;
  1387. begin
  1388. UniqueString(Str);
  1389. Result := UnsafeFixString(Str);
  1390. end;
  1391. class procedure TMarshal.UnfixString(Ptr: TPtrWrapper);
  1392. begin
  1393. if Ptr.Value <> PUnicodeChar('') then
  1394. Finalize(UnicodeString(Ptr));
  1395. end;
  1396. class function TMarshal.UnsafeFixString(const Str: UnicodeString): TPtrWrapper;
  1397. begin
  1398. if Length(Str) = 0 then
  1399. begin
  1400. Result.Value := PUnicodeChar('');
  1401. Exit;
  1402. end;
  1403. Result.Value := nil;
  1404. UnicodeString(Result) := Str;
  1405. end;
  1406. class function TMarshal.AllocStringAsAnsi(const Str: UnicodeString): TPtrWrapper;
  1407. begin
  1408. Result := AllocStringAsAnsi(PUnicodeChar(Pointer(Str)), Length(Str), DefaultSystemCodePage);
  1409. end;
  1410. class function TMarshal.AllocStringAsAnsi(const Str: UnicodeString; CodePage: Word): TPtrWrapper;
  1411. begin
  1412. Result := AllocStringAsAnsi(PUnicodeChar(Pointer(Str)), Length(Str), CodePage);
  1413. end;
  1414. class function TMarshal.AllocStringAsAnsi(S: PUnicodeChar): TPtrWrapper;
  1415. begin
  1416. Result := AllocStringAsAnsi(S, Length(S), DefaultSystemCodePage);
  1417. end;
  1418. class function TMarshal.AllocStringAsAnsi(S: PUnicodeChar; CodePage: Word): TPtrWrapper;
  1419. begin
  1420. Result := AllocStringAsAnsi(S, Length(S), CodePage);
  1421. end;
  1422. class function TMarshal.AllocStringAsUnicode(const Str: UnicodeString): TPtrWrapper;
  1423. var
  1424. NBytes: SizeUint;
  1425. begin
  1426. NBytes := (Length(Str) + 1) * SizeOf(UnicodeChar);
  1427. Result.Value := System.GetMem(NBytes);
  1428. System.Move(PUnicodeChar(Str)^, Result.Value^, NBytes);
  1429. end;
  1430. class function TMarshal.AllocStringAsUtf8(const Str: UnicodeString): TPtrWrapper;
  1431. begin
  1432. Result := AllocStringAsAnsi(PUnicodeChar(Pointer(Str)), Length(Str), CP_UTF8);
  1433. end;
  1434. class function TMarshal.AllocStringAsUtf8(S: PUnicodeChar): TPtrWrapper;
  1435. begin
  1436. Result := AllocStringAsAnsi(S, Length(S), CP_UTF8);
  1437. end;
  1438. class function TMarshal.AllocStringAsAnsi(S: PUnicodeChar; Len: SizeInt; CodePage: Word): TPtrWrapper;
  1439. var
  1440. U2ARes: AnsiString;
  1441. NBytes: SizeInt;
  1442. begin
  1443. U2ARes := ''; { Suppress warning. }
  1444. WideStringManager.Unicode2AnsiMoveProc(S, U2ARes, CodePage, Len);
  1445. if Length(U2ARes) = 0 then
  1446. begin
  1447. Result.Value := nil;
  1448. Exit;
  1449. end;
  1450. { Could instead avoid the second allocation, assuming U2ARes.RefCount = 1:
  1451. System.Move(Pointer(U2ARes)^, (Pointer(U2ARes) - AnsiStringHeaderSize)^, (Length(U2ARes) + 1) * SizeOf(AnsiChar));
  1452. Result.FValue := Pointer(U2ARes) - AnsiStringHeaderSize;
  1453. Pointer(U2ARes) := nil; }
  1454. NBytes := (Length(U2ARes) + 1) * SizeOf(AnsiChar);
  1455. Result.Value := System.GetMem(NBytes);
  1456. System.Move(PAnsiChar(U2ARes)^, Result.Value^, NBytes);
  1457. end;
  1458. class procedure TMarshal.Copy(const Src: TUnicodeCharArray; StartIndex: SizeInt; Dest: TPtrWrapper; Count: SizeInt);
  1459. begin
  1460. System.Move(PUnicodeChar(Src)[StartIndex], Dest.Value^, Count * SizeOf(UnicodeChar));
  1461. end;
  1462. class procedure TMarshal.Copy(Src: TPtrWrapper; var Dest: TUnicodeCharArray; StartIndex: SizeInt; Count: SizeInt);
  1463. begin
  1464. System.Move(Src.Value^, PUnicodeChar(Dest)[StartIndex], Count * SizeOf(UnicodeChar));
  1465. end;
  1466. class function TMarshal.ReadStringAsAnsi(Ptr: TPtrWrapper; Len: SizeInt = -1): UnicodeString;
  1467. begin
  1468. Result := ReadStringAsAnsi(DefaultSystemCodePage, Ptr, Len);
  1469. end;
  1470. class function TMarshal.ReadStringAsAnsi(CodePage: Word; Ptr: TPtrWrapper; Len: SizeInt = -1): UnicodeString;
  1471. begin
  1472. { Here and below, IndexByte/Word assume that, when Len >= 0, either:
  1473. - Up to Len characters are accessible in Ptr;
  1474. - IndexByte/Word cannot access invalid memory past the searched character
  1475. (e.g. i386.inc and x86_64.inc IndexByte/Word versions are specifically designed not to). }
  1476. if Len < 0 then
  1477. Len := IndexByte(Ptr.Value^, Len, 0);
  1478. Result := ''; { Suppress warning. }
  1479. WideStringManager.Ansi2UnicodeMoveProc(Ptr.Value, CodePage, Result, Len);
  1480. end;
  1481. class function TMarshal.ReadStringAsAnsiUpTo(CodePage: Word; Ptr: TPtrWrapper; MaxLen: SizeInt): UnicodeString;
  1482. var
  1483. Len: SizeInt;
  1484. begin
  1485. Len := IndexByte(Ptr.Value^, MaxLen, 0);
  1486. if Len < 0 then
  1487. Len := MaxLen;
  1488. Result := ReadStringAsAnsi(CodePage, Ptr, Len);
  1489. end;
  1490. class procedure TMarshal.WriteStringAsAnsi(Ptr: TPtrWrapper; const Value: UnicodeString; MaxCharsIncNull: SizeInt);
  1491. begin
  1492. WriteStringAsAnsi(Ptr, 0, Value, MaxCharsIncNull, DefaultSystemCodePage);
  1493. end;
  1494. class procedure TMarshal.WriteStringAsAnsi(Ptr: TPtrWrapper; const Value: UnicodeString; MaxCharsIncNull: SizeInt; CodePage: Word);
  1495. begin
  1496. WriteStringAsAnsi(Ptr, 0, Value, MaxCharsIncNull, CodePage);
  1497. end;
  1498. class procedure TMarshal.WriteStringAsAnsi(Ptr: TPtrWrapper; Ofs: SizeInt; const Value: UnicodeString; MaxCharsIncNull: SizeInt);
  1499. begin
  1500. WriteStringAsAnsi(Ptr, Ofs, Value, MaxCharsIncNull, DefaultSystemCodePage);
  1501. end;
  1502. class procedure TMarshal.WriteStringAsAnsi(Ptr: TPtrWrapper; Ofs: SizeInt; const Value: UnicodeString; MaxCharsIncNull: SizeInt; CodePage: Word);
  1503. var
  1504. U2ARes: AnsiString;
  1505. ValueLen, U2AResLen: SizeInt;
  1506. begin
  1507. U2ARes := ''; { Suppress warning. }
  1508. ValueLen := Length(Value);
  1509. { Delphi null-terminates iff MaxCharsIncNull < 0, so MaxCharsIncNull is actually just MaxChars. }
  1510. if (MaxCharsIncNull > 0) and (MaxCharsIncNull < ValueLen) then
  1511. ValueLen := MaxCharsIncNull; { UTF-16 → ANSI should never shrink element count, so limit the number of characters analyzed. }
  1512. WideStringManager.Unicode2AnsiMoveProc(PUnicodeChar(Pointer(Value)), U2ARes, CodePage, ValueLen);
  1513. U2AResLen := Length(U2ARes);
  1514. if (MaxCharsIncNull >= 0) and (MaxCharsIncNull < U2AResLen) then
  1515. U2AResLen := MaxCharsIncNull;
  1516. System.Move(PAnsiChar(Pointer(U2ARes))^, (Ptr.Value + Ofs)^, U2AResLen * SizeOf(AnsiChar));
  1517. if MaxCharsIncNull < 0 then
  1518. PAnsiChar(Ptr.Value + Ofs)[U2AResLen] := #0;
  1519. end;
  1520. class function TMarshal.ReadStringAsUnicode(Ptr: TPtrWrapper; Len: SizeInt = -1): UnicodeString;
  1521. begin
  1522. if Len < 0 then
  1523. Len := Length(PUnicodeChar(Ptr.Value));
  1524. Result := ''; { Suppress warning. }
  1525. SetLength(Result, Len);
  1526. System.Move(Ptr.Value^, Pointer(Result)^, Len * SizeOf(UnicodeChar));
  1527. end;
  1528. class function TMarshal.ReadStringAsUnicodeUpTo(Ptr: TPtrWrapper; MaxLen: SizeInt): UnicodeString;
  1529. var
  1530. Len: SizeInt;
  1531. begin
  1532. Len := IndexWord(Ptr.Value^, MaxLen, 0);
  1533. if Len < 0 then
  1534. Len := MaxLen;
  1535. Result := ReadStringAsUnicode(Ptr, Len);
  1536. end;
  1537. class procedure TMarshal.WriteStringAsUnicode(Ptr: TPtrWrapper; const Value: UnicodeString; MaxCharsIncNull: SizeInt);
  1538. begin
  1539. WriteStringAsUnicode(Ptr, 0, Value, MaxCharsIncNull);
  1540. end;
  1541. class procedure TMarshal.WriteStringAsUnicode(Ptr: TPtrWrapper; Ofs: SizeInt; const Value: UnicodeString; MaxCharsIncNull: SizeInt);
  1542. var
  1543. Len: SizeInt;
  1544. begin
  1545. { Again, Delphi null-terminates iff MaxCharsIncNull < 0, so MaxCharsIncNull is actually just MaxChars. }
  1546. Len := Length(Value);
  1547. if (MaxCharsIncNull >= 0) and (MaxCharsIncNull < Len) then
  1548. Len := MaxCharsIncNull;
  1549. System.Move(Pointer(Value)^, (Ptr.Value + Ofs)^, Len * SizeOf(UnicodeChar));
  1550. if MaxCharsIncNull < 0 then
  1551. PUnicodeChar(Ptr.Value + Ofs)[Len] := #0;
  1552. end;
  1553. class function TMarshal.ReadStringAsUtf8(Ptr: TPtrWrapper; Len: SizeInt = -1): UnicodeString;
  1554. begin
  1555. Result := ReadStringAsAnsi(CP_UTF8, Ptr, Len);
  1556. end;
  1557. class function TMarshal.ReadStringAsUtf8UpTo(Ptr: TPtrWrapper; MaxLen: SizeInt): UnicodeString;
  1558. begin
  1559. Result := ReadStringAsAnsiUpTo(CP_UTF8, Ptr, MaxLen);
  1560. end;
  1561. class procedure TMarshal.WriteStringAsUtf8(Ptr: TPtrWrapper; const Value: UnicodeString; MaxCharsIncNull: SizeInt);
  1562. begin
  1563. WriteStringAsAnsi(Ptr, Value, MaxCharsIncNull, CP_UTF8);
  1564. end;
  1565. class procedure TMarshal.WriteStringAsUtf8(Ptr: TPtrWrapper; Ofs: SizeInt; const Value: UnicodeString; MaxCharsIncNull: SizeInt);
  1566. begin
  1567. WriteStringAsAnsi(Ptr, Ofs, Value, MaxCharsIncNull, CP_UTF8);
  1568. end;
  1569. {$ENDIF}
  1570. {$IFDEF SYSTEM_HAS_FEATURE_MONITOR}
  1571. {$i monitor.inc}
  1572. {$ENDIF}