wstrings.inc 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657
  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_WideStr(const p : pwidechar): widestring; compilerproc;
  266. var
  267. Size : SizeInt;
  268. begin
  269. result:='';
  270. if p=nil then
  271. exit;
  272. Size := IndexWord(p^, -1, 0);
  273. Setlength(result,Size);
  274. if Size>0 then
  275. begin
  276. Move(p^,PWideChar(Pointer(result))^,Size*sizeof(WideChar));
  277. { Terminating Zero }
  278. PWideChar(Pointer(result)+Size*sizeof(WideChar))^:=#0;
  279. end;
  280. end;
  281. { checked against the ansistring routine, 2001-05-27 (FK) }
  282. Procedure fpc_WideStr_Assign (Var S1 : Pointer;S2 : Pointer);[Public,Alias:'FPC_WIDESTR_ASSIGN']; compilerproc;
  283. {
  284. Assigns S2 to S1 (S1:=S2), taking in account reference counts.
  285. }
  286. begin
  287. if S1=S2 then exit;
  288. if S2<>nil then
  289. begin
  290. if IsWideStringConstant(S1) then
  291. begin
  292. S1:=NewWidestring(length(WideString(S2)));
  293. move(s2^,s1^,(length(WideString(s1))+1)*sizeof(widechar));
  294. end
  295. else
  296. {$ifdef MSWINDOWS}
  297. if winwidestringalloc then
  298. begin
  299. if SysReAllocStringLen(S1, S2, Length(WideString(S2))) = 0 then
  300. WideStringError;
  301. end
  302. else
  303. {$endif MSWINDOWS}
  304. begin
  305. SetLength(WideString(S1),length(WideString(S2)));
  306. move(s2^,s1^,(length(WideString(s1))+1)*sizeof(widechar));
  307. end;
  308. end
  309. else
  310. begin
  311. { Free S1 }
  312. fpc_widestr_decr_ref (S1);
  313. S1:=nil;
  314. end;
  315. end;
  316. { alias for internal use }
  317. Procedure fpc_WideStr_Assign (Var S1 : Pointer;S2 : Pointer);[external name 'FPC_WIDESTR_ASSIGN'];
  318. {$ifndef STR_CONCAT_PROCS}
  319. function fpc_WideStr_Concat (const S1,S2 : WideString): WideString; compilerproc;
  320. Var
  321. Size,Location : SizeInt;
  322. pc : pwidechar;
  323. begin
  324. { only assign if s1 or s2 is empty }
  325. if (S1='') then
  326. begin
  327. result:=s2;
  328. exit;
  329. end;
  330. if (S2='') then
  331. begin
  332. result:=s1;
  333. exit;
  334. end;
  335. Location:=Length(S1);
  336. Size:=length(S2);
  337. SetLength(result,Size+Location);
  338. pc:=pwidechar(result);
  339. Move(S1[1],pc^,Location*sizeof(WideChar));
  340. inc(pc,location);
  341. Move(S2[1],pc^,(Size+1)*sizeof(WideChar));
  342. end;
  343. function fpc_WideStr_Concat_multi (const sarr:array of Widestring): widestring; compilerproc;
  344. Var
  345. i : Longint;
  346. p : pointer;
  347. pc : pwidechar;
  348. Size,NewSize : SizeInt;
  349. begin
  350. { First calculate size of the result so we can do
  351. a single call to SetLength() }
  352. NewSize:=0;
  353. for i:=low(sarr) to high(sarr) do
  354. inc(Newsize,length(sarr[i]));
  355. SetLength(result,NewSize);
  356. pc:=pwidechar(result);
  357. for i:=low(sarr) to high(sarr) do
  358. begin
  359. p:=pointer(sarr[i]);
  360. if assigned(p) then
  361. begin
  362. Size:=length(widestring(p));
  363. Move(pwidechar(p)^,pc^,(Size+1)*sizeof(WideChar));
  364. inc(pc,size);
  365. end;
  366. end;
  367. end;
  368. {$else STR_CONCAT_PROCS}
  369. procedure fpc_WideStr_Concat (var DestS:Widestring;const S1,S2 : WideString); compilerproc;
  370. Var
  371. Size,Location : SizeInt;
  372. same : boolean;
  373. begin
  374. { only assign if s1 or s2 is empty }
  375. if (S1='') then
  376. begin
  377. DestS:=s2;
  378. exit;
  379. end;
  380. if (S2='') then
  381. begin
  382. DestS:=s1;
  383. exit;
  384. end;
  385. Location:=Length(S1);
  386. Size:=length(S2);
  387. { Use Pointer() typecasts to prevent extra conversion code }
  388. if Pointer(DestS)=Pointer(S1) then
  389. begin
  390. same:=Pointer(S1)=Pointer(S2);
  391. SetLength(DestS,Size+Location);
  392. if same then
  393. Move(Pointer(DestS)^,(Pointer(DestS)+Location*sizeof(WideChar))^,(Size)*sizeof(WideChar))
  394. else
  395. Move(Pointer(S2)^,(Pointer(DestS)+Location*sizeof(WideChar))^,(Size+1)*sizeof(WideChar));
  396. end
  397. else if Pointer(DestS)=Pointer(S2) then
  398. begin
  399. SetLength(DestS,Size+Location);
  400. Move(Pointer(DestS)^,(Pointer(DestS)+Location*sizeof(WideChar))^,(Size+1)*sizeof(WideChar));
  401. Move(Pointer(S1)^,Pointer(DestS)^,Location*sizeof(WideChar));
  402. end
  403. else
  404. begin
  405. DestS:='';
  406. SetLength(DestS,Size+Location);
  407. Move(Pointer(S1)^,Pointer(DestS)^,Location*sizeof(WideChar));
  408. Move(Pointer(S2)^,(Pointer(DestS)+Location*sizeof(WideChar))^,(Size+1)*sizeof(WideChar));
  409. end;
  410. end;
  411. procedure fpc_WideStr_Concat_multi (var DestS:Widestring;const sarr:array of Widestring); compilerproc;
  412. Var
  413. i : Longint;
  414. p,pc : pointer;
  415. Size,NewLen : SizeInt;
  416. DestTmp : Widestring;
  417. begin
  418. if high(sarr)=0 then
  419. begin
  420. DestS:='';
  421. exit;
  422. end;
  423. { First calculate size of the result so we can do
  424. a single call to SetLength() }
  425. NewLen:=0;
  426. for i:=low(sarr) to high(sarr) do
  427. inc(NewLen,length(sarr[i]));
  428. SetLength(DestTmp,NewLen);
  429. pc:=pwidechar(DestTmp);
  430. for i:=low(sarr) to high(sarr) do
  431. begin
  432. p:=pointer(sarr[i]);
  433. if assigned(p) then
  434. begin
  435. Size:=length(widestring(p));
  436. Move(p^,pc^,(Size+1)*sizeof(WideChar));
  437. inc(pc,size*sizeof(WideChar));
  438. end;
  439. end;
  440. DestS:=DestTmp;
  441. end;
  442. {$endif STR_CONCAT_PROCS}
  443. Function fpc_Char_To_WChar(const c : Char): WideChar; compilerproc;
  444. var
  445. w: widestring;
  446. begin
  447. widestringmanager.Ansi2WideMoveProc(@c, w, 1);
  448. fpc_Char_To_WChar:= w[1];
  449. end;
  450. Function fpc_Char_To_WideStr(const c : Char): WideString; compilerproc;
  451. {
  452. Converts a Char to a WideString;
  453. }
  454. begin
  455. Setlength(fpc_Char_To_WideStr,1);
  456. fpc_Char_To_WideStr[1]:=c;
  457. { Terminating Zero }
  458. PWideChar(Pointer(fpc_Char_To_WideStr)+sizeof(WideChar))^:=#0;
  459. end;
  460. Function fpc_WChar_To_Char(const c : WideChar): Char; compilerproc;
  461. {
  462. Converts a WideChar to a Char;
  463. }
  464. var
  465. s: ansistring;
  466. begin
  467. widestringmanager.Wide2AnsiMoveProc(@c, s, 1);
  468. if length(s)=1 then
  469. fpc_WChar_To_Char:= s[1]
  470. else
  471. fpc_WChar_To_Char:='?';
  472. end;
  473. Function fpc_WChar_To_WideStr(const c : WideChar): WideString; compilerproc;
  474. {
  475. Converts a WideChar to a WideString;
  476. }
  477. begin
  478. Setlength (fpc_WChar_To_WideStr,1);
  479. fpc_WChar_To_WideStr[1]:= c;
  480. end;
  481. Function fpc_WChar_To_AnsiStr(const c : WideChar): AnsiString; compilerproc;
  482. {
  483. Converts a WideChar to a AnsiString;
  484. }
  485. begin
  486. widestringmanager.Wide2AnsiMoveProc(@c, fpc_WChar_To_AnsiStr, 1);
  487. end;
  488. Function fpc_UChar_To_WideStr(const c : WideChar): WideString; compilerproc;
  489. {
  490. Converts a WideChar to a WideString;
  491. }
  492. begin
  493. Setlength (fpc_UChar_To_WideStr,1);
  494. fpc_UChar_To_WideStr[1]:= c;
  495. end;
  496. {$ifndef FPC_STRTOSHORTSTRINGPROC}
  497. Function fpc_WChar_To_ShortStr(const c : WideChar): ShortString; compilerproc;
  498. {
  499. Converts a WideChar to a ShortString;
  500. }
  501. var
  502. s: ansistring;
  503. begin
  504. widestringmanager.Wide2AnsiMoveProc(@c, s, 1);
  505. fpc_WChar_To_ShortStr:= s;
  506. end;
  507. {$else FPC_STRTOSHORTSTRINGPROC}
  508. procedure fpc_WChar_To_ShortStr(out res : shortstring;const c : WideChar) compilerproc;
  509. {
  510. Converts a WideChar to a ShortString;
  511. }
  512. var
  513. s: ansistring;
  514. begin
  515. widestringmanager.Wide2AnsiMoveProc(@c,s,1);
  516. res:=s;
  517. end;
  518. {$endif FPC_STRTOSHORTSTRINGPROC}
  519. Function fpc_PChar_To_WideStr(const p : pchar): WideString; compilerproc;
  520. Var
  521. L : SizeInt;
  522. begin
  523. if (not assigned(p)) or (p[0]=#0) Then
  524. begin
  525. fpc_pchar_to_widestr := '';
  526. exit;
  527. end;
  528. l:=IndexChar(p^,-1,#0);
  529. widestringmanager.Ansi2WideMoveProc(P,fpc_PChar_To_WideStr,l);
  530. end;
  531. Function fpc_CharArray_To_WideStr(const arr: array of char; zerobased: boolean = true): WideString; compilerproc;
  532. var
  533. i : SizeInt;
  534. begin
  535. if (zerobased) then
  536. begin
  537. if (arr[0]=#0) Then
  538. begin
  539. fpc_chararray_to_widestr := '';
  540. exit;
  541. end;
  542. i:=IndexChar(arr,high(arr)+1,#0);
  543. if i = -1 then
  544. i := high(arr)+1;
  545. end
  546. else
  547. i := high(arr)+1;
  548. SetLength(fpc_CharArray_To_WideStr,i);
  549. widestringmanager.Ansi2WideMoveProc (pchar(@arr),fpc_CharArray_To_WideStr,i);
  550. end;
  551. {$ifndef FPC_STRTOCHARARRAYPROC}
  552. { inside the compiler, the resulttype is modified to that of the actual }
  553. { chararray we're converting to (JM) }
  554. function fpc_widestr_to_chararray(arraysize: SizeInt; const src: WideString): fpc_big_chararray;[public,alias: 'FPC_WIDESTR_TO_CHARARRAY']; compilerproc;
  555. var
  556. len: SizeInt;
  557. temp: ansistring;
  558. begin
  559. len := length(src);
  560. { make sure we don't dereference src if it can be nil (JM) }
  561. if len > 0 then
  562. widestringmanager.wide2ansimoveproc(pwidechar(@src[1]),temp,len);
  563. len := length(temp);
  564. if len > arraysize then
  565. len := arraysize;
  566. {$r-}
  567. move(temp[1],fpc_widestr_to_chararray[0],len);
  568. fillchar(fpc_widestr_to_chararray[len],arraysize-len,0);
  569. {$ifdef RangeCheckWasOn}
  570. {$r+}
  571. {$endif}
  572. end;
  573. { inside the compiler, the resulttype is modified to that of the actual }
  574. { widechararray we're converting to (JM) }
  575. function fpc_widestr_to_widechararray(arraysize: SizeInt; const src: WideString): fpc_big_widechararray;[public,alias: 'FPC_WIDESTR_TO_WIDECHARARRAY']; compilerproc;
  576. var
  577. len: SizeInt;
  578. begin
  579. len := length(src);
  580. if len > arraysize then
  581. len := arraysize;
  582. {$r-}
  583. { make sure we don't try to access element 1 of the ansistring if it's nil }
  584. if len > 0 then
  585. move(src[1],fpc_widestr_to_widechararray[0],len*SizeOf(WideChar));
  586. fillchar(fpc_widestr_to_widechararray[len],(arraysize-len)*SizeOf(WideChar),0);
  587. {$ifdef RangeCheckWasOn}
  588. {$r+}
  589. {$endif}
  590. end;
  591. { inside the compiler, the resulttype is modified to that of the actual }
  592. { chararray we're converting to (JM) }
  593. function fpc_ansistr_to_widechararray(arraysize: SizeInt; const src: AnsiString): fpc_big_widechararray;[public,alias: 'FPC_ANSISTR_TO_WIDECHARARRAY']; compilerproc;
  594. var
  595. len: SizeInt;
  596. temp: widestring;
  597. begin
  598. len := length(src);
  599. { make sure we don't dereference src if it can be nil (JM) }
  600. if len > 0 then
  601. widestringmanager.ansi2widemoveproc(pchar(@src[1]),temp,len);
  602. len := length(temp);
  603. if len > arraysize then
  604. len := arraysize;
  605. {$r-}
  606. move(temp[1],fpc_ansistr_to_widechararray[0],len*sizeof(widechar));
  607. fillchar(fpc_ansistr_to_widechararray[len],(arraysize-len)*SizeOf(WideChar),0);
  608. {$ifdef RangeCheckWasOn}
  609. {$r+}
  610. {$endif}
  611. end;
  612. function fpc_shortstr_to_widechararray(arraysize: SizeInt; const src: ShortString): fpc_big_widechararray;[public,alias: 'FPC_SHORTSTR_TO_WIDECHARARRAY']; compilerproc;
  613. var
  614. len: longint;
  615. temp : widestring;
  616. begin
  617. len := length(src);
  618. { make sure we don't access char 1 if length is 0 (JM) }
  619. if len > 0 then
  620. widestringmanager.ansi2widemoveproc(pchar(@src[1]),temp,len);
  621. len := length(temp);
  622. if len > arraysize then
  623. len := arraysize;
  624. {$r-}
  625. move(temp[1],fpc_shortstr_to_widechararray[0],len*sizeof(widechar));
  626. fillchar(fpc_shortstr_to_widechararray[len],(arraysize-len)*SizeOf(WideChar),0);
  627. {$ifdef RangeCheckWasOn}
  628. {$r+}
  629. {$endif}
  630. end;
  631. {$else ndef FPC_STRTOCHARARRAYPROC}
  632. procedure fpc_widestr_to_chararray(out res: array of char; const src: WideString); compilerproc;
  633. var
  634. len: SizeInt;
  635. temp: ansistring;
  636. begin
  637. len := length(src);
  638. { make sure we don't dereference src if it can be nil (JM) }
  639. if len > 0 then
  640. widestringmanager.wide2ansimoveproc(pwidechar(@src[1]),temp,len);
  641. len := length(temp);
  642. if len > length(res) then
  643. len := length(res);
  644. {$r-}
  645. move(temp[1],res[0],len);
  646. fillchar(res[len],length(res)-len,0);
  647. {$ifdef RangeCheckWasOn}
  648. {$r+}
  649. {$endif}
  650. end;
  651. procedure fpc_widestr_to_widechararray(out res: array of widechar; const src: WideString); compilerproc;
  652. var
  653. len: SizeInt;
  654. begin
  655. len := length(src);
  656. if len > length(res) then
  657. len := length(res);
  658. {$r-}
  659. { make sure we don't try to access element 1 of the ansistring if it's nil }
  660. if len > 0 then
  661. move(src[1],res[0],len*SizeOf(WideChar));
  662. fillchar(res[len],(length(res)-len)*SizeOf(WideChar),0);
  663. {$ifdef RangeCheckWasOn}
  664. {$r+}
  665. {$endif}
  666. end;
  667. {$endif ndef FPC_STRTOCHARARRAYPROC}
  668. Function fpc_WideStr_Compare(const S1,S2 : WideString): SizeInt;[Public,Alias : 'FPC_WIDESTR_COMPARE']; compilerproc;
  669. {
  670. Compares 2 WideStrings;
  671. The result is
  672. <0 if S1<S2
  673. 0 if S1=S2
  674. >0 if S1>S2
  675. }
  676. Var
  677. MaxI,Temp : SizeInt;
  678. begin
  679. if pointer(S1)=pointer(S2) then
  680. begin
  681. fpc_WideStr_Compare:=0;
  682. exit;
  683. end;
  684. Maxi:=Length(S1);
  685. temp:=Length(S2);
  686. If MaxI>Temp then
  687. MaxI:=Temp;
  688. Temp:=CompareWord(S1[1],S2[1],MaxI);
  689. if temp=0 then
  690. temp:=Length(S1)-Length(S2);
  691. fpc_WideStr_Compare:=Temp;
  692. end;
  693. Function fpc_WideStr_Compare_Equal(const S1,S2 : WideString): SizeInt;[Public,Alias : 'FPC_WIDESTR_COMPARE_EQUAL']; compilerproc;
  694. {
  695. Compares 2 WideStrings for equality only;
  696. The result is
  697. 0 if S1=S2
  698. <>0 if S1<>S2
  699. }
  700. Var
  701. MaxI : SizeInt;
  702. begin
  703. if pointer(S1)=pointer(S2) then
  704. exit(0);
  705. Maxi:=Length(S1);
  706. If MaxI<>Length(S2) then
  707. exit(-1)
  708. else
  709. exit(CompareWord(S1[1],S2[1],MaxI));
  710. end;
  711. Procedure fpc_WideStr_CheckZero(p : pointer);[Public,Alias : 'FPC_WIDESTR_CHECKZERO']; compilerproc;
  712. begin
  713. if p=nil then
  714. HandleErrorFrame(201,get_frame);
  715. end;
  716. Procedure fpc_WideStr_CheckRange(len,index : SizeInt);[Public,Alias : 'FPC_WIDESTR_RANGECHECK']; compilerproc;
  717. begin
  718. if (index>len div 2) or (Index<1) then
  719. HandleErrorFrame(201,get_frame);
  720. end;
  721. Procedure fpc_WideStr_SetLength(Var S : WideString; l : SizeInt);[Public,Alias : 'FPC_WIDESTR_SETLENGTH']; compilerproc;
  722. {
  723. Sets The length of string S to L.
  724. Makes sure S is unique, and contains enough room.
  725. }
  726. Var
  727. Temp : Pointer;
  728. movelen: SizeInt;
  729. begin
  730. if (l>0) then
  731. begin
  732. if Pointer(S)=nil then
  733. begin
  734. { Need a complete new string...}
  735. Pointer(s):=NewWideString(l);
  736. end
  737. { windows doesn't support reallocing widestrings, this code
  738. is anyways subject to be removed because widestrings shouldn't be
  739. ref. counted anymore (FK) }
  740. else
  741. if
  742. {$ifdef MSWINDOWS}
  743. not winwidestringalloc and
  744. {$endif MSWINDOWS}
  745. not IsWideStringConstant(pointer(S))
  746. then
  747. begin
  748. Dec(Pointer(S),WideFirstOff);
  749. if SizeUInt(L*sizeof(WideChar)+WideRecLen)>MemSize(Pointer(S)) then
  750. reallocmem(pointer(S), L*sizeof(WideChar)+WideRecLen);
  751. Inc(Pointer(S), WideFirstOff);
  752. end
  753. else
  754. begin
  755. { Reallocation is needed... }
  756. Temp:=Pointer(NewWideString(L));
  757. if Length(S)>0 then
  758. begin
  759. if l < succ(length(s)) then
  760. movelen := l
  761. { also move terminating null }
  762. else
  763. movelen := succ(length(s));
  764. Move(Pointer(S)^,Temp^,movelen * Sizeof(WideChar));
  765. end;
  766. fpc_widestr_decr_ref(Pointer(S));
  767. Pointer(S):=Temp;
  768. end;
  769. { Force nil termination in case it gets shorter }
  770. PWord(Pointer(S)+l*sizeof(WideChar))^:=0;
  771. {$ifdef MSWINDOWS}
  772. if not winwidestringalloc then
  773. {$endif MSWINDOWS}
  774. PWideRec(Pointer(S)-WideFirstOff)^.Len:=l*sizeof(WideChar);
  775. end
  776. else
  777. begin
  778. { Length=0 }
  779. if Pointer(S)<>nil then
  780. fpc_widestr_decr_ref (Pointer(S));
  781. Pointer(S):=Nil;
  782. end;
  783. end;
  784. {*****************************************************************************
  785. Public functions, In interface.
  786. *****************************************************************************}
  787. function WideCharToString(S : PWideChar) : AnsiString;
  788. begin
  789. result:=WideCharLenToString(s,Length(WideString(s)));
  790. end;
  791. function StringToWideChar(const Src : AnsiString;Dest : PWideChar;DestSize : SizeInt) : PWideChar;
  792. var
  793. temp:widestring;
  794. begin
  795. widestringmanager.Ansi2WideMoveProc(PChar(Src),temp,Length(Src));
  796. if Length(temp)<DestSize then
  797. move(temp[1],Dest^,Length(temp)*SizeOf(WideChar))
  798. else
  799. move(temp[1],Dest^,(DestSize-1)*SizeOf(WideChar));
  800. Dest[DestSize-1]:=#0;
  801. result:=Dest;
  802. end;
  803. function WideCharLenToString(S : PWideChar;Len : SizeInt) : AnsiString;
  804. begin
  805. //SetLength(result,Len);
  806. widestringmanager.Wide2AnsiMoveproc(S,result,Len);
  807. end;
  808. procedure WideCharLenToStrVar(Src : PWideChar;Len : SizeInt;out Dest : AnsiString);
  809. begin
  810. Dest:=WideCharLenToString(Src,Len);
  811. end;
  812. procedure WideCharToStrVar(S : PWideChar;out Dest : AnsiString);
  813. begin
  814. Dest:=WideCharToString(S);
  815. end;
  816. Function fpc_widestr_Unique(Var S : Pointer): Pointer; [Public,Alias : 'FPC_WIDESTR_UNIQUE']; compilerproc;
  817. begin
  818. pointer(result) := pointer(s);
  819. end;
  820. Function Fpc_WideStr_Copy (Const S : WideString; Index,Size : SizeInt) : WideString;compilerproc;
  821. var
  822. ResultAddress : Pointer;
  823. begin
  824. ResultAddress:=Nil;
  825. dec(index);
  826. if Index < 0 then
  827. Index := 0;
  828. { Check Size. Accounts for Zero-length S, the double check is needed because
  829. Size can be maxint and will get <0 when adding index }
  830. if (Size>Length(S)) or
  831. (Index+Size>Length(S)) then
  832. Size:=Length(S)-Index;
  833. If Size>0 then
  834. begin
  835. If Index<0 Then
  836. Index:=0;
  837. ResultAddress:=Pointer(NewWideString (Size));
  838. if ResultAddress<>Nil then
  839. begin
  840. Move (PWideChar(S)[Index],ResultAddress^,Size*sizeof(WideChar));
  841. PWideRec(ResultAddress-WideFirstOff)^.Len:=Size*sizeof(WideChar);
  842. PWideChar(ResultAddress+Size*sizeof(WideChar))^:=#0;
  843. end;
  844. end;
  845. fpc_widestr_decr_ref(Pointer(fpc_widestr_copy));
  846. Pointer(fpc_widestr_Copy):=ResultAddress;
  847. end;
  848. Function Pos (Const Substr : WideString; Const Source : WideString) : SizeInt;
  849. var
  850. i,MaxLen : SizeInt;
  851. pc : pwidechar;
  852. begin
  853. Pos:=0;
  854. if Length(SubStr)>0 then
  855. begin
  856. MaxLen:=Length(source)-Length(SubStr);
  857. i:=0;
  858. pc:=@source[1];
  859. while (i<=MaxLen) do
  860. begin
  861. inc(i);
  862. if (SubStr[1]=pc^) and
  863. (CompareWord(Substr[1],pc^,Length(SubStr))=0) then
  864. begin
  865. Pos:=i;
  866. exit;
  867. end;
  868. inc(pc);
  869. end;
  870. end;
  871. end;
  872. { Faster version for a widechar alone }
  873. Function Pos (c : WideChar; Const s : WideString) : SizeInt;
  874. var
  875. i: SizeInt;
  876. pc : pwidechar;
  877. begin
  878. pc:=@s[1];
  879. for i:=1 to length(s) do
  880. begin
  881. if pc^=c then
  882. begin
  883. pos:=i;
  884. exit;
  885. end;
  886. inc(pc);
  887. end;
  888. pos:=0;
  889. end;
  890. Function Pos (c : WideChar; Const s : AnsiString) : SizeInt;
  891. begin
  892. result:=Pos(c,WideString(s));
  893. end;
  894. Function Pos (c : AnsiString; Const s : WideString) : SizeInt;{$ifdef SYSTEMINLINE}inline;{$endif}
  895. begin
  896. result:=Pos(WideString(c),s);
  897. end;
  898. Function Pos (c : ShortString; Const s : WideString) : SizeInt;{$ifdef SYSTEMINLINE}inline;{$endif}
  899. begin
  900. result:=Pos(WideString(c),s);
  901. end;
  902. Function Pos (c : WideString; Const s : AnsiString) : SizeInt;{$ifdef SYSTEMINLINE}inline;{$endif}
  903. begin
  904. result:=Pos(c,WideString(s));
  905. end;
  906. { Faster version for a char alone. Must be implemented because }
  907. { pos(c: char; const s: shortstring) also exists, so otherwise }
  908. { using pos(char,pchar) will always call the shortstring version }
  909. { (exact match for first argument), also with $h+ (JM) }
  910. Function Pos (c : Char; Const s : WideString) : SizeInt;
  911. var
  912. i: SizeInt;
  913. wc : widechar;
  914. pc : pwidechar;
  915. begin
  916. wc:=c;
  917. pc:=@s[1];
  918. for i:=1 to length(s) do
  919. begin
  920. if pc^=wc then
  921. begin
  922. pos:=i;
  923. exit;
  924. end;
  925. inc(pc);
  926. end;
  927. pos:=0;
  928. end;
  929. Procedure Delete (Var S : WideString; Index,Size: SizeInt);
  930. Var
  931. LS : SizeInt;
  932. begin
  933. If Length(S)=0 then
  934. exit;
  935. if index<=0 then
  936. exit;
  937. LS:=PWideRec(Pointer(S)-WideFirstOff)^.Len div sizeof(WideChar);
  938. if (Index<=LS) and (Size>0) then
  939. begin
  940. UniqueString (S);
  941. if Size+Index>LS then
  942. Size:=LS-Index+1;
  943. if Index+Size<=LS then
  944. begin
  945. Dec(Index);
  946. Move(PWideChar(S)[Index+Size],PWideChar(S)[Index],(LS-Index-Size+1)*sizeof(WideChar));
  947. end;
  948. Setlength(s,LS-Size);
  949. end;
  950. end;
  951. Procedure Insert (Const Source : WideString; Var S : WideString; Index : SizeInt);
  952. var
  953. Temp : WideString;
  954. LS : SizeInt;
  955. begin
  956. If Length(Source)=0 then
  957. exit;
  958. if index <= 0 then
  959. index := 1;
  960. Ls:=Length(S);
  961. if index > LS then
  962. index := LS+1;
  963. Dec(Index);
  964. Pointer(Temp) := NewWideString(Length(Source)+LS);
  965. SetLength(Temp,Length(Source)+LS);
  966. If Index>0 then
  967. move (PWideChar(S)^,PWideChar(Temp)^,Index*sizeof(WideChar));
  968. Move (PWideChar(Source)^,PWideChar(Temp)[Index],Length(Source)*sizeof(WideChar));
  969. If (LS-Index)>0 then
  970. Move(PWideChar(S)[Index],PWideChar(temp)[Length(Source)+index],(LS-Index)*sizeof(WideChar));
  971. S:=Temp;
  972. end;
  973. function UpCase(const s : WideString) : WideString;
  974. begin
  975. result:=widestringmanager.UpperWideStringProc(s);
  976. end;
  977. Procedure SetString (Out S : WideString; Buf : PWideChar; Len : SizeInt);
  978. var
  979. BufLen: SizeInt;
  980. begin
  981. SetLength(S,Len);
  982. If (Buf<>Nil) and (Len>0) then
  983. begin
  984. BufLen := IndexWord(Buf^, Len+1, 0);
  985. If (BufLen>0) and (BufLen < Len) then
  986. Len := BufLen;
  987. Move (Buf[0],S[1],Len*sizeof(WideChar));
  988. PWideChar(Pointer(S)+Len*sizeof(WideChar))^:=#0;
  989. end;
  990. end;
  991. Procedure SetString (Out S : WideString; Buf : PChar; Len : SizeInt);
  992. var
  993. BufLen: SizeInt;
  994. begin
  995. SetLength(S,Len);
  996. If (Buf<>Nil) and (Len>0) then
  997. begin
  998. BufLen := IndexByte(Buf^, Len+1, 0);
  999. If (BufLen>0) and (BufLen < Len) then
  1000. Len := BufLen;
  1001. widestringmanager.Ansi2WideMoveProc(Buf,S,Len);
  1002. //PWideChar(Pointer(S)+Len*sizeof(WideChar))^:=#0;
  1003. end;
  1004. end;
  1005. {$ifndef FPUNONE}
  1006. Function fpc_Val_Real_WideStr(Const S : WideString; out Code : ValSInt): ValReal; [public, alias:'FPC_VAL_REAL_WIDESTR']; compilerproc;
  1007. Var
  1008. SS : String;
  1009. begin
  1010. fpc_Val_Real_WideStr := 0;
  1011. if length(S) > 255 then
  1012. code := 256
  1013. else
  1014. begin
  1015. SS := S;
  1016. Val(SS,fpc_Val_Real_WideStr,code);
  1017. end;
  1018. end;
  1019. {$endif}
  1020. function fpc_val_enum_widestr(str2ordindex:pointer;const s:widestring;out code:valsint):longint;compilerproc;
  1021. var ss:shortstring;
  1022. begin
  1023. if length(s)>255 then
  1024. code:=256
  1025. else
  1026. begin
  1027. ss:=s;
  1028. val(ss,fpc_val_enum_widestr,code);
  1029. end;
  1030. end;
  1031. Function fpc_Val_Currency_WideStr(Const S : WideString; out Code : ValSInt): Currency; [public, alias:'FPC_VAL_CURRENCY_WIDESTR']; compilerproc;
  1032. Var
  1033. SS : String;
  1034. begin
  1035. if length(S) > 255 then
  1036. begin
  1037. fpc_Val_Currency_WideStr:=0;
  1038. code := 256;
  1039. end
  1040. else
  1041. begin
  1042. SS := S;
  1043. Val(SS,fpc_Val_Currency_WideStr,code);
  1044. end;
  1045. end;
  1046. Function fpc_Val_UInt_WideStr (Const S : WideString; out Code : ValSInt): ValUInt; [public, alias:'FPC_VAL_UINT_WIDESTR']; compilerproc;
  1047. Var
  1048. SS : ShortString;
  1049. begin
  1050. fpc_Val_UInt_WideStr := 0;
  1051. if length(S) > 255 then
  1052. code := 256
  1053. else
  1054. begin
  1055. SS := S;
  1056. Val(SS,fpc_Val_UInt_WideStr,code);
  1057. end;
  1058. end;
  1059. Function fpc_Val_SInt_WideStr (DestSize: SizeInt; Const S : WideString; out Code : ValSInt): ValSInt; [public, alias:'FPC_VAL_SINT_WIDESTR']; compilerproc;
  1060. Var
  1061. SS : ShortString;
  1062. begin
  1063. fpc_Val_SInt_WideStr:=0;
  1064. if length(S)>255 then
  1065. code:=256
  1066. else
  1067. begin
  1068. SS := S;
  1069. fpc_Val_SInt_WideStr := int_Val_SInt_ShortStr(DestSize,SS,Code);
  1070. end;
  1071. end;
  1072. {$ifndef CPU64}
  1073. Function fpc_Val_qword_WideStr (Const S : WideString; out Code : ValSInt): qword; [public, alias:'FPC_VAL_QWORD_WIDESTR']; compilerproc;
  1074. Var
  1075. SS : ShortString;
  1076. begin
  1077. fpc_Val_qword_WideStr:=0;
  1078. if length(S)>255 then
  1079. code:=256
  1080. else
  1081. begin
  1082. SS := S;
  1083. Val(SS,fpc_Val_qword_WideStr,Code);
  1084. end;
  1085. end;
  1086. Function fpc_Val_int64_WideStr (Const S : WideString; out Code : ValSInt): Int64; [public, alias:'FPC_VAL_INT64_WIDESTR']; compilerproc;
  1087. Var
  1088. SS : ShortString;
  1089. begin
  1090. fpc_Val_int64_WideStr:=0;
  1091. if length(S)>255 then
  1092. code:=256
  1093. else
  1094. begin
  1095. SS := S;
  1096. Val(SS,fpc_Val_int64_WideStr,Code);
  1097. end;
  1098. end;
  1099. {$endif CPU64}
  1100. {$ifndef FPUNONE}
  1101. procedure fpc_WideStr_Float(d : ValReal;len,fr,rt : SizeInt;out s : WideString);compilerproc;
  1102. var
  1103. ss : shortstring;
  1104. begin
  1105. str_real(len,fr,d,treal_type(rt),ss);
  1106. s:=ss;
  1107. end;
  1108. {$endif}
  1109. procedure fpc_widestr_enum(ordinal,len:sizeint;typinfo,ord2strindex:pointer;out s:widestring);compilerproc;
  1110. var ss:shortstring;
  1111. begin
  1112. fpc_shortstr_enum(ordinal,len,typinfo,ord2strindex,ss);
  1113. s:=ss;
  1114. end;
  1115. {$ifdef FPC_HAS_STR_CURRENCY}
  1116. procedure fpc_WideStr_Currency(c : Currency;len,fr : SizeInt;out s : WideString);compilerproc;
  1117. var
  1118. ss : shortstring;
  1119. begin
  1120. str(c:len:fr,ss);
  1121. s:=ss;
  1122. end;
  1123. {$endif FPC_HAS_STR_CURRENCY}
  1124. Procedure fpc_WideStr_SInt(v : ValSint; Len : SizeInt; out S : WideString);compilerproc;
  1125. Var
  1126. SS : ShortString;
  1127. begin
  1128. Str (v:Len,SS);
  1129. S:=SS;
  1130. end;
  1131. Procedure fpc_WideStr_UInt(v : ValUInt;Len : SizeInt; out S : WideString);compilerproc;
  1132. Var
  1133. SS : ShortString;
  1134. begin
  1135. str(v:Len,SS);
  1136. S:=SS;
  1137. end;
  1138. {$ifndef CPU64}
  1139. Procedure fpc_WideStr_Int64(v : Int64; Len : SizeInt; out S : WideString);compilerproc;
  1140. Var
  1141. SS : ShortString;
  1142. begin
  1143. Str (v:Len,SS);
  1144. S:=SS;
  1145. end;
  1146. Procedure fpc_WideStr_Qword(v : Qword;Len : SizeInt; out S : WideString);compilerproc;
  1147. Var
  1148. SS : ShortString;
  1149. begin
  1150. str(v:Len,SS);
  1151. S:=SS;
  1152. end;
  1153. {$endif CPU64}
  1154. function UnicodeToUtf8(Dest: PChar; Source: PWideChar; MaxBytes: SizeInt): SizeInt;{$ifdef SYSTEMINLINE}inline;{$endif}
  1155. begin
  1156. if assigned(Source) then
  1157. Result:=UnicodeToUtf8(Dest,MaxBytes,Source,IndexWord(Source^,-1,0))
  1158. else
  1159. Result:=0;
  1160. end;
  1161. function UnicodeToUtf8(Dest: PChar; MaxDestBytes: SizeUInt; Source: PWideChar; SourceChars: SizeUInt): SizeUInt;
  1162. var
  1163. i,j : SizeUInt;
  1164. w : word;
  1165. begin
  1166. result:=0;
  1167. if source=nil then
  1168. exit;
  1169. i:=0;
  1170. j:=0;
  1171. if assigned(Dest) then
  1172. begin
  1173. while (i<SourceChars) and (j<MaxDestBytes) do
  1174. begin
  1175. w:=word(Source[i]);
  1176. case w of
  1177. 0..$7f:
  1178. begin
  1179. Dest[j]:=char(w);
  1180. inc(j);
  1181. end;
  1182. $80..$7ff:
  1183. begin
  1184. if j+1>=MaxDestBytes then
  1185. break;
  1186. Dest[j]:=char($c0 or (w shr 6));
  1187. Dest[j+1]:=char($80 or (w and $3f));
  1188. inc(j,2);
  1189. end;
  1190. else
  1191. begin
  1192. if j+2>=MaxDestBytes then
  1193. break;
  1194. Dest[j]:=char($e0 or (w shr 12));
  1195. Dest[j+1]:=char($80 or ((w shr 6)and $3f));
  1196. Dest[j+2]:=char($80 or (w and $3f));
  1197. inc(j,3);
  1198. end;
  1199. end;
  1200. inc(i);
  1201. end;
  1202. if j>SizeUInt(MaxDestBytes-1) then
  1203. j:=MaxDestBytes-1;
  1204. Dest[j]:=#0;
  1205. end
  1206. else
  1207. begin
  1208. while i<SourceChars do
  1209. begin
  1210. case word(Source[i]) of
  1211. $0..$7f:
  1212. inc(j);
  1213. $80..$7ff:
  1214. inc(j,2);
  1215. else
  1216. inc(j,3);
  1217. end;
  1218. inc(i);
  1219. end;
  1220. end;
  1221. result:=j+1;
  1222. end;
  1223. function Utf8ToUnicode(Dest: PWideChar; Source: PChar; MaxChars: SizeInt): SizeInt;{$ifdef SYSTEMINLINE}inline;{$endif}
  1224. begin
  1225. if assigned(Source) then
  1226. Result:=Utf8ToUnicode(Dest,MaxChars,Source,strlen(Source))
  1227. else
  1228. Result:=0;
  1229. end;
  1230. function Utf8ToUnicode(Dest: PWideChar; MaxDestChars: SizeUInt; Source: PChar; SourceBytes: SizeUInt): SizeUInt;
  1231. var
  1232. i,j : SizeUInt;
  1233. w: SizeUInt;
  1234. b : byte;
  1235. begin
  1236. if not assigned(Source) then
  1237. begin
  1238. result:=0;
  1239. exit;
  1240. end;
  1241. result:=SizeUInt(-1);
  1242. i:=0;
  1243. j:=0;
  1244. if assigned(Dest) then
  1245. begin
  1246. while (j<MaxDestChars) and (i<SourceBytes) do
  1247. begin
  1248. b:=byte(Source[i]);
  1249. w:=b;
  1250. inc(i);
  1251. // 2 or 3 bytes?
  1252. if b>=$80 then
  1253. begin
  1254. w:=b and $3f;
  1255. if i>=SourceBytes then
  1256. exit;
  1257. // 3 bytes?
  1258. if (b and $20)<>0 then
  1259. begin
  1260. b:=byte(Source[i]);
  1261. inc(i);
  1262. if i>=SourceBytes then
  1263. exit;
  1264. if (b and $c0)<>$80 then
  1265. exit;
  1266. w:=(w shl 6) or (b and $3f);
  1267. end;
  1268. b:=byte(Source[i]);
  1269. w:=(w shl 6) or (b and $3f);
  1270. if (b and $c0)<>$80 then
  1271. exit;
  1272. inc(i);
  1273. end;
  1274. Dest[j]:=WideChar(w);
  1275. inc(j);
  1276. end;
  1277. if j>=MaxDestChars then j:=MaxDestChars-1;
  1278. Dest[j]:=#0;
  1279. end
  1280. else
  1281. begin
  1282. while i<SourceBytes do
  1283. begin
  1284. b:=byte(Source[i]);
  1285. inc(i);
  1286. // 2 or 3 bytes?
  1287. if b>=$80 then
  1288. begin
  1289. if i>=SourceBytes then
  1290. exit;
  1291. // 3 bytes?
  1292. b := b and $3f;
  1293. if (b and $20)<>0 then
  1294. begin
  1295. b:=byte(Source[i]);
  1296. inc(i);
  1297. if i>=SourceBytes then
  1298. exit;
  1299. if (b and $c0)<>$80 then
  1300. exit;
  1301. end;
  1302. if (byte(Source[i]) and $c0)<>$80 then
  1303. exit;
  1304. inc(i);
  1305. end;
  1306. inc(j);
  1307. end;
  1308. end;
  1309. result:=j+1;
  1310. end;
  1311. function UTF8Encode(const s : WideString) : UTF8String;
  1312. var
  1313. i : SizeInt;
  1314. hs : UTF8String;
  1315. begin
  1316. result:='';
  1317. if s='' then
  1318. exit;
  1319. SetLength(hs,length(s)*3);
  1320. i:=UnicodeToUtf8(pchar(hs),length(hs)+1,PWideChar(s),length(s));
  1321. if i>0 then
  1322. begin
  1323. SetLength(hs,i-1);
  1324. result:=hs;
  1325. end;
  1326. end;
  1327. { converts an utf-16 code point or surrogate pair to utf-32 }
  1328. function utf16toutf32(const S: WideString; const index: SizeInt; out len: longint): UCS4Char; [public, alias: 'FPC_WIDETOUTF32'];
  1329. var
  1330. w: widechar;
  1331. begin
  1332. { UTF-16 points in the range #$0-#$D7FF and #$E000-#$FFFF }
  1333. { are the same in UTF-32 }
  1334. w:=s[index];
  1335. if (w<=#$d7ff) or
  1336. (w>=#$e000) then
  1337. begin
  1338. result:=UCS4Char(w);
  1339. len:=1;
  1340. end
  1341. { valid surrogate pair? }
  1342. else if (w<=#$dbff) and
  1343. { w>=#$d7ff check not needed, checked above }
  1344. (index<length(s)) and
  1345. (s[index+1]>=#$dc00) and
  1346. (s[index+1]<=#$dfff) then
  1347. { convert the surrogate pair to UTF-32 }
  1348. begin
  1349. result:=(UCS4Char(w)-$d800) shl 10 + (UCS4Char(s[index+1])-$dc00) + $10000;
  1350. len:=2;
  1351. end
  1352. else
  1353. { invalid surrogate -> do nothing }
  1354. begin
  1355. result:=UCS4Char(w);
  1356. len:=1;
  1357. end;
  1358. end;
  1359. function WideStringToUCS4String(const s : WideString) : UCS4String;
  1360. var
  1361. i, slen,
  1362. destindex : SizeInt;
  1363. len : longint;
  1364. begin
  1365. slen:=length(s);
  1366. setlength(result,slen+1);
  1367. i:=1;
  1368. destindex:=0;
  1369. while (i<=slen) do
  1370. begin
  1371. result[destindex]:=utf16toutf32(s,i,len);
  1372. inc(destindex);
  1373. inc(i,len);
  1374. end;
  1375. { destindex <= slen (surrogate pairs may have been merged) }
  1376. { destindex+1 for terminating #0 (dynamic arrays are }
  1377. { implicitely filled with zero) }
  1378. setlength(result,destindex+1);
  1379. end;
  1380. { concatenates an utf-32 char to a widestring. S *must* be unique when entering. }
  1381. procedure ConcatUTF32ToWideStr(const nc: UCS4Char; var S: WideString; var index: SizeInt);
  1382. var
  1383. p : PWideChar;
  1384. begin
  1385. { if nc > $ffff, we need two places }
  1386. if (index+ord(nc > $ffff)>length(s)) then
  1387. if (length(s) < 10*256) then
  1388. setlength(s,length(s)+10)
  1389. else
  1390. setlength(s,length(s)+length(s) shr 8);
  1391. { we know that s is unique -> avoid uniquestring calls}
  1392. p:=@s[index];
  1393. if (nc<$ffff) then
  1394. begin
  1395. p^:=widechar(nc);
  1396. inc(index);
  1397. end
  1398. else if (dword(nc)<=$10ffff) then
  1399. begin
  1400. p^:=widechar((nc - $10000) shr 10 + $d800);
  1401. (p+1)^:=widechar((nc - $10000) and $3ff + $dc00);
  1402. inc(index,2);
  1403. end
  1404. else
  1405. { invalid code point }
  1406. begin
  1407. p^:='?';
  1408. inc(index);
  1409. end;
  1410. end;
  1411. function UCS4StringToWideString(const s : UCS4String) : WideString;
  1412. var
  1413. i : SizeInt;
  1414. resindex : SizeInt;
  1415. begin
  1416. { skip terminating #0 }
  1417. SetLength(result,length(s)-1);
  1418. resindex:=1;
  1419. for i:=0 to high(s)-1 do
  1420. ConcatUTF32ToWideStr(s[i],result,resindex);
  1421. { adjust result length (may be too big due to growing }
  1422. { for surrogate pairs) }
  1423. setlength(result,resindex-1);
  1424. end;
  1425. const
  1426. SNoWidestrings = 'This binary has no widestrings support compiled in.';
  1427. SRecompileWithWidestrings = 'Recompile the application with a widestrings-manager in the program uses clause.';
  1428. procedure unimplementedwidestring;
  1429. begin
  1430. {$ifdef FPC_HAS_FEATURE_CONSOLEIO}
  1431. If IsConsole then
  1432. begin
  1433. Writeln(StdErr,SNoWidestrings);
  1434. Writeln(StdErr,SRecompileWithWidestrings);
  1435. end;
  1436. {$endif FPC_HAS_FEATURE_CONSOLEIO}
  1437. HandleErrorFrame(233,get_frame);
  1438. end;
  1439. {$warnings off}
  1440. function GenericWideCase(const s : WideString) : WideString;
  1441. begin
  1442. unimplementedwidestring;
  1443. end;
  1444. function CompareWideString(const s1, s2 : WideString) : PtrInt;
  1445. begin
  1446. unimplementedwidestring;
  1447. end;
  1448. function CompareTextWideString(const s1, s2 : WideString): PtrInt;
  1449. begin
  1450. unimplementedwidestring;
  1451. end;
  1452. {$warnings on}
  1453. procedure initwidestringmanager;
  1454. begin
  1455. fillchar(widestringmanager,sizeof(widestringmanager),0);
  1456. {$ifndef HAS_WIDESTRINGMANAGER}
  1457. widestringmanager.Wide2AnsiMoveProc:=@defaultWide2AnsiMove;
  1458. widestringmanager.Ansi2WideMoveProc:=@defaultAnsi2WideMove;
  1459. widestringmanager.UpperWideStringProc:=@GenericWideCase;
  1460. widestringmanager.LowerWideStringProc:=@GenericWideCase;
  1461. {$endif HAS_WIDESTRINGMANAGER}
  1462. widestringmanager.CompareWideStringProc:=@CompareWideString;
  1463. widestringmanager.CompareTextWideStringProc:=@CompareTextWideString;
  1464. widestringmanager.CharLengthPCharProc:=@CharLengthPChar;
  1465. end;