wstrings.inc 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531
  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/Unicode 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. {$ifdef FPC_WINLIKEWIDESTRING}
  31. Len : DWord;
  32. {$else FPC_WINLIKEWIDESTRING}
  33. Ref : SizeInt;
  34. Len : SizeInt;
  35. {$endif FPC_WINLIKEWIDESTRING}
  36. First : WideChar;
  37. end;
  38. Const
  39. WideRecLen = SizeOf(TWideRec);
  40. WideFirstOff = SizeOf(TWideRec)-sizeof(WideChar);
  41. {
  42. Default WideChar <-> Char conversion is to only convert the
  43. lower 127 chars, all others are translated to spaces.
  44. These routines can be overwritten for the Current Locale
  45. }
  46. procedure DefaultWide2AnsiMove(source:pwidechar;var dest:ansistring;len:SizeInt);
  47. var
  48. i : SizeInt;
  49. begin
  50. setlength(dest,len);
  51. for i:=1 to len do
  52. begin
  53. if word(source^)<256 then
  54. dest[i]:=char(word(source^))
  55. else
  56. dest[i]:='?';
  57. inc(source);
  58. end;
  59. end;
  60. procedure DefaultAnsi2WideMove(source:pchar;var dest:widestring;len:SizeInt);
  61. var
  62. i : SizeInt;
  63. begin
  64. setlength(dest,len);
  65. for i:=1 to len do
  66. begin
  67. dest[i]:=widechar(byte(source^));
  68. inc(source);
  69. end;
  70. end;
  71. Procedure GetWideStringManager (Var Manager : TWideStringManager);
  72. begin
  73. manager:=widestringmanager;
  74. end;
  75. Procedure SetWideStringManager (Const New : TWideStringManager; Var Old: TWideStringManager);
  76. begin
  77. Old:=widestringmanager;
  78. widestringmanager:=New;
  79. end;
  80. Procedure SetWideStringManager (Const New : TWideStringManager);
  81. begin
  82. widestringmanager:=New;
  83. end;
  84. (*
  85. Procedure UniqueWideString(Var S : WideString); [Public,Alias : 'FPC_WIDESTR_UNIQUE'];
  86. {
  87. Make sure reference count of S is 1,
  88. using copy-on-write semantics.
  89. }
  90. begin
  91. end;
  92. *)
  93. {****************************************************************************
  94. Internal functions, not in interface.
  95. ****************************************************************************}
  96. procedure WideStringError;
  97. begin
  98. HandleErrorFrame(204,get_frame);
  99. end;
  100. {$ifdef WideStrDebug}
  101. Procedure DumpWideRec(S : Pointer);
  102. begin
  103. If S=Nil then
  104. Writeln ('String is nil')
  105. Else
  106. Begin
  107. With PWideRec(S-WideFirstOff)^ do
  108. begin
  109. Write ('(Len:',len);
  110. Writeln (' Ref: ',ref,')');
  111. end;
  112. end;
  113. end;
  114. {$endif}
  115. Function NewWideString(Len : SizeInt) : Pointer;
  116. {
  117. Allocate a new WideString on the heap.
  118. initialize it to zero length and reference count 1.
  119. }
  120. Var
  121. P : Pointer;
  122. begin
  123. {$ifdef MSWINDOWS}
  124. if winwidestringalloc then
  125. P:=SysAllocStringLen(nil,Len)
  126. else
  127. {$endif MSWINDOWS}
  128. begin
  129. GetMem(P,Len*sizeof(WideChar)+WideRecLen);
  130. If P<>Nil then
  131. begin
  132. PWideRec(P)^.Len:=Len*2; { Initial length }
  133. {$ifndef FPC_WINLIKEWIDESTRING}
  134. PWideRec(P)^.Ref:=1; { Initial Refcount }
  135. {$endif FPC_WINLIKEWIDESTRING}
  136. PWideRec(P)^.First:=#0; { Terminating #0 }
  137. inc(p,WideFirstOff); { Points to string now }
  138. end
  139. else
  140. WideStringError;
  141. end;
  142. NewWideString:=P;
  143. end;
  144. Procedure DisposeWideString(Var S : Pointer);
  145. {
  146. Deallocates a WideString From the heap.
  147. }
  148. begin
  149. If S=Nil then
  150. exit;
  151. {$ifndef MSWINDOWS}
  152. Dec (S,WideFirstOff);
  153. Freemem(S);
  154. {$else MSWINDOWS}
  155. if winwidestringalloc then
  156. SysFreeString(S)
  157. else
  158. begin
  159. Dec (S,WideFirstOff);
  160. Freemem(S);
  161. end;
  162. {$endif MSWINDOWS}
  163. S:=Nil;
  164. end;
  165. Procedure fpc_WideStr_Decr_Ref (Var S : Pointer);[Public,Alias:'FPC_WIDESTR_DECR_REF']; compilerproc;
  166. {
  167. Decreases the ReferenceCount of a non constant widestring;
  168. If the reference count is zero, deallocate the string;
  169. }
  170. Type
  171. pSizeInt = ^SizeInt;
  172. {$ifndef FPC_WINLIKEWIDESTRING}
  173. Var
  174. l : pSizeInt;
  175. {$endif FPC_WINLIKEWIDESTRING}
  176. Begin
  177. { Zero string }
  178. if S=Nil then
  179. exit;
  180. {$ifndef FPC_WINLIKEWIDESTRING}
  181. { check for constant strings ...}
  182. l:=@PWideRec(S-WideFirstOff)^.Ref;
  183. if l^<0 then
  184. exit;
  185. { declocked does a MT safe dec and returns true, if the counter is 0 }
  186. if declocked(l^) then
  187. { Ref count dropped to zero ...
  188. ... remove }
  189. {$endif FPC_WINLIKEWIDESTRING}
  190. DisposeWideString(S);
  191. end;
  192. { alias for internal use }
  193. Procedure fpc_WideStr_Decr_Ref (Var S : Pointer);[external name 'FPC_WIDESTR_DECR_REF'];
  194. Procedure fpc_WideStr_Incr_Ref(Var S : Pointer);[Public,Alias:'FPC_WIDESTR_INCR_REF']; compilerproc;
  195. {$ifdef FPC_WINLIKEWIDESTRING}
  196. var
  197. p : pointer;
  198. {$endif FPC_WINLIKEWIDESTRING}
  199. Begin
  200. If S=Nil then
  201. exit;
  202. {$ifdef FPC_WINLIKEWIDESTRING}
  203. p:=NewWidestring(length(WideString(S)));
  204. move(s^,p^,length(WideString(s))*sizeof(widechar));
  205. s:=p;
  206. {$else FPC_WINLIKEWIDESTRING}
  207. { Let's be paranoid : Constant string ??}
  208. If PWideRec(S-WideFirstOff)^.Ref<0 then exit;
  209. inclocked(PWideRec(S-WideFirstOff)^.Ref);
  210. {$endif FPC_WINLIKEWIDESTRING}
  211. end;
  212. { alias for internal use }
  213. Procedure fpc_WideStr_Incr_Ref (Var S : Pointer);[external name 'FPC_WIDESTR_INCR_REF'];
  214. function fpc_WideStr_To_ShortStr (high_of_res: SizeInt;const S2 : WideString): shortstring;[Public, alias: 'FPC_WIDESTR_TO_SHORTSTR']; compilerproc;
  215. {
  216. Converts a WideString to a ShortString;
  217. }
  218. Var
  219. Size : SizeInt;
  220. temp : ansistring;
  221. begin
  222. result:='';
  223. Size:=Length(S2);
  224. if Size>0 then
  225. begin
  226. If Size>high_of_res then
  227. Size:=high_of_res;
  228. widestringmanager.Wide2AnsiMoveProc(PWideChar(S2),temp,Size);
  229. result:=temp;
  230. end;
  231. end;
  232. Function fpc_ShortStr_To_WideStr (Const S2 : ShortString): WideString;compilerproc;
  233. {
  234. Converts a ShortString to a WideString;
  235. }
  236. Var
  237. Size : SizeInt;
  238. begin
  239. result:='';
  240. Size:=Length(S2);
  241. if Size>0 then
  242. begin
  243. widestringmanager.Ansi2WideMoveProc(PChar(@S2[1]),result,Size);
  244. { Terminating Zero }
  245. PWideChar(Pointer(fpc_ShortStr_To_WideStr)+Size*sizeof(WideChar))^:=#0;
  246. end;
  247. end;
  248. Function fpc_WideStr_To_AnsiStr (const S2 : WideString): AnsiString; compilerproc;
  249. {
  250. Converts a WideString to an AnsiString
  251. }
  252. Var
  253. Size : SizeInt;
  254. begin
  255. result:='';
  256. Size:=Length(S2);
  257. if Size>0 then
  258. widestringmanager.Wide2AnsiMoveProc(PWideChar(Pointer(S2)),result,Size);
  259. end;
  260. Function fpc_AnsiStr_To_WideStr (Const S2 : AnsiString): WideString; compilerproc;
  261. {
  262. Converts an AnsiString to a WideString;
  263. }
  264. Var
  265. Size : SizeInt;
  266. begin
  267. result:='';
  268. Size:=Length(S2);
  269. if Size>0 then
  270. widestringmanager.Ansi2WideMoveProc(PChar(S2),result,Size);
  271. end;
  272. Function fpc_PWideChar_To_AnsiStr(const p : pwidechar): ansistring; compilerproc;
  273. var
  274. Size : SizeInt;
  275. begin
  276. result:='';
  277. if p=nil then
  278. exit;
  279. Size := IndexWord(p^, -1, 0);
  280. if Size>0 then
  281. widestringmanager.Wide2AnsiMoveProc(P,result,Size);
  282. end;
  283. Function fpc_PWideChar_To_WideStr(const p : pwidechar): widestring; compilerproc;
  284. var
  285. Size : SizeInt;
  286. begin
  287. result:='';
  288. if p=nil then
  289. exit;
  290. Size := IndexWord(p^, -1, 0);
  291. Setlength(result,Size);
  292. if Size>0 then
  293. begin
  294. Move(p^,PWideChar(Pointer(result))^,Size*sizeof(WideChar));
  295. { Terminating Zero }
  296. PWideChar(Pointer(result)+Size*sizeof(WideChar))^:=#0;
  297. end;
  298. end;
  299. Function fpc_PWideChar_To_ShortStr(const p : pwidechar): shortstring; compilerproc;
  300. var
  301. Size : SizeInt;
  302. temp: ansistring;
  303. begin
  304. result:='';
  305. if p=nil then
  306. exit;
  307. Size := IndexWord(p^, $7fffffff, 0);
  308. if Size>0 then
  309. begin
  310. widestringmanager.Wide2AnsiMoveProc(p,temp,Size);
  311. result:=temp;
  312. end;
  313. end;
  314. { checked against the ansistring routine, 2001-05-27 (FK) }
  315. Procedure fpc_WideStr_Assign (Var S1 : Pointer;S2 : Pointer);[Public,Alias:'FPC_WIDESTR_ASSIGN']; compilerproc;
  316. {
  317. Assigns S2 to S1 (S1:=S2), taking in account reference counts.
  318. }
  319. begin
  320. {$ifdef FPC_WINLIKEWIDESTRING}
  321. { Decrease the reference count on the old S1 }
  322. fpc_widestr_decr_ref (S1);
  323. if S2<>nil then
  324. begin
  325. S1:=NewWidestring(length(WideString(S2)));
  326. move(s2^,s1^,length(WideString(s1))*sizeof(widechar));
  327. end
  328. else
  329. S1:=nil;
  330. {$else FPC_WINLIKEWIDESTRING}
  331. If S2<>nil then
  332. If PWideRec(S2-WideFirstOff)^.Ref>0 then
  333. inclocked(PWideRec(S2-WideFirstOff)^.ref);
  334. { Decrease the reference count on the old S1 }
  335. fpc_widestr_decr_ref (S1);
  336. s1:=s2;
  337. {$endif FPC_WINLIKEWIDESTRING}
  338. end;
  339. { alias for internal use }
  340. Procedure fpc_WideStr_Assign (Var S1 : Pointer;S2 : Pointer);[external name 'FPC_WIDESTR_ASSIGN'];
  341. {$ifndef STR_CONCAT_PROCS}
  342. function fpc_WideStr_Concat (const S1,S2 : WideString): WideString; compilerproc;
  343. Var
  344. Size,Location : SizeInt;
  345. pc : pwidechar;
  346. begin
  347. { only assign if s1 or s2 is empty }
  348. if (S1='') then
  349. begin
  350. result:=s2;
  351. exit;
  352. end;
  353. if (S2='') then
  354. begin
  355. result:=s1;
  356. exit;
  357. end;
  358. Location:=Length(S1);
  359. Size:=length(S2);
  360. SetLength(result,Size+Location);
  361. pc:=pwidechar(result);
  362. Move(S1[1],pc^,Location*sizeof(WideChar));
  363. inc(pc,location);
  364. Move(S2[1],pc^,(Size+1)*sizeof(WideChar));
  365. end;
  366. function fpc_WideStr_Concat_multi (const sarr:array of Widestring): widestring; compilerproc;
  367. Var
  368. i : Longint;
  369. p : pointer;
  370. pc : pwidechar;
  371. Size,NewSize : SizeInt;
  372. begin
  373. { First calculate size of the result so we can do
  374. a single call to SetLength() }
  375. NewSize:=0;
  376. for i:=low(sarr) to high(sarr) do
  377. inc(Newsize,length(sarr[i]));
  378. SetLength(result,NewSize);
  379. pc:=pwidechar(result);
  380. for i:=low(sarr) to high(sarr) do
  381. begin
  382. p:=pointer(sarr[i]);
  383. if assigned(p) then
  384. begin
  385. Size:=length(widestring(p));
  386. Move(pwidechar(p)^,pc^,(Size+1)*sizeof(WideChar));
  387. inc(pc,size);
  388. end;
  389. end;
  390. end;
  391. {$else STR_CONCAT_PROCS}
  392. procedure fpc_WideStr_Concat (var DestS:Widestring;const S1,S2 : WideString); compilerproc;
  393. Var
  394. Size,Location : SizeInt;
  395. begin
  396. { only assign if s1 or s2 is empty }
  397. if (S1='') then
  398. begin
  399. DestS:=s2;
  400. exit;
  401. end;
  402. if (S2='') then
  403. begin
  404. DestS:=s1;
  405. exit;
  406. end;
  407. Location:=Length(S1);
  408. Size:=length(S2);
  409. { Use Pointer() typecasts to prevent extra conversion code }
  410. if Pointer(DestS)=Pointer(S1) then
  411. begin
  412. SetLength(DestS,Size+Location);
  413. Move(Pointer(S2)^,(Pointer(DestS)+Location*sizeof(WideChar))^,(Size+1)*sizeof(WideChar));
  414. end
  415. else if Pointer(DestS)=Pointer(S2) then
  416. begin
  417. SetLength(DestS,Size+Location);
  418. Move(Pointer(DestS)^,(Pointer(DestS)+Location*sizeof(WideChar))^,(Size+1)*sizeof(WideChar));
  419. Move(Pointer(S1)^,Pointer(DestS)^,Location*sizeof(WideChar));
  420. end
  421. else
  422. begin
  423. DestS:='';
  424. SetLength(DestS,Size+Location);
  425. Move(Pointer(S1)^,Pointer(DestS)^,Location*sizeof(WideChar));
  426. Move(Pointer(S2)^,(Pointer(DestS)+Location*sizeof(WideChar))^,(Size+1)*sizeof(WideChar));
  427. end;
  428. end;
  429. procedure fpc_WideStr_Concat_multi (var DestS:Widestring;const sarr:array of Widestring); compilerproc;
  430. Var
  431. lowstart,i : Longint;
  432. p,pc : pointer;
  433. Size,NewLen,
  434. OldDestLen : SizeInt;
  435. begin
  436. if high(sarr)=0 then
  437. begin
  438. DestS:='';
  439. exit;
  440. end;
  441. lowstart:=low(sarr);
  442. if Pointer(DestS)=Pointer(sarr[lowstart]) then
  443. begin
  444. inc(lowstart);
  445. { Check for another reuse, then we can't use
  446. the append optimization }
  447. for i:=lowstart to high(sarr) do
  448. begin
  449. if Pointer(DestS)=Pointer(sarr[i]) then
  450. begin
  451. lowstart:=low(sarr);
  452. break;
  453. end;
  454. end;
  455. end;
  456. { Start with empty DestS if we start with concatting
  457. the first array element }
  458. if lowstart=low(sarr) then
  459. DestS:='';
  460. OldDestLen:=length(DestS);
  461. { Calculate size of the result so we can do
  462. a single call to SetLength() }
  463. NewLen:=0;
  464. for i:=low(sarr) to high(sarr) do
  465. inc(NewLen,length(sarr[i]));
  466. SetLength(DestS,NewLen);
  467. { Concat all strings, except the string we already
  468. copied in DestS }
  469. pc:=Pointer(DestS)+OldDestLen*sizeof(WideChar);
  470. for i:=lowstart to high(sarr) do
  471. begin
  472. p:=pointer(sarr[i]);
  473. if assigned(p) then
  474. begin
  475. Size:=length(widestring(p));
  476. Move(p^,pc^,(Size+1)*sizeof(WideChar));
  477. inc(pc,size*sizeof(WideChar));
  478. end;
  479. end;
  480. end;
  481. {$endif STR_CONCAT_PROCS}
  482. Function fpc_Char_To_WideStr(const c : WideChar): WideString; compilerproc;
  483. {
  484. Converts a Char to a WideString;
  485. }
  486. begin
  487. if c = #0 then
  488. { result is automatically set to '' }
  489. exit;
  490. Setlength(fpc_Char_To_WideStr,1);
  491. fpc_Char_To_WideStr[1]:=c;
  492. { Terminating Zero }
  493. PWideChar(Pointer(fpc_Char_To_WideStr)+sizeof(WideChar))^:=#0;
  494. end;
  495. Function fpc_PChar_To_WideStr(const p : pchar): WideString; compilerproc;
  496. Var
  497. L : SizeInt;
  498. begin
  499. if (not assigned(p)) or (p[0]=#0) Then
  500. { result is automatically set to '' }
  501. exit;
  502. l:=IndexChar(p^,-1,#0);
  503. widestringmanager.Ansi2WideMoveProc(P,fpc_PChar_To_WideStr,l);
  504. end;
  505. Function fpc_CharArray_To_WideStr(const arr: array of char; zerobased: boolean = true): WideString; compilerproc;
  506. var
  507. i : SizeInt;
  508. begin
  509. if (zerobased) then
  510. begin
  511. if (arr[0]=#0) Then
  512. { result is automatically set to '' }
  513. exit;
  514. i:=IndexChar(arr,high(arr)+1,#0);
  515. if i = -1 then
  516. i := high(arr)+1;
  517. end
  518. else
  519. i := high(arr)+1;
  520. SetLength(fpc_CharArray_To_WideStr,i);
  521. widestringmanager.Ansi2WideMoveProc (pchar(@arr),fpc_CharArray_To_WideStr,i);
  522. end;
  523. function fpc_WideCharArray_To_ShortStr(const arr: array of widechar; zerobased: boolean = true): shortstring;[public,alias:'FPC_WIDECHARARRAY_TO_SHORTSTR']; compilerproc;
  524. var
  525. l: longint;
  526. index: longint;
  527. len: byte;
  528. temp: ansistring;
  529. begin
  530. l := high(arr)+1;
  531. if l>=256 then
  532. l:=255
  533. else if l<0 then
  534. l:=0;
  535. if zerobased then
  536. begin
  537. index:=IndexWord(arr[0],l,0);
  538. if (index < 0) then
  539. len := l
  540. else
  541. len := index;
  542. end
  543. else
  544. len := l;
  545. widestringmanager.Wide2AnsiMoveProc (pwidechar(@arr),temp,len);
  546. fpc_WideCharArray_To_ShortStr := temp;
  547. end;
  548. Function fpc_WideCharArray_To_AnsiStr(const arr: array of widechar; zerobased: boolean = true): AnsiString; compilerproc;
  549. var
  550. i : SizeInt;
  551. begin
  552. if (zerobased) then
  553. begin
  554. i:=IndexWord(arr,high(arr)+1,0);
  555. if i = -1 then
  556. i := high(arr)+1;
  557. end
  558. else
  559. i := high(arr)+1;
  560. SetLength(fpc_WideCharArray_To_AnsiStr,i);
  561. widestringmanager.Wide2AnsiMoveProc (pwidechar(@arr),fpc_WideCharArray_To_AnsiStr,i);
  562. end;
  563. Function fpc_WideCharArray_To_WideStr(const arr: array of widechar; zerobased: boolean = true): WideString; compilerproc;
  564. var
  565. i : SizeInt;
  566. begin
  567. if (zerobased) then
  568. begin
  569. i:=IndexWord(arr,high(arr)+1,0);
  570. if i = -1 then
  571. i := high(arr)+1;
  572. end
  573. else
  574. i := high(arr)+1;
  575. SetLength(fpc_WideCharArray_To_WideStr,i);
  576. Move(pwidechar(@arr)^, PWideChar(Pointer(@fpc_WideCharArray_To_WideStr[1]))^,i*sizeof(WideChar));
  577. { Terminating Zero }
  578. PWideChar(Pointer(@fpc_WideCharArray_To_WideStr[1])+i*sizeof(WideChar))^:=#0;
  579. end;
  580. { inside the compiler, the resulttype is modified to that of the actual }
  581. { chararray we're converting to (JM) }
  582. function fpc_widestr_to_chararray(arraysize: SizeInt; const src: WideString): fpc_big_chararray;[public,alias: 'FPC_WIDESTR_TO_CHARARRAY']; compilerproc;
  583. var
  584. len: SizeInt;
  585. temp: ansistring;
  586. begin
  587. len := length(src);
  588. { make sure we don't dereference src if it can be nil (JM) }
  589. if len > 0 then
  590. widestringmanager.wide2ansimoveproc(pwidechar(@src[1]),temp,len);
  591. len := length(temp);
  592. if len > arraysize then
  593. len := arraysize;
  594. move(temp[1],fpc_widestr_to_chararray[0],len);
  595. fillchar(fpc_widestr_to_chararray[len],arraysize-len,0);
  596. end;
  597. { inside the compiler, the resulttype is modified to that of the actual }
  598. { widechararray we're converting to (JM) }
  599. function fpc_widestr_to_widechararray(arraysize: SizeInt; const src: WideString): fpc_big_widechararray;[public,alias: 'FPC_WIDESTR_TO_WIDECHARARRAY']; compilerproc;
  600. var
  601. len: SizeInt;
  602. begin
  603. len := length(src);
  604. if len > arraysize then
  605. len := arraysize;
  606. { make sure we don't try to access element 1 of the ansistring if it's nil }
  607. if len > 0 then
  608. move(src[1],fpc_widestr_to_widechararray[0],len*SizeOf(WideChar));
  609. fillchar(fpc_widestr_to_widechararray[len],(arraysize-len)*SizeOf(WideChar),0);
  610. end;
  611. { inside the compiler, the resulttype is modified to that of the actual }
  612. { chararray we're converting to (JM) }
  613. function fpc_ansistr_to_widechararray(arraysize: SizeInt; const src: AnsiString): fpc_big_widechararray;[public,alias: 'FPC_ANSISTR_TO_WIDECHARARRAY']; compilerproc;
  614. var
  615. len: SizeInt;
  616. temp: widestring;
  617. begin
  618. len := length(src);
  619. { make sure we don't dereference src if it can be nil (JM) }
  620. if len > 0 then
  621. widestringmanager.ansi2widemoveproc(pchar(@src[1]),temp,len);
  622. len := length(temp);
  623. if len > arraysize then
  624. len := arraysize;
  625. move(temp[1],fpc_ansistr_to_widechararray[0],len*sizeof(widechar));
  626. fillchar(fpc_ansistr_to_widechararray[len],(arraysize-len)*SizeOf(WideChar),0);
  627. end;
  628. function fpc_shortstr_to_widechararray(arraysize: SizeInt; const src: ShortString): fpc_big_widechararray;[public,alias: 'FPC_SHORTSTR_TO_WIDECHARARRAY']; compilerproc;
  629. var
  630. len: longint;
  631. temp : widestring;
  632. begin
  633. len := length(src);
  634. { make sure we don't access char 1 if length is 0 (JM) }
  635. if len > 0 then
  636. widestringmanager.ansi2widemoveproc(pchar(@src[1]),temp,len);
  637. len := length(temp);
  638. if len > arraysize then
  639. len := arraysize;
  640. move(temp[1],fpc_shortstr_to_widechararray[0],len*sizeof(widechar));
  641. fillchar(fpc_shortstr_to_widechararray[len],(arraysize-len)*SizeOf(WideChar),0);
  642. end;
  643. Function fpc_WideStr_Compare(const S1,S2 : WideString): SizeInt;[Public,Alias : 'FPC_WIDESTR_COMPARE']; compilerproc;
  644. {
  645. Compares 2 WideStrings;
  646. The result is
  647. <0 if S1<S2
  648. 0 if S1=S2
  649. >0 if S1>S2
  650. }
  651. Var
  652. MaxI,Temp : SizeInt;
  653. begin
  654. if pointer(S1)=pointer(S2) then
  655. begin
  656. fpc_WideStr_Compare:=0;
  657. exit;
  658. end;
  659. Maxi:=Length(S1);
  660. temp:=Length(S2);
  661. If MaxI>Temp then
  662. MaxI:=Temp;
  663. Temp:=CompareWord(S1[1],S2[1],MaxI);
  664. if temp=0 then
  665. temp:=Length(S1)-Length(S2);
  666. fpc_WideStr_Compare:=Temp;
  667. end;
  668. Procedure fpc_WideStr_CheckZero(p : pointer);[Public,Alias : 'FPC_WIDESTR_CHECKZERO']; compilerproc;
  669. begin
  670. if p=nil then
  671. HandleErrorFrame(201,get_frame);
  672. end;
  673. Procedure fpc_WideStr_CheckRange(len,index : SizeInt);[Public,Alias : 'FPC_WIDESTR_RANGECHECK']; compilerproc;
  674. begin
  675. if (index>len) or (Index<1) then
  676. HandleErrorFrame(201,get_frame);
  677. end;
  678. Procedure fpc_WideStr_SetLength(Var S : WideString; l : SizeInt);[Public,Alias : 'FPC_WIDESTR_SETLENGTH']; compilerproc;
  679. {
  680. Sets The length of string S to L.
  681. Makes sure S is unique, and contains enough room.
  682. }
  683. Var
  684. Temp : Pointer;
  685. movelen: SizeInt;
  686. begin
  687. if (l>0) then
  688. begin
  689. if Pointer(S)=nil then
  690. begin
  691. { Need a complete new string...}
  692. Pointer(s):=NewWideString(l);
  693. end
  694. { windows doesn't support reallocing widestrings, this code
  695. is anyways subject to be removed because widestrings shouldn't be
  696. ref. counted anymore (FK) }
  697. else
  698. {$ifndef FPC_WINLIKEWIDESTRING}
  699. if
  700. {$ifdef MSWINDOWS}
  701. not winwidestringalloc and
  702. {$endif MSWINDOWS}
  703. (PWideRec(Pointer(S)-WideFirstOff)^.Ref = 1) then
  704. begin
  705. Dec(Pointer(S),WideFirstOff);
  706. if L*sizeof(WideChar)+WideRecLen>MemSize(Pointer(S)) then
  707. reallocmem(pointer(S), L*sizeof(WideChar)+WideRecLen);
  708. Inc(Pointer(S), WideFirstOff);
  709. end
  710. else
  711. {$endif FPC_WINLIKEWIDESTRING}
  712. begin
  713. { Reallocation is needed... }
  714. Temp:=Pointer(NewWideString(L));
  715. if Length(S)>0 then
  716. begin
  717. if l < succ(length(s)) then
  718. movelen := l
  719. { also move terminating null }
  720. else
  721. movelen := succ(length(s));
  722. Move(Pointer(S)^,Temp^,movelen * Sizeof(WideChar));
  723. end;
  724. fpc_widestr_decr_ref(Pointer(S));
  725. Pointer(S):=Temp;
  726. end;
  727. { Force nil termination in case it gets shorter }
  728. PWord(Pointer(S)+l*sizeof(WideChar))^:=0;
  729. {$ifndef FPC_WINLIKEWIDESTRING}
  730. PWideRec(Pointer(S)-WideFirstOff)^.Len:=l*sizeof(WideChar);
  731. {$endif FPC_WINLIKEWIDESTRING}
  732. end
  733. else
  734. begin
  735. { Length=0 }
  736. if Pointer(S)<>nil then
  737. fpc_widestr_decr_ref (Pointer(S));
  738. Pointer(S):=Nil;
  739. end;
  740. end;
  741. {*****************************************************************************
  742. Public functions, In interface.
  743. *****************************************************************************}
  744. function WideCharToString(S : PWideChar) : AnsiString;
  745. begin
  746. result:=WideCharLenToString(s,Length(WideString(s)));
  747. end;
  748. function StringToWideChar(const Src : AnsiString;Dest : PWideChar;DestSize : SizeInt) : PWideChar;
  749. var
  750. temp:widestring;
  751. begin
  752. widestringmanager.Ansi2WideMoveProc(PChar(Src),temp,Length(Src));
  753. if Length(temp)<DestSize then
  754. move(temp[1],Dest^,Length(temp)*SizeOf(WideChar))
  755. else
  756. move(temp[1],Dest^,(DestSize-1)*SizeOf(WideChar));
  757. Dest[DestSize-1]:=#0;
  758. result:=Dest;
  759. end;
  760. function WideCharLenToString(S : PWideChar;Len : SizeInt) : AnsiString;
  761. begin
  762. //SetLength(result,Len);
  763. widestringmanager.Wide2AnsiMoveproc(S,result,Len);
  764. end;
  765. procedure WideCharLenToStrVar(Src : PWideChar;Len : SizeInt;out Dest : AnsiString);
  766. begin
  767. Dest:=WideCharLenToString(Src,Len);
  768. end;
  769. procedure WideCharToStrVar(S : PWideChar;out Dest : AnsiString);
  770. begin
  771. Dest:=WideCharToString(S);
  772. end;
  773. Function fpc_widestr_Unique(Var S : Pointer): Pointer; [Public,Alias : 'FPC_WIDESTR_UNIQUE']; compilerproc;
  774. {$ifdef FPC_WINLIKEWIDESTRING}
  775. begin
  776. pointer(result) := pointer(s);
  777. end;
  778. {$else FPC_WINLIKEWIDESTRING}
  779. {
  780. Make sure reference count of S is 1,
  781. using copy-on-write semantics.
  782. }
  783. Var
  784. SNew : Pointer;
  785. L : SizeInt;
  786. begin
  787. pointer(result) := pointer(s);
  788. If Pointer(S)=Nil then
  789. exit;
  790. if PWideRec(Pointer(S)-WideFirstOff)^.Ref<>1 then
  791. begin
  792. L:=PWideRec(Pointer(S)-WideFirstOff)^.len div sizeof(WideChar);
  793. SNew:=NewWideString (L);
  794. Move (PWideChar(S)^,SNew^,(L+1)*sizeof(WideChar));
  795. PWideRec(SNew-WideFirstOff)^.len:=L * sizeof(WideChar);
  796. fpc_widestr_decr_ref (Pointer(S)); { Thread safe }
  797. pointer(S):=SNew;
  798. pointer(result):=SNew;
  799. end;
  800. end;
  801. {$endif FPC_WINLIKEWIDESTRING}
  802. Function Fpc_WideStr_Copy (Const S : WideString; Index,Size : SizeInt) : WideString;compilerproc;
  803. var
  804. ResultAddress : Pointer;
  805. begin
  806. ResultAddress:=Nil;
  807. dec(index);
  808. if Index < 0 then
  809. Index := 0;
  810. { Check Size. Accounts for Zero-length S, the double check is needed because
  811. Size can be maxint and will get <0 when adding index }
  812. if (Size>Length(S)) or
  813. (Index+Size>Length(S)) then
  814. Size:=Length(S)-Index;
  815. If Size>0 then
  816. begin
  817. If Index<0 Then
  818. Index:=0;
  819. ResultAddress:=Pointer(NewWideString (Size));
  820. if ResultAddress<>Nil then
  821. begin
  822. Move (PWideChar(S)[Index],ResultAddress^,Size*sizeof(WideChar));
  823. PWideRec(ResultAddress-WideFirstOff)^.Len:=Size*sizeof(WideChar);
  824. PWideChar(ResultAddress+Size*sizeof(WideChar))^:=#0;
  825. end;
  826. end;
  827. Pointer(fpc_widestr_Copy):=ResultAddress;
  828. end;
  829. Function Pos (Const Substr : WideString; Const Source : WideString) : SizeInt;
  830. var
  831. i,MaxLen : SizeInt;
  832. pc : pwidechar;
  833. begin
  834. Pos:=0;
  835. if Length(SubStr)>0 then
  836. begin
  837. MaxLen:=Length(source)-Length(SubStr);
  838. i:=0;
  839. pc:=@source[1];
  840. while (i<=MaxLen) do
  841. begin
  842. inc(i);
  843. if (SubStr[1]=pc^) and
  844. (CompareWord(Substr[1],pc^,Length(SubStr))=0) then
  845. begin
  846. Pos:=i;
  847. exit;
  848. end;
  849. inc(pc);
  850. end;
  851. end;
  852. end;
  853. { Faster version for a widechar alone }
  854. Function Pos (c : WideChar; Const s : WideString) : SizeInt;
  855. var
  856. i: SizeInt;
  857. pc : pwidechar;
  858. begin
  859. pc:=@s[1];
  860. for i:=1 to length(s) do
  861. begin
  862. if pc^=c then
  863. begin
  864. pos:=i;
  865. exit;
  866. end;
  867. inc(pc);
  868. end;
  869. pos:=0;
  870. end;
  871. Function Pos (c : WideChar; Const s : AnsiString) : SizeInt;
  872. var
  873. i: SizeInt;
  874. pc : pchar;
  875. begin
  876. pc:=@s[1];
  877. for i:=1 to length(s) do
  878. begin
  879. if widechar(pc^)=c then
  880. begin
  881. pos:=i;
  882. exit;
  883. end;
  884. inc(pc);
  885. end;
  886. pos:=0;
  887. end;
  888. Function Pos (c : AnsiString; Const s : WideString) : SizeInt;{$ifdef SYSTEMINLINE}inline;{$endif}
  889. begin
  890. result:=Pos(WideString(c),s);
  891. end;
  892. Function Pos (c : ShortString; Const s : WideString) : SizeInt;{$ifdef SYSTEMINLINE}inline;{$endif}
  893. begin
  894. result:=Pos(WideString(c),s);
  895. end;
  896. Function Pos (c : WideString; Const s : AnsiString) : SizeInt;{$ifdef SYSTEMINLINE}inline;{$endif}
  897. begin
  898. result:=Pos(c,WideString(s));
  899. end;
  900. { Faster version for a char alone. Must be implemented because }
  901. { pos(c: char; const s: shortstring) also exists, so otherwise }
  902. { using pos(char,pchar) will always call the shortstring version }
  903. { (exact match for first argument), also with $h+ (JM) }
  904. Function Pos (c : Char; Const s : WideString) : SizeInt;
  905. var
  906. i: SizeInt;
  907. wc : widechar;
  908. pc : pwidechar;
  909. begin
  910. wc:=c;
  911. pc:=@s[1];
  912. for i:=1 to length(s) do
  913. begin
  914. if pc^=wc then
  915. begin
  916. pos:=i;
  917. exit;
  918. end;
  919. inc(pc);
  920. end;
  921. pos:=0;
  922. end;
  923. Procedure Delete (Var S : WideString; Index,Size: SizeInt);
  924. Var
  925. LS : SizeInt;
  926. begin
  927. If Length(S)=0 then
  928. exit;
  929. if index<=0 then
  930. exit;
  931. LS:=PWideRec(Pointer(S)-WideFirstOff)^.Len div sizeof(WideChar);
  932. if (Index<=LS) and (Size>0) then
  933. begin
  934. UniqueString (S);
  935. if Size+Index>LS then
  936. Size:=LS-Index+1;
  937. if Index+Size<=LS then
  938. begin
  939. Dec(Index);
  940. Move(PWideChar(S)[Index+Size],PWideChar(S)[Index],(LS-Index+1)*sizeof(WideChar));
  941. end;
  942. Setlength(s,LS-Size);
  943. end;
  944. end;
  945. Procedure Insert (Const Source : WideString; Var S : WideString; Index : SizeInt);
  946. var
  947. Temp : WideString;
  948. LS : SizeInt;
  949. begin
  950. If Length(Source)=0 then
  951. exit;
  952. if index <= 0 then
  953. index := 1;
  954. Ls:=Length(S);
  955. if index > LS then
  956. index := LS+1;
  957. Dec(Index);
  958. Pointer(Temp) := NewWideString(Length(Source)+LS);
  959. SetLength(Temp,Length(Source)+LS);
  960. If Index>0 then
  961. move (PWideChar(S)^,PWideChar(Temp)^,Index*sizeof(WideChar));
  962. Move (PWideChar(Source)^,PWideChar(Temp)[Index],Length(Source)*sizeof(WideChar));
  963. If (LS-Index)>0 then
  964. Move(PWideChar(S)[Index],PWideChar(temp)[Length(Source)+index],(LS-Index)*sizeof(WideChar));
  965. S:=Temp;
  966. end;
  967. function UpCase(const s : WideString) : WideString;
  968. begin
  969. result:=widestringmanager.UpperWideStringProc(s);
  970. end;
  971. Procedure SetString (Out S : WideString; Buf : PWideChar; Len : SizeInt);
  972. var
  973. BufLen: SizeInt;
  974. begin
  975. SetLength(S,Len);
  976. If (Buf<>Nil) and (Len>0) then
  977. begin
  978. BufLen := IndexWord(Buf^, Len+1, 0);
  979. If (BufLen>0) and (BufLen < Len) then
  980. Len := BufLen;
  981. Move (Buf[0],S[1],Len*sizeof(WideChar));
  982. PWideChar(Pointer(S)+Len*sizeof(WideChar))^:=#0;
  983. end;
  984. end;
  985. Procedure SetString (Out S : WideString; Buf : PChar; Len : SizeInt);
  986. var
  987. BufLen: SizeInt;
  988. begin
  989. SetLength(S,Len);
  990. If (Buf<>Nil) and (Len>0) then
  991. begin
  992. BufLen := IndexByte(Buf^, Len+1, 0);
  993. If (BufLen>0) and (BufLen < Len) then
  994. Len := BufLen;
  995. widestringmanager.Ansi2WideMoveProc(Buf,S,Len);
  996. //PWideChar(Pointer(S)+Len*sizeof(WideChar))^:=#0;
  997. end;
  998. end;
  999. Function fpc_Val_Real_WideStr(Const S : WideString; out Code : ValSInt): ValReal; [public, alias:'FPC_VAL_REAL_WIDESTR']; compilerproc;
  1000. Var
  1001. SS : String;
  1002. begin
  1003. fpc_Val_Real_WideStr := 0;
  1004. if length(S) > 255 then
  1005. code := 256
  1006. else
  1007. begin
  1008. SS := S;
  1009. Val(SS,fpc_Val_Real_WideStr,code);
  1010. end;
  1011. end;
  1012. Function fpc_Val_UInt_WideStr (Const S : WideString; out Code : ValSInt): ValUInt; [public, alias:'FPC_VAL_UINT_WIDESTR']; compilerproc;
  1013. Var
  1014. SS : ShortString;
  1015. begin
  1016. fpc_Val_UInt_WideStr := 0;
  1017. if length(S) > 255 then
  1018. code := 256
  1019. else
  1020. begin
  1021. SS := S;
  1022. Val(SS,fpc_Val_UInt_WideStr,code);
  1023. end;
  1024. end;
  1025. Function fpc_Val_SInt_WideStr (DestSize: SizeInt; Const S : WideString; out Code : ValSInt): ValSInt; [public, alias:'FPC_VAL_SINT_WIDESTR']; compilerproc;
  1026. Var
  1027. SS : ShortString;
  1028. begin
  1029. fpc_Val_SInt_WideStr:=0;
  1030. if length(S)>255 then
  1031. code:=256
  1032. else
  1033. begin
  1034. SS := S;
  1035. fpc_Val_SInt_WideStr := int_Val_SInt_ShortStr(DestSize,SS,Code);
  1036. end;
  1037. end;
  1038. {$ifndef CPU64}
  1039. Function fpc_Val_qword_WideStr (Const S : WideString; out Code : ValSInt): qword; [public, alias:'FPC_VAL_QWORD_WIDESTR']; compilerproc;
  1040. Var
  1041. SS : ShortString;
  1042. begin
  1043. fpc_Val_qword_WideStr:=0;
  1044. if length(S)>255 then
  1045. code:=256
  1046. else
  1047. begin
  1048. SS := S;
  1049. Val(SS,fpc_Val_qword_WideStr,Code);
  1050. end;
  1051. end;
  1052. Function fpc_Val_int64_WideStr (Const S : WideString; out Code : ValSInt): Int64; [public, alias:'FPC_VAL_INT64_WIDESTR']; compilerproc;
  1053. Var
  1054. SS : ShortString;
  1055. begin
  1056. fpc_Val_int64_WideStr:=0;
  1057. if length(S)>255 then
  1058. code:=256
  1059. else
  1060. begin
  1061. SS := S;
  1062. Val(SS,fpc_Val_int64_WideStr,Code);
  1063. end;
  1064. end;
  1065. {$endif CPU64}
  1066. procedure fpc_WideStr_Float(d : ValReal;len,fr,rt : SizeInt;out s : WideString);compilerproc;
  1067. var
  1068. ss : shortstring;
  1069. begin
  1070. str_real(len,fr,d,treal_type(rt),ss);
  1071. s:=ss;
  1072. end;
  1073. Procedure fpc_WideStr_SInt(v : ValSint; Len : SizeInt; out S : WideString);compilerproc;
  1074. Var
  1075. SS : ShortString;
  1076. begin
  1077. Str (v:Len,SS);
  1078. S:=SS;
  1079. end;
  1080. Procedure fpc_WideStr_UInt(v : ValUInt;Len : SizeInt; out S : WideString);compilerproc;
  1081. Var
  1082. SS : ShortString;
  1083. begin
  1084. str(v:Len,SS);
  1085. S:=SS;
  1086. end;
  1087. {$ifndef CPU64}
  1088. Procedure fpc_WideStr_Int64(v : Int64; Len : SizeInt; out S : WideString);compilerproc;
  1089. Var
  1090. SS : ShortString;
  1091. begin
  1092. Str (v:Len,SS);
  1093. S:=SS;
  1094. end;
  1095. Procedure fpc_WideStr_Qword(v : Qword;Len : SizeInt; out S : WideString);compilerproc;
  1096. Var
  1097. SS : ShortString;
  1098. begin
  1099. str(v:Len,SS);
  1100. S:=SS;
  1101. end;
  1102. {$endif CPU64}
  1103. function UnicodeToUtf8(Dest: PChar; Source: PWideChar; MaxBytes: SizeInt): SizeInt;{$ifdef SYSTEMINLINE}inline;{$endif}
  1104. begin
  1105. if assigned(Source) then
  1106. Result:=UnicodeToUtf8(Dest,MaxBytes,Source,IndexWord(Source^,-1,0))
  1107. else
  1108. Result:=0;
  1109. end;
  1110. function UnicodeToUtf8(Dest: PChar; MaxDestBytes: SizeUInt; Source: PWideChar; SourceChars: SizeUInt): SizeUInt;
  1111. var
  1112. i,j : SizeUInt;
  1113. w : word;
  1114. begin
  1115. result:=0;
  1116. if source=nil then
  1117. exit;
  1118. i:=0;
  1119. j:=0;
  1120. if assigned(Dest) then
  1121. begin
  1122. while (i<SourceChars) and (j<MaxDestBytes) do
  1123. begin
  1124. w:=word(Source[i]);
  1125. case w of
  1126. 0..$7f:
  1127. begin
  1128. Dest[j]:=char(w);
  1129. inc(j);
  1130. end;
  1131. $80..$7ff:
  1132. begin
  1133. if j+1>=MaxDestBytes then
  1134. break;
  1135. Dest[j]:=char($c0 or (w shr 6));
  1136. Dest[j+1]:=char($80 or (w and $3f));
  1137. inc(j,2);
  1138. end;
  1139. else
  1140. begin
  1141. if j+2>=MaxDestBytes then
  1142. break;
  1143. Dest[j]:=char($e0 or (w shr 12));
  1144. Dest[j+1]:=char($80 or ((w shr 6)and $3f));
  1145. Dest[j+2]:=char($80 or (w and $3f));
  1146. inc(j,3);
  1147. end;
  1148. end;
  1149. inc(i);
  1150. end;
  1151. if j>MaxDestBytes-1 then
  1152. j:=MaxDestBytes-1;
  1153. Dest[j]:=#0;
  1154. end
  1155. else
  1156. begin
  1157. while i<SourceChars do
  1158. begin
  1159. case word(Source[i]) of
  1160. $0..$7f:
  1161. inc(j);
  1162. $80..$7ff:
  1163. inc(j,2);
  1164. else
  1165. inc(j,3);
  1166. end;
  1167. end;
  1168. end;
  1169. result:=j+1;
  1170. end;
  1171. function Utf8ToUnicode(Dest: PWideChar; Source: PChar; MaxChars: SizeInt): SizeInt;{$ifdef SYSTEMINLINE}inline;{$endif}
  1172. begin
  1173. if assigned(Source) then
  1174. Result:=Utf8ToUnicode(Dest,MaxChars,Source,strlen(Source))
  1175. else
  1176. Result:=0;
  1177. end;
  1178. function Utf8ToUnicode(Dest: PWideChar; MaxDestChars: SizeUInt; Source: PChar; SourceBytes: SizeUInt): SizeUInt;
  1179. var
  1180. i,j : SizeUInt;
  1181. w: SizeUInt;
  1182. b : byte;
  1183. begin
  1184. if not assigned(Source) then
  1185. begin
  1186. result:=0;
  1187. exit;
  1188. end;
  1189. result:=SizeUInt(-1);
  1190. i:=0;
  1191. j:=0;
  1192. if assigned(Dest) then
  1193. begin
  1194. while (j<MaxDestChars) and (i<SourceBytes) do
  1195. begin
  1196. b:=byte(Source[i]);
  1197. w:=b;
  1198. inc(i);
  1199. // 2 or 3 bytes?
  1200. if b>=$80 then
  1201. begin
  1202. w:=b and $3f;
  1203. if i>=SourceBytes then
  1204. exit;
  1205. // 3 bytes?
  1206. if (b and $20)<>0 then
  1207. begin
  1208. b:=byte(Source[i]);
  1209. inc(i);
  1210. if i>=SourceBytes then
  1211. exit;
  1212. if (b and $c0)<>$80 then
  1213. exit;
  1214. w:=(w shl 6) or (b and $3f);
  1215. end;
  1216. b:=byte(Source[i]);
  1217. w:=(w shl 6) or (b and $3f);
  1218. if (b and $c0)<>$80 then
  1219. exit;
  1220. inc(i);
  1221. end;
  1222. Dest[j]:=WideChar(w);
  1223. inc(j);
  1224. end;
  1225. if j>=MaxDestChars then j:=MaxDestChars-1;
  1226. Dest[j]:=#0;
  1227. end
  1228. else
  1229. begin
  1230. while i<SourceBytes do
  1231. begin
  1232. b:=byte(Source[i]);
  1233. inc(i);
  1234. // 2 or 3 bytes?
  1235. if b>=$80 then
  1236. begin
  1237. if i>=SourceBytes then
  1238. exit;
  1239. // 3 bytes?
  1240. b := b and $3f;
  1241. if (b and $20)<>0 then
  1242. begin
  1243. b:=byte(Source[i]);
  1244. inc(i);
  1245. if i>=SourceBytes then
  1246. exit;
  1247. if (b and $c0)<>$80 then
  1248. exit;
  1249. end;
  1250. if (byte(Source[i]) and $c0)<>$80 then
  1251. exit;
  1252. inc(i);
  1253. end;
  1254. inc(j);
  1255. end;
  1256. end;
  1257. result:=j+1;
  1258. end;
  1259. function UTF8Encode(const s : WideString) : UTF8String;
  1260. var
  1261. i : SizeInt;
  1262. hs : UTF8String;
  1263. begin
  1264. result:='';
  1265. if s='' then
  1266. exit;
  1267. SetLength(hs,length(s)*3);
  1268. i:=UnicodeToUtf8(pchar(hs),length(hs)+1,PWideChar(s),length(s));
  1269. if i>0 then
  1270. begin
  1271. SetLength(hs,i-1);
  1272. result:=hs;
  1273. end;
  1274. end;
  1275. function UTF8Decode(const s : UTF8String): WideString;
  1276. var
  1277. i : SizeInt;
  1278. hs : WideString;
  1279. begin
  1280. result:='';
  1281. if s='' then
  1282. exit;
  1283. SetLength(hs,length(s));
  1284. i:=Utf8ToUnicode(PWideChar(hs),length(hs)+1,pchar(s),length(s));
  1285. if i>0 then
  1286. begin
  1287. SetLength(hs,i-1);
  1288. result:=hs;
  1289. end;
  1290. end;
  1291. function AnsiToUtf8(const s : ansistring): UTF8String;{$ifdef SYSTEMINLINE}inline;{$endif}
  1292. begin
  1293. Result:=Utf8Encode(s);
  1294. end;
  1295. function Utf8ToAnsi(const s : UTF8String) : ansistring;{$ifdef SYSTEMINLINE}inline;{$endif}
  1296. begin
  1297. Result:=Utf8Decode(s);
  1298. end;
  1299. function WideStringToUCS4String(const s : WideString) : UCS4String;
  1300. var
  1301. i : SizeInt;
  1302. begin
  1303. setlength(result,length(s)+1);
  1304. for i:=1 to length(s) do
  1305. result[i-1]:=UCS4Char(s[i]);
  1306. result[length(s)]:=UCS4Char(0);
  1307. end;
  1308. function UCS4StringToWideString(const s : UCS4String) : WideString;
  1309. var
  1310. i : SizeInt;
  1311. begin
  1312. setlength(result,length(s)-1);
  1313. for i:=1 to length(s)-1 do
  1314. result[i]:=WideChar(s[i-1]);
  1315. end;
  1316. procedure unimplementedwidestring;
  1317. begin
  1318. HandleErrorFrame(215,get_frame);
  1319. end;
  1320. {$warnings off}
  1321. function GenericWideCase(const s : WideString) : WideString;
  1322. begin
  1323. unimplementedwidestring;
  1324. end;
  1325. function CompareWideString(const s1, s2 : WideString) : PtrInt;
  1326. begin
  1327. unimplementedwidestring;
  1328. end;
  1329. function CompareTextWideString(const s1, s2 : WideString): PtrInt;
  1330. begin
  1331. unimplementedwidestring;
  1332. end;
  1333. function CharLengthPChar(const Str: PChar): PtrInt;
  1334. begin
  1335. unimplementedwidestring;
  1336. end;
  1337. {$warnings on}
  1338. procedure initwidestringmanager;
  1339. begin
  1340. fillchar(widestringmanager,sizeof(widestringmanager),0);
  1341. {$ifndef HAS_WIDESTRINGMANAGER}
  1342. widestringmanager.Wide2AnsiMoveProc:=@defaultWide2AnsiMove;
  1343. widestringmanager.Ansi2WideMoveProc:=@defaultAnsi2WideMove;
  1344. widestringmanager.UpperWideStringProc:=@GenericWideCase;
  1345. widestringmanager.LowerWideStringProc:=@GenericWideCase;
  1346. {$endif HAS_WIDESTRINGMANAGER}
  1347. widestringmanager.CompareWideStringProc:=@CompareWideString;
  1348. widestringmanager.CompareTextWideStringProc:=@CompareTextWideString;
  1349. widestringmanager.CharLengthPCharProc:=@CharLengthPChar;
  1350. end;