wstrings.inc 46 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2005 by Florian Klaempfl,
  4. member of the Free Pascal development team.
  5. This file implements support routines for WideStrings with FPC
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. {
  13. This file contains the implementation of the WideString type,
  14. and all things that are needed for it.
  15. WideString is defined as a 'silent' pwidechar :
  16. a pwidechar that points to :
  17. @-8 : SizeInt for reference count;
  18. @-4 : SizeInt for size; size=number of bytes, not the number of chars. Divide or multiply
  19. with sizeof(WideChar) to convert. This is needed to be compatible with Delphi and
  20. Windows COM BSTR.
  21. @ : String + Terminating #0;
  22. Pwidechar(Widestring) is a valid typecast.
  23. So WS[i] is converted to the address @WS+i-1.
  24. Constants should be assigned a reference count of -1
  25. Meaning that they can't be disposed of.
  26. }
  27. Type
  28. PWideRec = ^TWideRec;
  29. TWideRec = Packed Record
  30. Len : DWord;
  31. First : WideChar;
  32. end;
  33. Const
  34. WideRecLen = SizeOf(TWideRec);
  35. WideFirstOff = SizeOf(TWideRec)-sizeof(WideChar);
  36. {
  37. Default WideChar <-> Char conversion is to only convert the
  38. lower 127 chars, all others are translated to spaces.
  39. These routines can be overwritten for the Current Locale
  40. }
  41. procedure DefaultWide2AnsiMove(source:pwidechar;var dest:ansistring;len:SizeInt);
  42. var
  43. i : SizeInt;
  44. begin
  45. setlength(dest,len);
  46. for i:=1 to len do
  47. begin
  48. if word(source^)<256 then
  49. dest[i]:=char(word(source^))
  50. else
  51. dest[i]:='?';
  52. inc(source);
  53. end;
  54. end;
  55. procedure DefaultAnsi2WideMove(source:pchar;var dest:widestring;len:SizeInt);
  56. var
  57. i : SizeInt;
  58. begin
  59. setlength(dest,len);
  60. for i:=1 to len do
  61. begin
  62. dest[i]:=widechar(byte(source^));
  63. inc(source);
  64. end;
  65. end;
  66. (*
  67. Procedure UniqueWideString(Var S : WideString); [Public,Alias : 'FPC_WIDESTR_UNIQUE'];
  68. {
  69. Make sure reference count of S is 1,
  70. using copy-on-write semantics.
  71. }
  72. begin
  73. end;
  74. *)
  75. {****************************************************************************
  76. Internal functions, not in interface.
  77. ****************************************************************************}
  78. procedure WideStringError;
  79. begin
  80. HandleErrorFrame(204,get_frame);
  81. end;
  82. {$ifdef WideStrDebug}
  83. Procedure DumpWideRec(S : Pointer);
  84. begin
  85. If S=Nil then
  86. Writeln ('String is nil')
  87. Else
  88. Begin
  89. With PWideRec(S-WideFirstOff)^ do
  90. begin
  91. Write ('(Len:',len);
  92. Writeln (' Ref: ',ref,')');
  93. end;
  94. end;
  95. end;
  96. {$endif}
  97. Function NewWideString(Len : SizeInt) : Pointer;
  98. {
  99. Allocate a new WideString on the heap.
  100. initialize it to zero length and reference count 1.
  101. }
  102. Var
  103. P : Pointer;
  104. begin
  105. {$ifdef MSWINDOWS}
  106. if winwidestringalloc then
  107. begin
  108. P:=SysAllocStringLen(nil,Len);
  109. if P=nil then
  110. WideStringError;
  111. end
  112. else
  113. {$endif MSWINDOWS}
  114. begin
  115. GetMem(P,Len*sizeof(WideChar)+WideRecLen);
  116. If P<>Nil then
  117. begin
  118. PWideRec(P)^.Len:=Len*2; { Initial length }
  119. PWideRec(P)^.First:=#0; { Terminating #0 }
  120. inc(p,WideFirstOff); { Points to string now }
  121. end
  122. else
  123. WideStringError;
  124. end;
  125. NewWideString:=P;
  126. end;
  127. Procedure DisposeWideString(Var S : Pointer);
  128. {
  129. Deallocates a WideString From the heap.
  130. }
  131. begin
  132. If S=Nil then
  133. exit;
  134. {$ifndef MSWINDOWS}
  135. Dec (S,WideFirstOff);
  136. Freemem(S);
  137. {$else MSWINDOWS}
  138. if winwidestringalloc then
  139. SysFreeString(S)
  140. else
  141. begin
  142. Dec (S,WideFirstOff);
  143. Freemem(S);
  144. end;
  145. {$endif MSWINDOWS}
  146. S:=Nil;
  147. end;
  148. var
  149. __data_start: byte; external name '__data_start__';
  150. __data_end: byte; external name '__data_end__';
  151. function IsWideStringConstant(S: pointer): boolean;{$ifdef SYSTEMINLINE}inline;{$endif}
  152. {
  153. Returns True if widestring is constant (located in .data section);
  154. }
  155. begin
  156. Result:=(S>=@__data_start) and (S<@__data_end);
  157. end;
  158. Procedure fpc_WideStr_Decr_Ref (Var S : Pointer);[Public,Alias:'FPC_WIDESTR_DECR_REF']; compilerproc;
  159. {
  160. Decreases the ReferenceCount of a non constant widestring;
  161. If the reference count is zero, deallocate the string;
  162. }
  163. Type
  164. pSizeInt = ^SizeInt;
  165. Begin
  166. { Zero string }
  167. if S=Nil then
  168. exit;
  169. if not IsWideStringConstant(S) then
  170. DisposeWideString(S);
  171. end;
  172. { alias for internal use }
  173. Procedure fpc_WideStr_Decr_Ref (Var S : Pointer);[external name 'FPC_WIDESTR_DECR_REF'];
  174. Procedure fpc_WideStr_Incr_Ref(Var S : Pointer);[Public,Alias:'FPC_WIDESTR_INCR_REF']; compilerproc;
  175. var
  176. p : pointer;
  177. Begin
  178. If S=Nil then
  179. exit;
  180. p:=NewWidestring(length(WideString(S)));
  181. move(s^,p^,(length(WideString(s))+1)*sizeof(widechar)); // double #0 too
  182. s:=p;
  183. end;
  184. { alias for internal use }
  185. Procedure fpc_WideStr_Incr_Ref (Var S : Pointer);[external name 'FPC_WIDESTR_INCR_REF'];
  186. {$ifndef FPC_STRTOSHORTSTRINGPROC}
  187. function fpc_WideStr_To_ShortStr (high_of_res: SizeInt;const S2 : WideString): shortstring;[Public, alias: 'FPC_WIDESTR_TO_SHORTSTR']; compilerproc;
  188. {
  189. Converts a WideString to a ShortString;
  190. }
  191. Var
  192. Size : SizeInt;
  193. temp : ansistring;
  194. begin
  195. result:='';
  196. Size:=Length(S2);
  197. if Size>0 then
  198. begin
  199. If Size>high_of_res then
  200. Size:=high_of_res;
  201. widestringmanager.Wide2AnsiMoveProc(PWideChar(S2),temp,Size);
  202. result:=temp;
  203. end;
  204. end;
  205. {$else FPC_STRTOSHORTSTRINGPROC}
  206. procedure fpc_WideStr_To_ShortStr (out res: ShortString;const S2 : WideString); [Public, alias: 'FPC_WIDESTR_TO_SHORTSTR'];compilerproc;
  207. {
  208. Converts a WideString to a ShortString;
  209. }
  210. Var
  211. Size : SizeInt;
  212. temp : ansistring;
  213. begin
  214. res:='';
  215. Size:=Length(S2);
  216. if Size>0 then
  217. begin
  218. If Size>high(res) then
  219. Size:=high(res);
  220. widestringmanager.Wide2AnsiMoveProc(PWideChar(S2),temp,Size);
  221. res:=temp;
  222. end;
  223. end;
  224. {$endif FPC_STRTOSHORTSTRINGPROC}
  225. Function fpc_ShortStr_To_WideStr (Const S2 : ShortString): WideString;compilerproc;
  226. {
  227. Converts a ShortString to a WideString;
  228. }
  229. Var
  230. Size : SizeInt;
  231. begin
  232. result:='';
  233. Size:=Length(S2);
  234. if Size>0 then
  235. begin
  236. widestringmanager.Ansi2WideMoveProc(PChar(@S2[1]),result,Size);
  237. { Terminating Zero }
  238. PWideChar(Pointer(fpc_ShortStr_To_WideStr)+Size*sizeof(WideChar))^:=#0;
  239. end;
  240. end;
  241. Function fpc_WideStr_To_AnsiStr (const S2 : WideString): AnsiString; compilerproc;
  242. {
  243. Converts a WideString to an AnsiString
  244. }
  245. Var
  246. Size : SizeInt;
  247. begin
  248. result:='';
  249. Size:=Length(S2);
  250. if Size>0 then
  251. widestringmanager.Wide2AnsiMoveProc(PWideChar(Pointer(S2)),result,Size);
  252. end;
  253. Function fpc_AnsiStr_To_WideStr (Const S2 : AnsiString): WideString; compilerproc;
  254. {
  255. Converts an AnsiString to a WideString;
  256. }
  257. Var
  258. Size : SizeInt;
  259. begin
  260. result:='';
  261. Size:=Length(S2);
  262. if Size>0 then
  263. widestringmanager.Ansi2WideMoveProc(PChar(S2),result,Size);
  264. end;
  265. Function fpc_PWideChar_To_AnsiStr(const p : pwidechar): ansistring; compilerproc;
  266. var
  267. Size : SizeInt;
  268. begin
  269. result:='';
  270. if p=nil then
  271. exit;
  272. Size := IndexWord(p^, -1, 0);
  273. if Size>0 then
  274. widestringmanager.Wide2AnsiMoveProc(P,result,Size);
  275. end;
  276. Function fpc_PWideChar_To_WideStr(const p : pwidechar): widestring; compilerproc;
  277. var
  278. Size : SizeInt;
  279. begin
  280. result:='';
  281. if p=nil then
  282. exit;
  283. Size := IndexWord(p^, -1, 0);
  284. Setlength(result,Size);
  285. if Size>0 then
  286. begin
  287. Move(p^,PWideChar(Pointer(result))^,Size*sizeof(WideChar));
  288. { Terminating Zero }
  289. PWideChar(Pointer(result)+Size*sizeof(WideChar))^:=#0;
  290. end;
  291. end;
  292. {$ifndef FPC_STRTOSHORTSTRINGPROC}
  293. Function fpc_PWideChar_To_ShortStr(const p : pwidechar): shortstring; compilerproc;
  294. var
  295. Size : SizeInt;
  296. temp: ansistring;
  297. begin
  298. result:='';
  299. if p=nil then
  300. exit;
  301. Size := IndexWord(p^, $7fffffff, 0);
  302. if Size>0 then
  303. begin
  304. widestringmanager.Wide2AnsiMoveProc(p,temp,Size);
  305. result:=temp;
  306. end;
  307. end;
  308. {$else FPC_STRTOSHORTSTRINGPROC}
  309. procedure fpc_PWideChar_To_ShortStr(out res : shortstring;const p : pwidechar); compilerproc;
  310. var
  311. Size : SizeInt;
  312. temp: ansistring;
  313. begin
  314. res:='';
  315. if p=nil then
  316. exit;
  317. Size:=IndexWord(p^, high(PtrInt), 0);
  318. if Size>0 then
  319. begin
  320. widestringmanager.Wide2AnsiMoveProc(p,temp,Size);
  321. res:=temp;
  322. end;
  323. end;
  324. {$endif FPC_STRTOSHORTSTRINGPROC}
  325. { checked against the ansistring routine, 2001-05-27 (FK) }
  326. Procedure fpc_WideStr_Assign (Var S1 : Pointer;S2 : Pointer);[Public,Alias:'FPC_WIDESTR_ASSIGN']; compilerproc;
  327. {
  328. Assigns S2 to S1 (S1:=S2), taking in account reference counts.
  329. }
  330. begin
  331. if S1=S2 then exit;
  332. if S2<>nil then
  333. begin
  334. if IsWideStringConstant(S1) then
  335. begin
  336. S1:=NewWidestring(length(WideString(S2)));
  337. move(s2^,s1^,(length(WideString(s1))+1)*sizeof(widechar));
  338. end
  339. else
  340. {$ifdef MSWINDOWS}
  341. if winwidestringalloc then
  342. begin
  343. if SysReAllocStringLen(S1, S2, Length(WideString(S2))) = 0 then
  344. WideStringError;
  345. end
  346. else
  347. {$endif MSWINDOWS}
  348. begin
  349. SetLength(WideString(S1),length(WideString(S2)));
  350. move(s2^,s1^,(length(WideString(s1))+1)*sizeof(widechar));
  351. end;
  352. end
  353. else
  354. begin
  355. { Free S1 }
  356. fpc_widestr_decr_ref (S1);
  357. S1:=nil;
  358. end;
  359. end;
  360. { alias for internal use }
  361. Procedure fpc_WideStr_Assign (Var S1 : Pointer;S2 : Pointer);[external name 'FPC_WIDESTR_ASSIGN'];
  362. {$ifndef STR_CONCAT_PROCS}
  363. function fpc_WideStr_Concat (const S1,S2 : WideString): WideString; compilerproc;
  364. Var
  365. Size,Location : SizeInt;
  366. pc : pwidechar;
  367. begin
  368. { only assign if s1 or s2 is empty }
  369. if (S1='') then
  370. begin
  371. result:=s2;
  372. exit;
  373. end;
  374. if (S2='') then
  375. begin
  376. result:=s1;
  377. exit;
  378. end;
  379. Location:=Length(S1);
  380. Size:=length(S2);
  381. SetLength(result,Size+Location);
  382. pc:=pwidechar(result);
  383. Move(S1[1],pc^,Location*sizeof(WideChar));
  384. inc(pc,location);
  385. Move(S2[1],pc^,(Size+1)*sizeof(WideChar));
  386. end;
  387. function fpc_WideStr_Concat_multi (const sarr:array of Widestring): widestring; compilerproc;
  388. Var
  389. i : Longint;
  390. p : pointer;
  391. pc : pwidechar;
  392. Size,NewSize : SizeInt;
  393. begin
  394. { First calculate size of the result so we can do
  395. a single call to SetLength() }
  396. NewSize:=0;
  397. for i:=low(sarr) to high(sarr) do
  398. inc(Newsize,length(sarr[i]));
  399. SetLength(result,NewSize);
  400. pc:=pwidechar(result);
  401. for i:=low(sarr) to high(sarr) do
  402. begin
  403. p:=pointer(sarr[i]);
  404. if assigned(p) then
  405. begin
  406. Size:=length(widestring(p));
  407. Move(pwidechar(p)^,pc^,(Size+1)*sizeof(WideChar));
  408. inc(pc,size);
  409. end;
  410. end;
  411. end;
  412. {$else STR_CONCAT_PROCS}
  413. procedure fpc_WideStr_Concat (var DestS:Widestring;const S1,S2 : WideString); compilerproc;
  414. Var
  415. Size,Location : SizeInt;
  416. same : boolean;
  417. begin
  418. { only assign if s1 or s2 is empty }
  419. if (S1='') then
  420. begin
  421. DestS:=s2;
  422. exit;
  423. end;
  424. if (S2='') then
  425. begin
  426. DestS:=s1;
  427. exit;
  428. end;
  429. Location:=Length(S1);
  430. Size:=length(S2);
  431. { Use Pointer() typecasts to prevent extra conversion code }
  432. if Pointer(DestS)=Pointer(S1) then
  433. begin
  434. same:=Pointer(S1)=Pointer(S2);
  435. SetLength(DestS,Size+Location);
  436. if same then
  437. Move(Pointer(DestS)^,(Pointer(DestS)+Location*sizeof(WideChar))^,(Size)*sizeof(WideChar))
  438. else
  439. Move(Pointer(S2)^,(Pointer(DestS)+Location*sizeof(WideChar))^,(Size+1)*sizeof(WideChar));
  440. end
  441. else if Pointer(DestS)=Pointer(S2) then
  442. begin
  443. SetLength(DestS,Size+Location);
  444. Move(Pointer(DestS)^,(Pointer(DestS)+Location*sizeof(WideChar))^,(Size+1)*sizeof(WideChar));
  445. Move(Pointer(S1)^,Pointer(DestS)^,Location*sizeof(WideChar));
  446. end
  447. else
  448. begin
  449. DestS:='';
  450. SetLength(DestS,Size+Location);
  451. Move(Pointer(S1)^,Pointer(DestS)^,Location*sizeof(WideChar));
  452. Move(Pointer(S2)^,(Pointer(DestS)+Location*sizeof(WideChar))^,(Size+1)*sizeof(WideChar));
  453. end;
  454. end;
  455. procedure fpc_WideStr_Concat_multi (var DestS:Widestring;const sarr:array of Widestring); compilerproc;
  456. Var
  457. i : Longint;
  458. p,pc : pointer;
  459. Size,NewLen : SizeInt;
  460. DestTmp : Widestring;
  461. begin
  462. if high(sarr)=0 then
  463. begin
  464. DestS:='';
  465. exit;
  466. end;
  467. { First calculate size of the result so we can do
  468. a single call to SetLength() }
  469. NewLen:=0;
  470. for i:=low(sarr) to high(sarr) do
  471. inc(NewLen,length(sarr[i]));
  472. SetLength(DestTmp,NewLen);
  473. pc:=pwidechar(DestTmp);
  474. for i:=low(sarr) to high(sarr) do
  475. begin
  476. p:=pointer(sarr[i]);
  477. if assigned(p) then
  478. begin
  479. Size:=length(widestring(p));
  480. Move(p^,pc^,(Size+1)*sizeof(WideChar));
  481. inc(pc,size*sizeof(WideChar));
  482. end;
  483. end;
  484. DestS:=DestTmp;
  485. end;
  486. {$endif STR_CONCAT_PROCS}
  487. Function fpc_Char_To_WChar(const c : Char): WideChar; compilerproc;
  488. var
  489. w: widestring;
  490. begin
  491. widestringmanager.Ansi2WideMoveProc(@c, w, 1);
  492. fpc_Char_To_WChar:= w[1];
  493. end;
  494. Function fpc_Char_To_WideStr(const c : Char): WideString; compilerproc;
  495. {
  496. Converts a Char to a WideString;
  497. }
  498. begin
  499. Setlength(fpc_Char_To_WideStr,1);
  500. fpc_Char_To_WideStr[1]:=c;
  501. { Terminating Zero }
  502. PWideChar(Pointer(fpc_Char_To_WideStr)+sizeof(WideChar))^:=#0;
  503. end;
  504. Function fpc_WChar_To_Char(const c : WideChar): Char; compilerproc;
  505. {
  506. Converts a WideChar to a Char;
  507. }
  508. var
  509. s: ansistring;
  510. begin
  511. widestringmanager.Wide2AnsiMoveProc(@c, s, 1);
  512. if length(s)=1 then
  513. fpc_WChar_To_Char:= s[1]
  514. else
  515. fpc_WChar_To_Char:='?';
  516. end;
  517. Function fpc_WChar_To_WideStr(const c : WideChar): WideString; compilerproc;
  518. {
  519. Converts a WideChar to a WideString;
  520. }
  521. begin
  522. Setlength (fpc_WChar_To_WideStr,1);
  523. fpc_WChar_To_WideStr[1]:= c;
  524. end;
  525. Function fpc_WChar_To_AnsiStr(const c : WideChar): AnsiString; compilerproc;
  526. {
  527. Converts a WideChar to a AnsiString;
  528. }
  529. begin
  530. widestringmanager.Wide2AnsiMoveProc(@c, fpc_WChar_To_AnsiStr, 1);
  531. end;
  532. Function fpc_UChar_To_WideStr(const c : WideChar): WideString; compilerproc;
  533. {
  534. Converts a WideChar to a WideString;
  535. }
  536. begin
  537. Setlength (fpc_UChar_To_WideStr,1);
  538. fpc_UChar_To_WideStr[1]:= c;
  539. end;
  540. {$ifndef FPC_STRTOSHORTSTRINGPROC}
  541. Function fpc_WChar_To_ShortStr(const c : WideChar): ShortString; compilerproc;
  542. {
  543. Converts a WideChar to a ShortString;
  544. }
  545. var
  546. s: ansistring;
  547. begin
  548. widestringmanager.Wide2AnsiMoveProc(@c, s, 1);
  549. fpc_WChar_To_ShortStr:= s;
  550. end;
  551. {$else FPC_STRTOSHORTSTRINGPROC}
  552. procedure fpc_WChar_To_ShortStr(out res : shortstring;const c : WideChar) compilerproc;
  553. {
  554. Converts a WideChar to a ShortString;
  555. }
  556. var
  557. s: ansistring;
  558. begin
  559. widestringmanager.Wide2AnsiMoveProc(@c,s,1);
  560. res:=s;
  561. end;
  562. {$endif FPC_STRTOSHORTSTRINGPROC}
  563. Function fpc_PChar_To_WideStr(const p : pchar): WideString; compilerproc;
  564. Var
  565. L : SizeInt;
  566. begin
  567. if (not assigned(p)) or (p[0]=#0) Then
  568. begin
  569. fpc_pchar_to_widestr := '';
  570. exit;
  571. end;
  572. l:=IndexChar(p^,-1,#0);
  573. widestringmanager.Ansi2WideMoveProc(P,fpc_PChar_To_WideStr,l);
  574. end;
  575. Function fpc_CharArray_To_WideStr(const arr: array of char; zerobased: boolean = true): WideString; compilerproc;
  576. var
  577. i : SizeInt;
  578. begin
  579. if (zerobased) then
  580. begin
  581. if (arr[0]=#0) Then
  582. begin
  583. fpc_chararray_to_widestr := '';
  584. exit;
  585. end;
  586. i:=IndexChar(arr,high(arr)+1,#0);
  587. if i = -1 then
  588. i := high(arr)+1;
  589. end
  590. else
  591. i := high(arr)+1;
  592. SetLength(fpc_CharArray_To_WideStr,i);
  593. widestringmanager.Ansi2WideMoveProc (pchar(@arr),fpc_CharArray_To_WideStr,i);
  594. end;
  595. {$ifndef FPC_STRTOSHORTSTRINGPROC}
  596. function fpc_WideCharArray_To_ShortStr(const arr: array of widechar; zerobased: boolean = true): shortstring;[public,alias:'FPC_WIDECHARARRAY_TO_SHORTSTR']; compilerproc;
  597. var
  598. l: longint;
  599. index: longint;
  600. len: byte;
  601. temp: ansistring;
  602. begin
  603. l := high(arr)+1;
  604. if l>=256 then
  605. l:=255
  606. else if l<0 then
  607. l:=0;
  608. if zerobased then
  609. begin
  610. index:=IndexWord(arr[0],l,0);
  611. if (index < 0) then
  612. len := l
  613. else
  614. len := index;
  615. end
  616. else
  617. len := l;
  618. widestringmanager.Wide2AnsiMoveProc (pwidechar(@arr),temp,len);
  619. fpc_WideCharArray_To_ShortStr := temp;
  620. end;
  621. {$else FPC_STRTOSHORTSTRINGPROC}
  622. procedure fpc_WideCharArray_To_ShortStr(out res : shortstring;const arr: array of widechar; zerobased: boolean = true);[public,alias:'FPC_WIDECHARARRAY_TO_SHORTSTR']; compilerproc;
  623. var
  624. l: longint;
  625. index: ptrint;
  626. len: byte;
  627. temp: ansistring;
  628. begin
  629. l := high(arr)+1;
  630. if l>=high(res)+1 then
  631. l:=high(res)
  632. else if l<0 then
  633. l:=0;
  634. if zerobased then
  635. begin
  636. index:=IndexWord(arr[0],l,0);
  637. if index<0 then
  638. len:=l
  639. else
  640. len:=index;
  641. end
  642. else
  643. len:=l;
  644. widestringmanager.Wide2AnsiMoveProc (pwidechar(@arr),temp,len);
  645. res:=temp;
  646. end;
  647. {$endif FPC_STRTOSHORTSTRINGPROC}
  648. Function fpc_WideCharArray_To_AnsiStr(const arr: array of widechar; zerobased: boolean = true): AnsiString; compilerproc;
  649. var
  650. i : SizeInt;
  651. begin
  652. if (zerobased) then
  653. begin
  654. i:=IndexWord(arr,high(arr)+1,0);
  655. if i = -1 then
  656. i := high(arr)+1;
  657. end
  658. else
  659. i := high(arr)+1;
  660. SetLength(fpc_WideCharArray_To_AnsiStr,i);
  661. widestringmanager.Wide2AnsiMoveProc (pwidechar(@arr),fpc_WideCharArray_To_AnsiStr,i);
  662. end;
  663. Function fpc_WideCharArray_To_WideStr(const arr: array of widechar; zerobased: boolean = true): WideString; compilerproc;
  664. var
  665. i : SizeInt;
  666. begin
  667. if (zerobased) then
  668. begin
  669. i:=IndexWord(arr,high(arr)+1,0);
  670. if i = -1 then
  671. i := high(arr)+1;
  672. end
  673. else
  674. i := high(arr)+1;
  675. SetLength(fpc_WideCharArray_To_WideStr,i);
  676. Move(arr[0], Pointer(fpc_WideCharArray_To_WideStr)^,i*sizeof(WideChar));
  677. end;
  678. {$ifndef FPC_STRTOCHARARRAYPROC}
  679. { inside the compiler, the resulttype is modified to that of the actual }
  680. { chararray we're converting to (JM) }
  681. function fpc_widestr_to_chararray(arraysize: SizeInt; const src: WideString): fpc_big_chararray;[public,alias: 'FPC_WIDESTR_TO_CHARARRAY']; compilerproc;
  682. var
  683. len: SizeInt;
  684. temp: ansistring;
  685. begin
  686. len := length(src);
  687. { make sure we don't dereference src if it can be nil (JM) }
  688. if len > 0 then
  689. widestringmanager.wide2ansimoveproc(pwidechar(@src[1]),temp,len);
  690. len := length(temp);
  691. if len > arraysize then
  692. len := arraysize;
  693. {$r-}
  694. move(temp[1],fpc_widestr_to_chararray[0],len);
  695. fillchar(fpc_widestr_to_chararray[len],arraysize-len,0);
  696. {$ifdef RangeCheckWasOn}
  697. {$r+}
  698. {$endif}
  699. end;
  700. { inside the compiler, the resulttype is modified to that of the actual }
  701. { widechararray we're converting to (JM) }
  702. function fpc_widestr_to_widechararray(arraysize: SizeInt; const src: WideString): fpc_big_widechararray;[public,alias: 'FPC_WIDESTR_TO_WIDECHARARRAY']; compilerproc;
  703. var
  704. len: SizeInt;
  705. begin
  706. len := length(src);
  707. if len > arraysize then
  708. len := arraysize;
  709. {$r-}
  710. { make sure we don't try to access element 1 of the ansistring if it's nil }
  711. if len > 0 then
  712. move(src[1],fpc_widestr_to_widechararray[0],len*SizeOf(WideChar));
  713. fillchar(fpc_widestr_to_widechararray[len],(arraysize-len)*SizeOf(WideChar),0);
  714. {$ifdef RangeCheckWasOn}
  715. {$r+}
  716. {$endif}
  717. end;
  718. { inside the compiler, the resulttype is modified to that of the actual }
  719. { chararray we're converting to (JM) }
  720. function fpc_ansistr_to_widechararray(arraysize: SizeInt; const src: AnsiString): fpc_big_widechararray;[public,alias: 'FPC_ANSISTR_TO_WIDECHARARRAY']; compilerproc;
  721. var
  722. len: SizeInt;
  723. temp: widestring;
  724. begin
  725. len := length(src);
  726. { make sure we don't dereference src if it can be nil (JM) }
  727. if len > 0 then
  728. widestringmanager.ansi2widemoveproc(pchar(@src[1]),temp,len);
  729. len := length(temp);
  730. if len > arraysize then
  731. len := arraysize;
  732. {$r-}
  733. move(temp[1],fpc_ansistr_to_widechararray[0],len*sizeof(widechar));
  734. fillchar(fpc_ansistr_to_widechararray[len],(arraysize-len)*SizeOf(WideChar),0);
  735. {$ifdef RangeCheckWasOn}
  736. {$r+}
  737. {$endif}
  738. end;
  739. function fpc_shortstr_to_widechararray(arraysize: SizeInt; const src: ShortString): fpc_big_widechararray;[public,alias: 'FPC_SHORTSTR_TO_WIDECHARARRAY']; compilerproc;
  740. var
  741. len: longint;
  742. temp : widestring;
  743. begin
  744. len := length(src);
  745. { make sure we don't access char 1 if length is 0 (JM) }
  746. if len > 0 then
  747. widestringmanager.ansi2widemoveproc(pchar(@src[1]),temp,len);
  748. len := length(temp);
  749. if len > arraysize then
  750. len := arraysize;
  751. {$r-}
  752. move(temp[1],fpc_shortstr_to_widechararray[0],len*sizeof(widechar));
  753. fillchar(fpc_shortstr_to_widechararray[len],(arraysize-len)*SizeOf(WideChar),0);
  754. {$ifdef RangeCheckWasOn}
  755. {$r+}
  756. {$endif}
  757. end;
  758. {$else ndef FPC_STRTOCHARARRAYPROC}
  759. procedure fpc_widestr_to_chararray(out res: array of char; const src: WideString); compilerproc;
  760. var
  761. len: SizeInt;
  762. temp: ansistring;
  763. begin
  764. len := length(src);
  765. { make sure we don't dereference src if it can be nil (JM) }
  766. if len > 0 then
  767. widestringmanager.wide2ansimoveproc(pwidechar(@src[1]),temp,len);
  768. len := length(temp);
  769. if len > length(res) then
  770. len := length(res);
  771. {$r-}
  772. move(temp[1],res[0],len);
  773. fillchar(res[len],length(res)-len,0);
  774. {$ifdef RangeCheckWasOn}
  775. {$r+}
  776. {$endif}
  777. end;
  778. procedure fpc_widestr_to_widechararray(out res: array of widechar; const src: WideString); compilerproc;
  779. var
  780. len: SizeInt;
  781. begin
  782. len := length(src);
  783. if len > length(res) then
  784. len := length(res);
  785. {$r-}
  786. { make sure we don't try to access element 1 of the ansistring if it's nil }
  787. if len > 0 then
  788. move(src[1],res[0],len*SizeOf(WideChar));
  789. fillchar(res[len],(length(res)-len)*SizeOf(WideChar),0);
  790. {$ifdef RangeCheckWasOn}
  791. {$r+}
  792. {$endif}
  793. end;
  794. procedure fpc_ansistr_to_widechararray(out res: array of widechar; const src: AnsiString); compilerproc;
  795. var
  796. len: SizeInt;
  797. temp: widestring;
  798. begin
  799. len := length(src);
  800. { make sure we don't dereference src if it can be nil (JM) }
  801. if len > 0 then
  802. widestringmanager.ansi2widemoveproc(pchar(@src[1]),temp,len);
  803. len := length(temp);
  804. if len > length(res) then
  805. len := length(res);
  806. {$r-}
  807. move(temp[1],res[0],len*sizeof(widechar));
  808. fillchar(res[len],(length(res)-len)*SizeOf(WideChar),0);
  809. {$ifdef RangeCheckWasOn}
  810. {$r+}
  811. {$endif}
  812. end;
  813. procedure fpc_shortstr_to_widechararray(out res: array of widechar; const src: ShortString); compilerproc;
  814. var
  815. len: longint;
  816. temp : widestring;
  817. begin
  818. len := length(src);
  819. { make sure we don't access char 1 if length is 0 (JM) }
  820. if len > 0 then
  821. widestringmanager.ansi2widemoveproc(pchar(@src[1]),temp,len);
  822. len := length(temp);
  823. if len > length(res) then
  824. len := length(res);
  825. {$r-}
  826. move(temp[1],res[0],len*sizeof(widechar));
  827. fillchar(res[len],(length(res)-len)*SizeOf(WideChar),0);
  828. {$ifdef RangeCheckWasOn}
  829. {$r+}
  830. {$endif}
  831. end;
  832. {$endif ndef FPC_STRTOCHARARRAYPROC}
  833. Function fpc_WideStr_Compare(const S1,S2 : WideString): SizeInt;[Public,Alias : 'FPC_WIDESTR_COMPARE']; compilerproc;
  834. {
  835. Compares 2 WideStrings;
  836. The result is
  837. <0 if S1<S2
  838. 0 if S1=S2
  839. >0 if S1>S2
  840. }
  841. Var
  842. MaxI,Temp : SizeInt;
  843. begin
  844. if pointer(S1)=pointer(S2) then
  845. begin
  846. fpc_WideStr_Compare:=0;
  847. exit;
  848. end;
  849. Maxi:=Length(S1);
  850. temp:=Length(S2);
  851. If MaxI>Temp then
  852. MaxI:=Temp;
  853. Temp:=CompareWord(S1[1],S2[1],MaxI);
  854. if temp=0 then
  855. temp:=Length(S1)-Length(S2);
  856. fpc_WideStr_Compare:=Temp;
  857. end;
  858. Function fpc_WideStr_Compare_Equal(const S1,S2 : WideString): SizeInt;[Public,Alias : 'FPC_WIDESTR_COMPARE_EQUAL']; compilerproc;
  859. {
  860. Compares 2 WideStrings for equality only;
  861. The result is
  862. 0 if S1=S2
  863. <>0 if S1<>S2
  864. }
  865. Var
  866. MaxI : SizeInt;
  867. begin
  868. if pointer(S1)=pointer(S2) then
  869. exit(0);
  870. Maxi:=Length(S1);
  871. If MaxI<>Length(S2) then
  872. exit(-1)
  873. else
  874. exit(CompareWord(S1[1],S2[1],MaxI));
  875. end;
  876. Procedure fpc_WideStr_CheckZero(p : pointer);[Public,Alias : 'FPC_WIDESTR_CHECKZERO']; compilerproc;
  877. begin
  878. if p=nil then
  879. HandleErrorFrame(201,get_frame);
  880. end;
  881. Procedure fpc_WideStr_CheckRange(len,index : SizeInt);[Public,Alias : 'FPC_WIDESTR_RANGECHECK']; compilerproc;
  882. begin
  883. if (index>len div 2) or (Index<1) then
  884. HandleErrorFrame(201,get_frame);
  885. end;
  886. Procedure fpc_WideStr_SetLength(Var S : WideString; l : SizeInt);[Public,Alias : 'FPC_WIDESTR_SETLENGTH']; compilerproc;
  887. {
  888. Sets The length of string S to L.
  889. Makes sure S is unique, and contains enough room.
  890. }
  891. Var
  892. Temp : Pointer;
  893. movelen: SizeInt;
  894. begin
  895. if (l>0) then
  896. begin
  897. if Pointer(S)=nil then
  898. begin
  899. { Need a complete new string...}
  900. Pointer(s):=NewWideString(l);
  901. end
  902. { windows doesn't support reallocing widestrings, this code
  903. is anyways subject to be removed because widestrings shouldn't be
  904. ref. counted anymore (FK) }
  905. else
  906. if
  907. {$ifdef MSWINDOWS}
  908. not winwidestringalloc and
  909. {$endif MSWINDOWS}
  910. not IsWideStringConstant(pointer(S))
  911. then
  912. begin
  913. Dec(Pointer(S),WideFirstOff);
  914. if SizeUInt(L*sizeof(WideChar)+WideRecLen)>MemSize(Pointer(S)) then
  915. reallocmem(pointer(S), L*sizeof(WideChar)+WideRecLen);
  916. Inc(Pointer(S), WideFirstOff);
  917. end
  918. else
  919. begin
  920. { Reallocation is needed... }
  921. Temp:=Pointer(NewWideString(L));
  922. if Length(S)>0 then
  923. begin
  924. if l < succ(length(s)) then
  925. movelen := l
  926. { also move terminating null }
  927. else
  928. movelen := succ(length(s));
  929. Move(Pointer(S)^,Temp^,movelen * Sizeof(WideChar));
  930. end;
  931. fpc_widestr_decr_ref(Pointer(S));
  932. Pointer(S):=Temp;
  933. end;
  934. { Force nil termination in case it gets shorter }
  935. PWord(Pointer(S)+l*sizeof(WideChar))^:=0;
  936. {$ifdef MSWINDOWS}
  937. if not winwidestringalloc then
  938. {$endif MSWINDOWS}
  939. PWideRec(Pointer(S)-WideFirstOff)^.Len:=l*sizeof(WideChar);
  940. end
  941. else
  942. begin
  943. { Length=0 }
  944. if Pointer(S)<>nil then
  945. fpc_widestr_decr_ref (Pointer(S));
  946. Pointer(S):=Nil;
  947. end;
  948. end;
  949. {*****************************************************************************
  950. Public functions, In interface.
  951. *****************************************************************************}
  952. function WideCharToString(S : PWideChar) : AnsiString;
  953. begin
  954. result:=WideCharLenToString(s,Length(WideString(s)));
  955. end;
  956. function StringToWideChar(const Src : AnsiString;Dest : PWideChar;DestSize : SizeInt) : PWideChar;
  957. var
  958. temp:widestring;
  959. begin
  960. widestringmanager.Ansi2WideMoveProc(PChar(Src),temp,Length(Src));
  961. if Length(temp)<DestSize then
  962. move(temp[1],Dest^,Length(temp)*SizeOf(WideChar))
  963. else
  964. move(temp[1],Dest^,(DestSize-1)*SizeOf(WideChar));
  965. Dest[DestSize-1]:=#0;
  966. result:=Dest;
  967. end;
  968. function WideCharLenToString(S : PWideChar;Len : SizeInt) : AnsiString;
  969. begin
  970. //SetLength(result,Len);
  971. widestringmanager.Wide2AnsiMoveproc(S,result,Len);
  972. end;
  973. procedure WideCharLenToStrVar(Src : PWideChar;Len : SizeInt;out Dest : AnsiString);
  974. begin
  975. Dest:=WideCharLenToString(Src,Len);
  976. end;
  977. procedure WideCharToStrVar(S : PWideChar;out Dest : AnsiString);
  978. begin
  979. Dest:=WideCharToString(S);
  980. end;
  981. Function fpc_widestr_Unique(Var S : Pointer): Pointer; [Public,Alias : 'FPC_WIDESTR_UNIQUE']; compilerproc;
  982. begin
  983. pointer(result) := pointer(s);
  984. end;
  985. Function Fpc_WideStr_Copy (Const S : WideString; Index,Size : SizeInt) : WideString;compilerproc;
  986. var
  987. ResultAddress : Pointer;
  988. begin
  989. ResultAddress:=Nil;
  990. dec(index);
  991. if Index < 0 then
  992. Index := 0;
  993. { Check Size. Accounts for Zero-length S, the double check is needed because
  994. Size can be maxint and will get <0 when adding index }
  995. if (Size>Length(S)) or
  996. (Index+Size>Length(S)) then
  997. Size:=Length(S)-Index;
  998. If Size>0 then
  999. begin
  1000. If Index<0 Then
  1001. Index:=0;
  1002. ResultAddress:=Pointer(NewWideString (Size));
  1003. if ResultAddress<>Nil then
  1004. begin
  1005. Move (PWideChar(S)[Index],ResultAddress^,Size*sizeof(WideChar));
  1006. PWideRec(ResultAddress-WideFirstOff)^.Len:=Size*sizeof(WideChar);
  1007. PWideChar(ResultAddress+Size*sizeof(WideChar))^:=#0;
  1008. end;
  1009. end;
  1010. fpc_widestr_decr_ref(Pointer(fpc_widestr_copy));
  1011. Pointer(fpc_widestr_Copy):=ResultAddress;
  1012. end;
  1013. Function Pos (Const Substr : WideString; Const Source : WideString) : SizeInt;
  1014. var
  1015. i,MaxLen : SizeInt;
  1016. pc : pwidechar;
  1017. begin
  1018. Pos:=0;
  1019. if Length(SubStr)>0 then
  1020. begin
  1021. MaxLen:=Length(source)-Length(SubStr);
  1022. i:=0;
  1023. pc:=@source[1];
  1024. while (i<=MaxLen) do
  1025. begin
  1026. inc(i);
  1027. if (SubStr[1]=pc^) and
  1028. (CompareWord(Substr[1],pc^,Length(SubStr))=0) then
  1029. begin
  1030. Pos:=i;
  1031. exit;
  1032. end;
  1033. inc(pc);
  1034. end;
  1035. end;
  1036. end;
  1037. { Faster version for a widechar alone }
  1038. Function Pos (c : WideChar; Const s : WideString) : SizeInt;
  1039. var
  1040. i: SizeInt;
  1041. pc : pwidechar;
  1042. begin
  1043. pc:=@s[1];
  1044. for i:=1 to length(s) do
  1045. begin
  1046. if pc^=c then
  1047. begin
  1048. pos:=i;
  1049. exit;
  1050. end;
  1051. inc(pc);
  1052. end;
  1053. pos:=0;
  1054. end;
  1055. Function Pos (c : WideChar; Const s : AnsiString) : SizeInt;
  1056. begin
  1057. result:=Pos(c,WideString(s));
  1058. end;
  1059. Function Pos (c : AnsiString; Const s : WideString) : SizeInt;{$ifdef SYSTEMINLINE}inline;{$endif}
  1060. begin
  1061. result:=Pos(WideString(c),s);
  1062. end;
  1063. Function Pos (c : ShortString; Const s : WideString) : SizeInt;{$ifdef SYSTEMINLINE}inline;{$endif}
  1064. begin
  1065. result:=Pos(WideString(c),s);
  1066. end;
  1067. Function Pos (c : WideString; Const s : AnsiString) : SizeInt;{$ifdef SYSTEMINLINE}inline;{$endif}
  1068. begin
  1069. result:=Pos(c,WideString(s));
  1070. end;
  1071. { Faster version for a char alone. Must be implemented because }
  1072. { pos(c: char; const s: shortstring) also exists, so otherwise }
  1073. { using pos(char,pchar) will always call the shortstring version }
  1074. { (exact match for first argument), also with $h+ (JM) }
  1075. Function Pos (c : Char; Const s : WideString) : SizeInt;
  1076. var
  1077. i: SizeInt;
  1078. wc : widechar;
  1079. pc : pwidechar;
  1080. begin
  1081. wc:=c;
  1082. pc:=@s[1];
  1083. for i:=1 to length(s) do
  1084. begin
  1085. if pc^=wc then
  1086. begin
  1087. pos:=i;
  1088. exit;
  1089. end;
  1090. inc(pc);
  1091. end;
  1092. pos:=0;
  1093. end;
  1094. Procedure Delete (Var S : WideString; Index,Size: SizeInt);
  1095. Var
  1096. LS : SizeInt;
  1097. begin
  1098. If Length(S)=0 then
  1099. exit;
  1100. if index<=0 then
  1101. exit;
  1102. LS:=PWideRec(Pointer(S)-WideFirstOff)^.Len div sizeof(WideChar);
  1103. if (Index<=LS) and (Size>0) then
  1104. begin
  1105. UniqueString (S);
  1106. if Size+Index>LS then
  1107. Size:=LS-Index+1;
  1108. if Index+Size<=LS then
  1109. begin
  1110. Dec(Index);
  1111. Move(PWideChar(S)[Index+Size],PWideChar(S)[Index],(LS-Index-Size+1)*sizeof(WideChar));
  1112. end;
  1113. Setlength(s,LS-Size);
  1114. end;
  1115. end;
  1116. Procedure Insert (Const Source : WideString; Var S : WideString; Index : SizeInt);
  1117. var
  1118. Temp : WideString;
  1119. LS : SizeInt;
  1120. begin
  1121. If Length(Source)=0 then
  1122. exit;
  1123. if index <= 0 then
  1124. index := 1;
  1125. Ls:=Length(S);
  1126. if index > LS then
  1127. index := LS+1;
  1128. Dec(Index);
  1129. Pointer(Temp) := NewWideString(Length(Source)+LS);
  1130. SetLength(Temp,Length(Source)+LS);
  1131. If Index>0 then
  1132. move (PWideChar(S)^,PWideChar(Temp)^,Index*sizeof(WideChar));
  1133. Move (PWideChar(Source)^,PWideChar(Temp)[Index],Length(Source)*sizeof(WideChar));
  1134. If (LS-Index)>0 then
  1135. Move(PWideChar(S)[Index],PWideChar(temp)[Length(Source)+index],(LS-Index)*sizeof(WideChar));
  1136. S:=Temp;
  1137. end;
  1138. function UpCase(const s : WideString) : WideString;
  1139. begin
  1140. result:=widestringmanager.UpperWideStringProc(s);
  1141. end;
  1142. Procedure SetString (Out S : WideString; Buf : PWideChar; Len : SizeInt);
  1143. var
  1144. BufLen: SizeInt;
  1145. begin
  1146. SetLength(S,Len);
  1147. If (Buf<>Nil) and (Len>0) then
  1148. begin
  1149. BufLen := IndexWord(Buf^, Len+1, 0);
  1150. If (BufLen>0) and (BufLen < Len) then
  1151. Len := BufLen;
  1152. Move (Buf[0],S[1],Len*sizeof(WideChar));
  1153. PWideChar(Pointer(S)+Len*sizeof(WideChar))^:=#0;
  1154. end;
  1155. end;
  1156. Procedure SetString (Out S : WideString; Buf : PChar; Len : SizeInt);
  1157. var
  1158. BufLen: SizeInt;
  1159. begin
  1160. SetLength(S,Len);
  1161. If (Buf<>Nil) and (Len>0) then
  1162. begin
  1163. BufLen := IndexByte(Buf^, Len+1, 0);
  1164. If (BufLen>0) and (BufLen < Len) then
  1165. Len := BufLen;
  1166. widestringmanager.Ansi2WideMoveProc(Buf,S,Len);
  1167. //PWideChar(Pointer(S)+Len*sizeof(WideChar))^:=#0;
  1168. end;
  1169. end;
  1170. {$ifndef FPUNONE}
  1171. Function fpc_Val_Real_WideStr(Const S : WideString; out Code : ValSInt): ValReal; [public, alias:'FPC_VAL_REAL_WIDESTR']; compilerproc;
  1172. Var
  1173. SS : String;
  1174. begin
  1175. fpc_Val_Real_WideStr := 0;
  1176. if length(S) > 255 then
  1177. code := 256
  1178. else
  1179. begin
  1180. SS := S;
  1181. Val(SS,fpc_Val_Real_WideStr,code);
  1182. end;
  1183. end;
  1184. {$endif}
  1185. function fpc_val_enum_widestr(str2ordindex:pointer;const s:widestring;out code:valsint):longint;compilerproc;
  1186. var ss:shortstring;
  1187. begin
  1188. if length(s)>255 then
  1189. code:=256
  1190. else
  1191. begin
  1192. ss:=s;
  1193. val(ss,fpc_val_enum_widestr,code);
  1194. end;
  1195. end;
  1196. Function fpc_Val_Currency_WideStr(Const S : WideString; out Code : ValSInt): Currency; [public, alias:'FPC_VAL_CURRENCY_WIDESTR']; compilerproc;
  1197. Var
  1198. SS : String;
  1199. begin
  1200. if length(S) > 255 then
  1201. begin
  1202. fpc_Val_Currency_WideStr:=0;
  1203. code := 256;
  1204. end
  1205. else
  1206. begin
  1207. SS := S;
  1208. Val(SS,fpc_Val_Currency_WideStr,code);
  1209. end;
  1210. end;
  1211. Function fpc_Val_UInt_WideStr (Const S : WideString; out Code : ValSInt): ValUInt; [public, alias:'FPC_VAL_UINT_WIDESTR']; compilerproc;
  1212. Var
  1213. SS : ShortString;
  1214. begin
  1215. fpc_Val_UInt_WideStr := 0;
  1216. if length(S) > 255 then
  1217. code := 256
  1218. else
  1219. begin
  1220. SS := S;
  1221. Val(SS,fpc_Val_UInt_WideStr,code);
  1222. end;
  1223. end;
  1224. Function fpc_Val_SInt_WideStr (DestSize: SizeInt; Const S : WideString; out Code : ValSInt): ValSInt; [public, alias:'FPC_VAL_SINT_WIDESTR']; compilerproc;
  1225. Var
  1226. SS : ShortString;
  1227. begin
  1228. fpc_Val_SInt_WideStr:=0;
  1229. if length(S)>255 then
  1230. code:=256
  1231. else
  1232. begin
  1233. SS := S;
  1234. fpc_Val_SInt_WideStr := int_Val_SInt_ShortStr(DestSize,SS,Code);
  1235. end;
  1236. end;
  1237. {$ifndef CPU64}
  1238. Function fpc_Val_qword_WideStr (Const S : WideString; out Code : ValSInt): qword; [public, alias:'FPC_VAL_QWORD_WIDESTR']; compilerproc;
  1239. Var
  1240. SS : ShortString;
  1241. begin
  1242. fpc_Val_qword_WideStr:=0;
  1243. if length(S)>255 then
  1244. code:=256
  1245. else
  1246. begin
  1247. SS := S;
  1248. Val(SS,fpc_Val_qword_WideStr,Code);
  1249. end;
  1250. end;
  1251. Function fpc_Val_int64_WideStr (Const S : WideString; out Code : ValSInt): Int64; [public, alias:'FPC_VAL_INT64_WIDESTR']; compilerproc;
  1252. Var
  1253. SS : ShortString;
  1254. begin
  1255. fpc_Val_int64_WideStr:=0;
  1256. if length(S)>255 then
  1257. code:=256
  1258. else
  1259. begin
  1260. SS := S;
  1261. Val(SS,fpc_Val_int64_WideStr,Code);
  1262. end;
  1263. end;
  1264. {$endif CPU64}
  1265. {$ifndef FPUNONE}
  1266. procedure fpc_WideStr_Float(d : ValReal;len,fr,rt : SizeInt;out s : WideString);compilerproc;
  1267. var
  1268. ss : shortstring;
  1269. begin
  1270. str_real(len,fr,d,treal_type(rt),ss);
  1271. s:=ss;
  1272. end;
  1273. {$endif}
  1274. procedure fpc_widestr_enum(ordinal,len:sizeint;typinfo,ord2strindex:pointer;out s:widestring);compilerproc;
  1275. var ss:shortstring;
  1276. begin
  1277. fpc_shortstr_enum(ordinal,len,typinfo,ord2strindex,ss);
  1278. s:=ss;
  1279. end;
  1280. {$ifdef FPC_HAS_STR_CURRENCY}
  1281. procedure fpc_WideStr_Currency(c : Currency;len,fr : SizeInt;out s : WideString);compilerproc;
  1282. var
  1283. ss : shortstring;
  1284. begin
  1285. str(c:len:fr,ss);
  1286. s:=ss;
  1287. end;
  1288. {$endif FPC_HAS_STR_CURRENCY}
  1289. Procedure fpc_WideStr_SInt(v : ValSint; Len : SizeInt; out S : WideString);compilerproc;
  1290. Var
  1291. SS : ShortString;
  1292. begin
  1293. Str (v:Len,SS);
  1294. S:=SS;
  1295. end;
  1296. Procedure fpc_WideStr_UInt(v : ValUInt;Len : SizeInt; out S : WideString);compilerproc;
  1297. Var
  1298. SS : ShortString;
  1299. begin
  1300. str(v:Len,SS);
  1301. S:=SS;
  1302. end;
  1303. {$ifndef CPU64}
  1304. Procedure fpc_WideStr_Int64(v : Int64; Len : SizeInt; out S : WideString);compilerproc;
  1305. Var
  1306. SS : ShortString;
  1307. begin
  1308. Str (v:Len,SS);
  1309. S:=SS;
  1310. end;
  1311. Procedure fpc_WideStr_Qword(v : Qword;Len : SizeInt; out S : WideString);compilerproc;
  1312. Var
  1313. SS : ShortString;
  1314. begin
  1315. str(v:Len,SS);
  1316. S:=SS;
  1317. end;
  1318. {$endif CPU64}
  1319. function UnicodeToUtf8(Dest: PChar; Source: PWideChar; MaxBytes: SizeInt): SizeInt;{$ifdef SYSTEMINLINE}inline;{$endif}
  1320. begin
  1321. if assigned(Source) then
  1322. Result:=UnicodeToUtf8(Dest,MaxBytes,Source,IndexWord(Source^,-1,0))
  1323. else
  1324. Result:=0;
  1325. end;
  1326. function UnicodeToUtf8(Dest: PChar; MaxDestBytes: SizeUInt; Source: PWideChar; SourceChars: SizeUInt): SizeUInt;
  1327. var
  1328. i,j : SizeUInt;
  1329. w : word;
  1330. begin
  1331. result:=0;
  1332. if source=nil then
  1333. exit;
  1334. i:=0;
  1335. j:=0;
  1336. if assigned(Dest) then
  1337. begin
  1338. while (i<SourceChars) and (j<MaxDestBytes) do
  1339. begin
  1340. w:=word(Source[i]);
  1341. case w of
  1342. 0..$7f:
  1343. begin
  1344. Dest[j]:=char(w);
  1345. inc(j);
  1346. end;
  1347. $80..$7ff:
  1348. begin
  1349. if j+1>=MaxDestBytes then
  1350. break;
  1351. Dest[j]:=char($c0 or (w shr 6));
  1352. Dest[j+1]:=char($80 or (w and $3f));
  1353. inc(j,2);
  1354. end;
  1355. else
  1356. begin
  1357. if j+2>=MaxDestBytes then
  1358. break;
  1359. Dest[j]:=char($e0 or (w shr 12));
  1360. Dest[j+1]:=char($80 or ((w shr 6)and $3f));
  1361. Dest[j+2]:=char($80 or (w and $3f));
  1362. inc(j,3);
  1363. end;
  1364. end;
  1365. inc(i);
  1366. end;
  1367. if j>SizeUInt(MaxDestBytes-1) then
  1368. j:=MaxDestBytes-1;
  1369. Dest[j]:=#0;
  1370. end
  1371. else
  1372. begin
  1373. while i<SourceChars do
  1374. begin
  1375. case word(Source[i]) of
  1376. $0..$7f:
  1377. inc(j);
  1378. $80..$7ff:
  1379. inc(j,2);
  1380. else
  1381. inc(j,3);
  1382. end;
  1383. inc(i);
  1384. end;
  1385. end;
  1386. result:=j+1;
  1387. end;
  1388. function Utf8ToUnicode(Dest: PWideChar; Source: PChar; MaxChars: SizeInt): SizeInt;{$ifdef SYSTEMINLINE}inline;{$endif}
  1389. begin
  1390. if assigned(Source) then
  1391. Result:=Utf8ToUnicode(Dest,MaxChars,Source,strlen(Source))
  1392. else
  1393. Result:=0;
  1394. end;
  1395. function Utf8ToUnicode(Dest: PWideChar; MaxDestChars: SizeUInt; Source: PChar; SourceBytes: SizeUInt): SizeUInt;
  1396. var
  1397. i,j : SizeUInt;
  1398. w: SizeUInt;
  1399. b : byte;
  1400. begin
  1401. if not assigned(Source) then
  1402. begin
  1403. result:=0;
  1404. exit;
  1405. end;
  1406. result:=SizeUInt(-1);
  1407. i:=0;
  1408. j:=0;
  1409. if assigned(Dest) then
  1410. begin
  1411. while (j<MaxDestChars) and (i<SourceBytes) do
  1412. begin
  1413. b:=byte(Source[i]);
  1414. w:=b;
  1415. inc(i);
  1416. // 2 or 3 bytes?
  1417. if b>=$80 then
  1418. begin
  1419. w:=b and $3f;
  1420. if i>=SourceBytes then
  1421. exit;
  1422. // 3 bytes?
  1423. if (b and $20)<>0 then
  1424. begin
  1425. b:=byte(Source[i]);
  1426. inc(i);
  1427. if i>=SourceBytes then
  1428. exit;
  1429. if (b and $c0)<>$80 then
  1430. exit;
  1431. w:=(w shl 6) or (b and $3f);
  1432. end;
  1433. b:=byte(Source[i]);
  1434. w:=(w shl 6) or (b and $3f);
  1435. if (b and $c0)<>$80 then
  1436. exit;
  1437. inc(i);
  1438. end;
  1439. Dest[j]:=WideChar(w);
  1440. inc(j);
  1441. end;
  1442. if j>=MaxDestChars then j:=MaxDestChars-1;
  1443. Dest[j]:=#0;
  1444. end
  1445. else
  1446. begin
  1447. while i<SourceBytes do
  1448. begin
  1449. b:=byte(Source[i]);
  1450. inc(i);
  1451. // 2 or 3 bytes?
  1452. if b>=$80 then
  1453. begin
  1454. if i>=SourceBytes then
  1455. exit;
  1456. // 3 bytes?
  1457. b := b and $3f;
  1458. if (b and $20)<>0 then
  1459. begin
  1460. b:=byte(Source[i]);
  1461. inc(i);
  1462. if i>=SourceBytes then
  1463. exit;
  1464. if (b and $c0)<>$80 then
  1465. exit;
  1466. end;
  1467. if (byte(Source[i]) and $c0)<>$80 then
  1468. exit;
  1469. inc(i);
  1470. end;
  1471. inc(j);
  1472. end;
  1473. end;
  1474. result:=j+1;
  1475. end;
  1476. function UTF8Encode(const s : WideString) : UTF8String;
  1477. var
  1478. i : SizeInt;
  1479. hs : UTF8String;
  1480. begin
  1481. result:='';
  1482. if s='' then
  1483. exit;
  1484. SetLength(hs,length(s)*3);
  1485. i:=UnicodeToUtf8(pchar(hs),length(hs)+1,PWideChar(s),length(s));
  1486. if i>0 then
  1487. begin
  1488. SetLength(hs,i-1);
  1489. result:=hs;
  1490. end;
  1491. end;
  1492. { converts an utf-16 code point or surrogate pair to utf-32 }
  1493. function utf16toutf32(const S: WideString; const index: SizeInt; out len: longint): UCS4Char; [public, alias: 'FPC_WIDETOUTF32'];
  1494. var
  1495. w: widechar;
  1496. begin
  1497. { UTF-16 points in the range #$0-#$D7FF and #$E000-#$FFFF }
  1498. { are the same in UTF-32 }
  1499. w:=s[index];
  1500. if (w<=#$d7ff) or
  1501. (w>=#$e000) then
  1502. begin
  1503. result:=UCS4Char(w);
  1504. len:=1;
  1505. end
  1506. { valid surrogate pair? }
  1507. else if (w<=#$dbff) and
  1508. { w>=#$d7ff check not needed, checked above }
  1509. (index<length(s)) and
  1510. (s[index+1]>=#$dc00) and
  1511. (s[index+1]<=#$dfff) then
  1512. { convert the surrogate pair to UTF-32 }
  1513. begin
  1514. result:=(UCS4Char(w)-$d800) shl 10 + (UCS4Char(s[index+1])-$dc00) + $10000;
  1515. len:=2;
  1516. end
  1517. else
  1518. { invalid surrogate -> do nothing }
  1519. begin
  1520. result:=UCS4Char(w);
  1521. len:=1;
  1522. end;
  1523. end;
  1524. function WideStringToUCS4String(const s : WideString) : UCS4String;
  1525. var
  1526. i, slen,
  1527. destindex : SizeInt;
  1528. len : longint;
  1529. begin
  1530. slen:=length(s);
  1531. setlength(result,slen+1);
  1532. i:=1;
  1533. destindex:=0;
  1534. while (i<=slen) do
  1535. begin
  1536. result[destindex]:=utf16toutf32(s,i,len);
  1537. inc(destindex);
  1538. inc(i,len);
  1539. end;
  1540. { destindex <= slen (surrogate pairs may have been merged) }
  1541. { destindex+1 for terminating #0 (dynamic arrays are }
  1542. { implicitely filled with zero) }
  1543. setlength(result,destindex+1);
  1544. end;
  1545. { concatenates an utf-32 char to a widestring. S *must* be unique when entering. }
  1546. procedure ConcatUTF32ToWideStr(const nc: UCS4Char; var S: WideString; var index: SizeInt);
  1547. var
  1548. p : PWideChar;
  1549. begin
  1550. { if nc > $ffff, we need two places }
  1551. if (index+ord(nc > $ffff)>length(s)) then
  1552. if (length(s) < 10*256) then
  1553. setlength(s,length(s)+10)
  1554. else
  1555. setlength(s,length(s)+length(s) shr 8);
  1556. { we know that s is unique -> avoid uniquestring calls}
  1557. p:=@s[index];
  1558. if (nc<$ffff) then
  1559. begin
  1560. p^:=widechar(nc);
  1561. inc(index);
  1562. end
  1563. else if (dword(nc)<=$10ffff) then
  1564. begin
  1565. p^:=widechar((nc - $10000) shr 10 + $d800);
  1566. (p+1)^:=widechar((nc - $10000) and $3ff + $dc00);
  1567. inc(index,2);
  1568. end
  1569. else
  1570. { invalid code point }
  1571. begin
  1572. p^:='?';
  1573. inc(index);
  1574. end;
  1575. end;
  1576. function UCS4StringToWideString(const s : UCS4String) : WideString;
  1577. var
  1578. i : SizeInt;
  1579. resindex : SizeInt;
  1580. begin
  1581. { skip terminating #0 }
  1582. SetLength(result,length(s)-1);
  1583. resindex:=1;
  1584. for i:=0 to high(s)-1 do
  1585. ConcatUTF32ToWideStr(s[i],result,resindex);
  1586. { adjust result length (may be too big due to growing }
  1587. { for surrogate pairs) }
  1588. setlength(result,resindex-1);
  1589. end;
  1590. const
  1591. SNoWidestrings = 'This binary has no widestrings support compiled in.';
  1592. SRecompileWithWidestrings = 'Recompile the application with a widestrings-manager in the program uses clause.';
  1593. procedure unimplementedwidestring;
  1594. begin
  1595. {$ifdef FPC_HAS_FEATURE_CONSOLEIO}
  1596. If IsConsole then
  1597. begin
  1598. Writeln(StdErr,SNoWidestrings);
  1599. Writeln(StdErr,SRecompileWithWidestrings);
  1600. end;
  1601. {$endif FPC_HAS_FEATURE_CONSOLEIO}
  1602. HandleErrorFrame(233,get_frame);
  1603. end;
  1604. {$warnings off}
  1605. function GenericWideCase(const s : WideString) : WideString;
  1606. begin
  1607. unimplementedwidestring;
  1608. end;
  1609. function CompareWideString(const s1, s2 : WideString) : PtrInt;
  1610. begin
  1611. unimplementedwidestring;
  1612. end;
  1613. function CompareTextWideString(const s1, s2 : WideString): PtrInt;
  1614. begin
  1615. unimplementedwidestring;
  1616. end;
  1617. function CharLengthPChar(const Str: PChar): PtrInt;
  1618. begin
  1619. unimplementedwidestring;
  1620. end;
  1621. {$warnings on}
  1622. procedure initwidestringmanager;
  1623. begin
  1624. fillchar(widestringmanager,sizeof(widestringmanager),0);
  1625. {$ifndef HAS_WIDESTRINGMANAGER}
  1626. widestringmanager.Wide2AnsiMoveProc:=@defaultWide2AnsiMove;
  1627. widestringmanager.Ansi2WideMoveProc:=@defaultAnsi2WideMove;
  1628. widestringmanager.UpperWideStringProc:=@GenericWideCase;
  1629. widestringmanager.LowerWideStringProc:=@GenericWideCase;
  1630. {$endif HAS_WIDESTRINGMANAGER}
  1631. widestringmanager.CompareWideStringProc:=@CompareWideString;
  1632. widestringmanager.CompareTextWideStringProc:=@CompareTextWideString;
  1633. widestringmanager.CharLengthPCharProc:=@CharLengthPChar;
  1634. end;