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