2
0

objpas.inc 58 KB

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