ustrings.inc 48 KB

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