justrings.inc 34 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246
  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. { unicodestring is a plain java.lang.String }
  14. {$define FPC_UNICODESTRING_TYPE_DEFINED}
  15. { helpers for converting between Windows and Java code page identifiers }
  16. {$i jwin2javacharset.inc}
  17. {$define FPC_HAS_DEFAULT_UNICODE_2_ANSI_MOVE}
  18. procedure DefaultUnicode2AnsiMove(source:punicodechar;var dest:RawByteString;cp : TSystemCodePage;len:SizeInt);
  19. var
  20. localencoder: JNCCharsetEncoder;
  21. inbuf: JNCharBuffer;
  22. outbuf: JNByteBuffer;
  23. begin
  24. localencoder:=widestringmanager.encoder.getForCodePage(cp);
  25. localencoder.reset;
  26. localencoder.onMalformedInput(JNCCodingErrorAction.fREPLACE);
  27. localencoder.onUnmappableCharacter(JNCCodingErrorAction.fREPLACE);
  28. inbuf:=JNCharBuffer.wrap(TJCharArray(source),0,len);
  29. outbuf:=localencoder.encode(inbuf);
  30. setlength(dest,outbuf.limit);
  31. { "The buffer's position will be zero and its limit will *follow* the last
  32. byte written" -> we already have a terminating zero }
  33. outbuf.get(TJByteArray(AnsiStringClass(dest).fdata),0,outbuf.limit);
  34. { already null-terminated because of setlength }
  35. SetCodePage(dest,cp,false);
  36. end;
  37. {$define FPC_HAS_DEFAULT_ANSI_2_UNICODE}
  38. procedure DefaultAnsi2UnicodeMove(source:pchar;cp : TSystemCodePage;var dest:unicodestring;len:SizeInt);
  39. var
  40. localdecoder: JNCCharsetDecoder;
  41. inbuf: JNByteBuffer;
  42. outbuf: JNCharBuffer;
  43. begin
  44. localdecoder:=widestringmanager.decoder.getForCodePage(cp);
  45. localdecoder.reset;
  46. localdecoder.onMalformedInput(JNCCodingErrorAction.fREPLACE);
  47. localdecoder.onUnmappableCharacter(JNCCodingErrorAction.fREPLACE);
  48. inbuf:=JNByteBuffer.wrap(TJByteArray(source),0,len);
  49. outbuf:=localdecoder.decode(inbuf);
  50. dest:=outbuf.toString;
  51. end;
  52. {
  53. This file contains the implementation of the UnicodeString type,
  54. which on the Java platforms is an alias for java.lang.String
  55. }
  56. {$define FPC_HAS_NEW_UNICODESTRING}
  57. Function NewUnicodeString(Len : SizeInt) : JLString;
  58. {
  59. Allocate a new UnicodeString on the heap.
  60. initialize it to zero length and reference count 1.
  61. }
  62. var
  63. data: array of jchar;
  64. begin
  65. setlength(data,len);
  66. result:=JLString.create(data);
  67. end;
  68. { lie, not required }
  69. {$define FPC_HAS_UNICODESTR_DECR_REF}
  70. {$define FPC_HAS_UNICODESTR_INCR_REF}
  71. {$define FPC_HAS_UNICODESTR_TO_SHORTSTR}
  72. procedure fpc_UnicodeStr_To_ShortStr (out res: ShortString;const S2 : UnicodeString); [Public, alias: 'FPC_UNICODESTR_TO_SHORTSTR'];compilerproc;
  73. {
  74. Converts a UnicodeString to a ShortString;
  75. }
  76. Var
  77. Size : SizeInt;
  78. temp : ansistring;
  79. begin
  80. res:='';
  81. Size:=Length(S2);
  82. if Size>0 then
  83. begin
  84. temp:=s2;
  85. res:=temp;
  86. end;
  87. end;
  88. {$define FPC_HAS_SHORTSTR_TO_UNICODESTR}
  89. Function fpc_ShortStr_To_UnicodeStr (Const S2 : ShortString): UnicodeString;compilerproc;
  90. {
  91. Converts a ShortString to a UnicodeString;
  92. }
  93. Var
  94. Size : SizeInt;
  95. begin
  96. result:='';
  97. Size:=Length(S2);
  98. if Size>0 then
  99. widestringmanager.Ansi2UnicodeMoveProc(PChar(ShortstringClass(@S2).fdata),DefaultSystemCodePage,result,Size);
  100. end;
  101. {$define FPC_HAS_UNICODESTR_TO_ANSISTR}
  102. Function fpc_UnicodeStr_To_AnsiStr (const S2 : UnicodeString{$ifdef FPC_HAS_CPSTRING};cp : TSystemCodePage{$endif FPC_HAS_CPSTRING}): AnsiString; compilerproc;
  103. {
  104. Converts a UnicodeString to an AnsiString
  105. }
  106. Var
  107. Size : SizeInt;
  108. begin
  109. cp:=TranslatePlaceholderCP(cp);
  110. { avoid codepage conversion -- why isn't the result rawbytestring? }
  111. pointer(result):=pointer(AnsistringClass.Create(s2,cp));
  112. end;
  113. {$define FPC_HAS_ANSISTR_TO_UNICODESTR}
  114. Function fpc_AnsiStr_To_UnicodeStr (Const S2 : RawByteString): UnicodeString; compilerproc;
  115. {
  116. Converts an AnsiString to a UnicodeString;
  117. }
  118. Var
  119. Size : SizeInt;
  120. begin
  121. if length(s2)=0 then
  122. result:=''
  123. else
  124. result:=AnsistringClass(S2).toString;
  125. end;
  126. {$define FPC_HAS_UNICODESTR_TO_WIDESTR}
  127. Function fpc_UnicodeStr_To_WideStr (const S2 : UnicodeString): WideString; compilerproc;
  128. begin
  129. result:=s2;
  130. end;
  131. {$define FPC_HAS_WIDESTR_TO_UNICODESTR}
  132. Function fpc_WideStr_To_UnicodeStr (Const S2 : WideString): UnicodeString; compilerproc;
  133. begin
  134. result:=s2;
  135. end;
  136. {$define FPC_HAS_PWIDECHAR_TO_UNICODESTR}
  137. Function fpc_PWideChar_To_UnicodeStr(const p : pwidechar): unicodestring; compilerproc;
  138. var
  139. Size : SizeInt;
  140. begin
  141. result:='';
  142. if p=nil then
  143. exit;
  144. size:=0;
  145. while p[size]<>#0 do
  146. inc(size);
  147. Setlength(result,Size);
  148. if Size>0 then
  149. result:=JLString.Create(TJCharArray(p),0,Size);
  150. end;
  151. { lie, not used by compiler }
  152. {$define FPC_HAS_PUNICODECHAR_TO_SHORTSTR}
  153. {$define FPC_HAS_PWIDECHAR_TO_ANSISTR}
  154. Function fpc_PWideChar_To_AnsiStr(const p : pwidechar{$ifdef FPC_HAS_CPSTRING};cp : TSystemCodePage{$endif FPC_HAS_CPSTRING}): ansistring; compilerproc;
  155. begin
  156. result:='';
  157. if (p=nil) or
  158. (p^=#0) then
  159. exit;
  160. cp:=TranslatePlaceholderCP(cp);
  161. pointer(result):=pointer(AnsistringClass.Create(unicodestring(p),cp));
  162. end;
  163. {$define FPC_HAS_PWIDECHAR_TO_SHORTSTR}
  164. procedure fpc_PWideChar_To_ShortStr(out res : shortstring;const p : pwidechar); compilerproc;
  165. begin
  166. res:='';
  167. if (p=nil) or
  168. (p^=#0) then
  169. exit;
  170. res:=unicodestring(p);
  171. end;
  172. { lie, not required for JVM target }
  173. {$define FPC_HAS_UNICODESTR_ASSIGN}
  174. {$define FPC_HAS_UNICODESTR_CONCAT}
  175. procedure fpc_UnicodeStr_Concat (var DestS:Unicodestring;const S1,S2 : UnicodeString); compilerproc;
  176. Var
  177. sb: JLStringBuilder;
  178. begin
  179. { only assign if s1 or s2 is empty }
  180. if (length(S1)=0) then
  181. begin
  182. DestS:=s2;
  183. exit;
  184. end;
  185. if (length(S2)=0) then
  186. begin
  187. DestS:=s1;
  188. exit;
  189. end;
  190. sb:=JLStringBuilder.create(S1);
  191. sb.append(s2);
  192. DestS:=sb.toString;
  193. end;
  194. {$define FPC_HAS_UNICODESTR_CONCAT_MULTI}
  195. procedure fpc_UnicodeStr_Concat_multi (var DestS:Unicodestring;const sarr:array of Unicodestring); compilerproc;
  196. Var
  197. i : Longint;
  198. Size,NewSize : SizeInt;
  199. sb: JLStringBuilder;
  200. begin
  201. { First calculate size of the result so we can allocate a StringBuilder of
  202. the right size }
  203. NewSize:=0;
  204. for i:=low(sarr) to high(sarr) do
  205. inc(Newsize,length(sarr[i]));
  206. sb:=JLStringBuilder.create(NewSize);
  207. for i:=low(sarr) to high(sarr) do
  208. begin
  209. if length(sarr[i])>0 then
  210. sb.append(sarr[i]);
  211. end;
  212. dests:=sb.toString;
  213. end;
  214. {$define FPC_HAS_CHAR_TO_UCHAR}
  215. Function fpc_Char_To_UChar(const c : AnsiChar): UnicodeChar; compilerproc;
  216. var
  217. arr: array[0..0] of ansichar;
  218. w: unicodestring;
  219. begin
  220. arr[0]:=c;
  221. widestringmanager.Ansi2UnicodeMoveProc(pansichar(@arr),DefaultSystemCodePage,w,1);
  222. fpc_Char_To_UChar:=w[1];
  223. end;
  224. {$define FPC_HAS_CHAR_TO_UNICODESTR}
  225. Function fpc_Char_To_UnicodeStr(const c : AnsiChar): UnicodeString; compilerproc;
  226. {
  227. Converts a AnsiChar to a UnicodeString;
  228. }
  229. var
  230. arr: array[0..0] of ansichar;
  231. begin
  232. arr[0]:=c;
  233. widestringmanager.Ansi2UnicodeMoveProc(pansichar(@arr),DefaultSystemCodePage,result,1);
  234. end;
  235. {$define FPC_HAS_UCHAR_TO_CHAR}
  236. Function fpc_UChar_To_Char(const c : UnicodeChar): Char; compilerproc;
  237. {
  238. Converts a UnicodeChar to a Char;
  239. }
  240. var
  241. u: unicodestring;
  242. s: RawByteString;
  243. arr: array[0..0] of unicodechar;
  244. begin
  245. arr[0]:=c;
  246. widestringmanager.Unicode2AnsiMoveProc(punicodechar(@arr), s, DefaultSystemCodePage, 1);
  247. if length(s)=1 then
  248. fpc_UChar_To_Char:= s[1]
  249. else
  250. fpc_UChar_To_Char:='?';
  251. end;
  252. { lie, unused for this target since widechar = unicodechar }
  253. {$define FPC_HAS_UCHAR_TO_UNICODESTR}
  254. Function fpc_UChar_To_UnicodeStr(const c : UnicodeChar): UnicodeString; compilerproc;
  255. {
  256. Converts a UnicodeChar to a UnicodeString;
  257. }
  258. var
  259. arr: array[0..0] of UnicodeChar;
  260. begin
  261. arr[0]:=c;
  262. result:=JLString.create(arr);
  263. end;
  264. {$define FPC_HAS_UCHAR_TO_ANSISTR}
  265. Function fpc_UChar_To_AnsiStr(const c : UnicodeChar{$ifdef FPC_HAS_CPSTRING};cp : TSystemCodePage{$endif FPC_HAS_CPSTRING}): AnsiString; compilerproc;
  266. {
  267. Converts a UnicodeChar to a AnsiString;
  268. }
  269. var
  270. u: unicodestring;
  271. arr: array[0..0] of unicodechar;
  272. begin
  273. arr[0]:=c;
  274. cp:=TranslatePlaceholderCP(cp);
  275. widestringmanager.Unicode2AnsiMoveProc(punicodechar(@arr), RawByteString(fpc_UChar_To_AnsiStr), cp, 1);
  276. end;
  277. {$define FPC_HAS_UCHAR_TO_SHORTSTR}
  278. function fpc_UChar_To_ShortStr(const c : UnicodeChar): shortstring; compilerproc;
  279. {
  280. Converts a UnicodeChar to a AnsiString;
  281. }
  282. var
  283. u: unicodestring;
  284. begin
  285. u:=c;
  286. result:=u;
  287. end;
  288. {$ifndef FPC_HAS_UCHAR_TO_ANSISTR}
  289. {$define FPC_HAS_UCHAR_TO_ANSISTR}
  290. Function fpc_UChar_To_AnsiStr(const c : UnicodeChar{$ifdef FPC_HAS_CPSTRING};cp : TSystemCodePage{$endif FPC_HAS_CPSTRING}): AnsiString; compilerproc;
  291. {
  292. Converts a UnicodeChar to a AnsiString;
  293. }
  294. var
  295. arr: array[0..0] of unicodechar;
  296. {$ifndef FPC_HAS_CPSTRING}
  297. cp : TSystemCodePage;
  298. {$endif FPC_HAS_CPSTRING}
  299. begin
  300. {$ifndef FPC_HAS_CPSTRING}
  301. cp:=DefaultSystemCodePage;
  302. {$endif FPC_HAS_CPSTRING}
  303. cp:=TranslatePlaceholderCP(cp);
  304. arr[0]:=c;
  305. widestringmanager.Unicode2AnsiMoveProc(punicodechar(@arr[0]), fpc_UChar_To_AnsiStr, cp, 1);
  306. end;
  307. {$endif FPC_HAS_UCHAR_TO_ANSISTR}
  308. {$define FPC_HAS_PCHAR_TO_UNICODESTR}
  309. Function fpc_PChar_To_UnicodeStr(const p : pchar): UnicodeString; compilerproc;
  310. var
  311. i, len: longint;
  312. arr: TAnsiCharArray;
  313. begin
  314. arr:=TAnsiCharArray(p);
  315. i:=0;
  316. while arr[i]<>#0 do
  317. inc(i);
  318. if i<>0 then
  319. widestringmanager.Ansi2UnicodeMoveProc(P,DefaultSystemCodePage,fpc_PChar_To_UnicodeStr,i)
  320. else
  321. result:=''
  322. end;
  323. Function real_widechararray_to_unicodestr(const arr: array of widechar; zerobased: boolean): Unicodestring;
  324. var
  325. i : SizeInt;
  326. foundnull : boolean;
  327. begin
  328. if (zerobased) then
  329. begin
  330. foundnull:=false;
  331. for i:=low(arr) to high(arr) do
  332. if arr[i]=#0 then
  333. begin
  334. foundnull:=true;
  335. break;
  336. end;
  337. if not foundnull then
  338. i := high(arr)+1;
  339. end
  340. else
  341. i := high(arr)+1;
  342. result:=JLString.create(arr,0,i);
  343. end;
  344. {$define FPC_HAS_WIDECHARARRAY_TO_UNICODESTR}
  345. Function fpc_WideCharArray_To_UnicodeStr(const arr: array of widechar; zerobased: boolean = true): UnicodeString; compilerproc;
  346. begin
  347. result:=real_widechararray_to_unicodestr(arr,zerobased);
  348. end;
  349. { due to their names, the following procedures should be in wstrings.inc,
  350. however, the compiler generates code using this functions on all platforms }
  351. {$define FPC_HAS_WIDECHARARRAY_TO_SHORTSTR}
  352. procedure fpc_WideCharArray_To_ShortStr(out res : shortstring;const arr: array of widechar; zerobased: boolean = true);[public,alias:'FPC_WIDECHARARRAY_TO_SHORTSTR']; compilerproc;
  353. begin
  354. res:=real_widechararray_to_unicodestr(arr,zerobased);
  355. end;
  356. {$define FPC_HAS_WIDECHARARRAY_TO_WIDESTR}
  357. Function fpc_WideCharArray_To_WideStr(const arr: array of widechar; zerobased: boolean = true): WideString; compilerproc;
  358. begin
  359. result:=real_widechararray_to_unicodestr(arr,zerobased);
  360. end;
  361. {$define FPC_HAS_UNICODESTR_TO_CHARARRAY}
  362. procedure fpc_unicodestr_to_chararray(out res: array of AnsiChar; const src: UnicodeString); compilerproc;
  363. var
  364. len: longint;
  365. temp: array of jbyte;
  366. csname: unicodestring;
  367. begin
  368. len:=length(src);
  369. { make sure we don't dereference src if it can be nil (JM) }
  370. if len>0 then
  371. begin
  372. csname:=win2javacs(DefaultSystemCodePage);
  373. if csname='<unsupported>' then
  374. csname:='US-ASCII';
  375. temp:=JLString(src).getBytes(csname);
  376. len:=length(temp);
  377. if len>length(res) then
  378. len:=length(res);
  379. JLSystem.ArrayCopy(JLObject(temp),0,JLObject(@res),0,len);
  380. end;
  381. if len<=high(res) then
  382. JUArrays.fill(TJByteArray(@res),len,high(res),0);
  383. end;
  384. function fpc_unicodestr_setchar(const s: UnicodeString; const index: longint; const ch: unicodechar): UnicodeString; compilerproc;
  385. var
  386. sb: JLStringBuilder;
  387. begin
  388. sb:=JLStringBuilder.create(s);
  389. { string indexes are 1-based in Pascal, 0-based in Java }
  390. sb.setCharAt(index-1,ch);
  391. result:=sb.toString();
  392. end;
  393. {$define FPC_HAS_ANSISTR_TO_WIDECHARARRAY}
  394. procedure fpc_ansistr_to_widechararray(out res: array of widechar; const src: RawByteString); compilerproc;
  395. var
  396. len: SizeInt;
  397. temp: widestring;
  398. begin
  399. len := length(src);
  400. { make sure we don't dereference src if it can be nil (JM) }
  401. if len > 0 then
  402. temp:=src;
  403. len := length(temp);
  404. if len > high(res)+1 then
  405. len := high(res)+1;
  406. JLString(temp).getChars(0,len,res,0);
  407. JUArrays.fill(res,len,high(res),#0);
  408. end;
  409. {$define FPC_HAS_SHORTSTR_TO_WIDECHARARRAY}
  410. procedure fpc_shortstr_to_widechararray(out res: array of widechar; const src: ShortString); compilerproc;
  411. var
  412. len: longint;
  413. temp : unicodestring;
  414. begin
  415. len := length(src);
  416. { temp is initialized with an empty string, so no need to convert src in case
  417. it's also empty}
  418. if len > 0 then
  419. temp:=src;
  420. len := length(temp);
  421. if len > high(res)+1 then
  422. len := high(res)+1;
  423. JLString(temp).getChars(0,len,res,0);
  424. JUArrays.fill(res,len,high(res),#0);
  425. end;
  426. {$define FPC_HAS_UNICODESTR_TO_WIDECHARARRAY}
  427. procedure fpc_unicodestr_to_widechararray(out res: array of widechar; const src: UnicodeString); compilerproc;
  428. var
  429. i, len: SizeInt;
  430. begin
  431. len := length(src);
  432. if len > length(res) then
  433. len := length(res);
  434. JLString(src).getChars(0,len,res,0);
  435. end;
  436. {$define FPC_HAS_UNICODESTR_COMPARE}
  437. Function fpc_UnicodeStr_Compare(const S1,S2 : UnicodeString): SizeInt; compilerproc;
  438. {
  439. Compares 2 UnicodeStrings;
  440. The result is
  441. <0 if S1<S2
  442. 0 if S1=S2
  443. >0 if S1>S2
  444. }
  445. Var
  446. MaxI,Temp : SizeInt;
  447. begin
  448. if JLObject(S1)=JLObject(S2) then
  449. begin
  450. result:=0;
  451. exit;
  452. end;
  453. result:=JLString(S1).compareTo(S2);
  454. end;
  455. {$define FPC_HAS_UNICODESTR_COMPARE_EQUAL}
  456. Function fpc_UnicodeStr_Compare_Equal(const S1,S2 : UnicodeString): SizeInt; compilerproc;
  457. {
  458. Compares 2 UnicodeStrings for equality only;
  459. The result is
  460. 0 if S1=S2
  461. <>0 if S1<>S2
  462. }
  463. Var
  464. MaxI : SizeInt;
  465. begin
  466. result:=ord(not JLString(S1).equals(JLString(S2)));
  467. end;
  468. { lie, not required for this target }
  469. {$define FPC_HAS_UNICODESTR_RANGECHECK}
  470. {$define FPC_HAS_UNICODESTR_SETLENGTH}
  471. Procedure fpc_UnicodeStr_SetLength(Var S : UnicodeString; l : SizeInt);[Public,Alias : 'FPC_UNICODESTR_SETLENGTH']; compilerproc;
  472. {
  473. Sets The length of string S to L.
  474. Makes sure S is unique, and contains enough room.
  475. Returns new val
  476. }
  477. Var
  478. result: UnicodeString;
  479. movelen: SizeInt;
  480. chars: array of widechar;
  481. strlen: SizeInt;
  482. begin
  483. if (l>0) then
  484. begin
  485. if JLObject(S)=nil then
  486. begin
  487. { Need a completely new string...}
  488. result:=NewUnicodeString(l);
  489. end
  490. { no need to create a new string, since Java strings are immutable }
  491. else
  492. begin
  493. strlen:=length(s);
  494. if l=strlen then
  495. result:=s
  496. else if (l<strlen) then
  497. result:=JLString(s).substring(0,l)
  498. else
  499. begin
  500. setlength(chars,l);
  501. JLString(s).getChars(0,strlen,chars,0);
  502. result:=JLString.create(chars,0,l)
  503. end;
  504. end
  505. end
  506. else
  507. begin
  508. result:='';
  509. end;
  510. S:=Result;
  511. end;
  512. {*****************************************************************************
  513. Public functions, In interface.
  514. *****************************************************************************}
  515. {$define FPC_HAS_STRING_LEN_TO_WIDECHAR}
  516. function StringToWideChar(const Src : RawByteString;Dest : PWideChar;DestSize : SizeInt) : PWideChar;
  517. var
  518. temp: widestring;
  519. Len: SizeInt;
  520. begin
  521. temp:=src;
  522. Len:=Length(temp);
  523. if DestSize<=Len then
  524. Len:=Destsize-1;
  525. JLString(temp).getChars(0,Len,TJCharArray(Dest),0);
  526. Dest[Len]:=#0;
  527. result:=Dest;
  528. end;
  529. {$define FPC_HAS_UNICODECHAR_LEN_TO_STRING}
  530. function UnicodeCharLenToString(S : PUnicodeChar;Len : SizeInt) : UnicodeString;
  531. begin
  532. result:=JLString.Create(TJCharArray(S),0,len);
  533. end;
  534. {$define FPC_HAS_WIDECHAR_LEN_TO_STRING}
  535. function WideCharLenToString(S : PWideChar;Len : SizeInt) : UnicodeString;
  536. begin
  537. result:=JLString.Create(TJCharArray(S),0,len);
  538. end;
  539. {$define FPC_HAS_UNICODESTR_UNIQUE}
  540. Function fpc_unicodestr_Unique(var S : JLObject): JLObject; compilerproc;
  541. begin
  542. result:=s;
  543. end;
  544. { the publicly accessible uniquestring function is declared as
  545. "external name 'FPC_UNICODESTR_UNIQUE'", which is normally an alias for
  546. the fpc_unicodestr_Unique compiler proc; since one is a function and the
  547. other a procedure that sort of hackery doesn't work for the JVM -> create
  548. a separate procedure for that (since Java strings are immutable, they are
  549. always unique though) }
  550. procedure FPC_UNICODESTR_UNIQUE(var S : UnicodeString);
  551. begin
  552. { do nothing }
  553. end;
  554. {$define FPC_HAS_UNICODESTR_COPY}
  555. Function Fpc_UnicodeStr_Copy (Const S : UnicodeString; Index,Size : SizeInt) : UnicodeString;compilerproc;
  556. begin
  557. dec(index);
  558. if Index < 0 then
  559. Index := 0;
  560. { Check Size. Accounts for Zero-length S, the double check is needed because
  561. Size can be maxint and will get <0 when adding index }
  562. if (Size>Length(S)) or
  563. (Index+Size>Length(S)) then
  564. Size:=Length(S)-Index;
  565. If Size>0 then
  566. result:=JLString(s).subString(Index,Index+Size)
  567. else
  568. result:='';
  569. end;
  570. {$define FPC_HAS_POS_UNICODESTR_UNICODESTR}
  571. Function Pos (Const Substr : UnicodeString; Const Source : UnicodeString; Offset: Sizeint = 1) : SizeInt;
  572. begin
  573. Pos:=0;
  574. if (Length(SubStr)>0) and (Offset>0) and (Offset<=Length(Source)) then
  575. Pos:=JLString(Source).indexOf(SubStr,Offset-1)+1
  576. end;
  577. { Faster version for a unicodechar alone }
  578. {$define FPC_HAS_POS_UNICODECHAR_UNICODESTR}
  579. Function Pos (c : UnicodeChar; Const s : UnicodeString; Offset: Sizeint = 1) : SizeInt;
  580. begin
  581. Pos:=0;
  582. if (Offset>0) and (Offset<=Length(s)) then
  583. Pos:=JLString(s).indexOf(ord(c),Offset-1)+1;
  584. end;
  585. { Faster version for a char alone. Must be implemented because }
  586. { pos(c: char; const s: shortstring) also exists, so otherwise }
  587. { using pos(char,pchar) will always call the shortstring version }
  588. { (exact match for first argument), also with $h+ (JM) }
  589. {$define FPC_HAS_POS_CHAR_UNICODESTR}
  590. Function Pos (c : AnsiChar; Const s : UnicodeString; Offset: Sizeint = 1) : SizeInt;
  591. var
  592. i: SizeInt;
  593. wc : unicodechar;
  594. begin
  595. wc:=c;
  596. result:=Pos(wc,s,Offset);
  597. end;
  598. {$define FPC_HAS_DELETE_UNICODESTR}
  599. Procedure Delete (Var S : UnicodeString; Index,Size: SizeInt);
  600. Var
  601. LS : SizeInt;
  602. sb: JLStringBuilder;
  603. begin
  604. LS:=Length(S);
  605. if (Index>LS) or (Index<=0) or (Size<=0) then
  606. exit;
  607. { (Size+Index) will overflow if Size=MaxInt. }
  608. if Size>LS-Index then
  609. Size:=LS-Index+1;
  610. if Size<=LS-Index then
  611. begin
  612. Dec(Index);
  613. sb:=JLStringBuilder.Create(s);
  614. sb.delete(index,size);
  615. s:=sb.toString;
  616. end
  617. else
  618. s:=JLString(s).substring(0,index-1);
  619. end;
  620. {$define FPC_HAS_INSERT_UNICODESTR}
  621. Procedure Insert (Const Source : UnicodeString; Var S : UnicodeString; Index : SizeInt);
  622. var
  623. Temp : UnicodeString;
  624. LS : SizeInt;
  625. sb : JLStringBuilder;
  626. begin
  627. If Length(Source)=0 then
  628. exit;
  629. if index <= 0 then
  630. index := 1;
  631. Ls:=Length(S);
  632. if index > LS then
  633. index := LS+1;
  634. Dec(Index);
  635. sb:=JLStringBuilder.Create(S);
  636. sb.insert(Index,Source);
  637. S:=sb.toString;
  638. end;
  639. {$define FPC_HAS_UPCASE_UNICODECHAR}
  640. Function UpCase(c:UnicodeChar):UnicodeChar;
  641. begin
  642. result:=JLCharacter.toUpperCase(c);
  643. end;
  644. {$define FPC_HAS_UPCASE_UNICODESTR}
  645. function UpCase(const s : UnicodeString) : UnicodeString;
  646. begin
  647. result:=JLString(s).toUpperCase;
  648. end;
  649. {$define FPC_HAS_LOWERCASE_UNICODECHAR}
  650. Function LowerCase(c:UnicodeChar):UnicodeChar;
  651. begin
  652. result:=JLCharacter.toLowerCase(c);
  653. end;
  654. {$define FPC_HAS_LOWERCASE_UNICODESTR}
  655. function LowerCase(const s : UnicodeString) : UnicodeString;
  656. begin
  657. result:=JLString(s).toLowerCase;
  658. end;
  659. {$define FPC_HAS_SETSTRING_UNICODESTR_PUNICODECHAR}
  660. Procedure fpc_setstring_unicodestr_pwidechar(Out S : UnicodeString; Buf : PUnicodeChar; Len : SizeInt); compilerproc;
  661. begin
  662. if assigned(buf) and (Len>0) then
  663. s:=JLString.Create(TJCharArray(Buf),0,Len)
  664. else
  665. s:='';
  666. end;
  667. {$define FPC_HAS_UTF8ENCODE_UNICODESTRING}
  668. function UTF8Encode(const s : UnicodeString) : RawByteString;
  669. var
  670. i : SizeInt;
  671. hs : UTF8String;
  672. chars: array of widechar;
  673. begin
  674. result:='';
  675. if s='' then
  676. exit;
  677. SetLength(hs,length(s)*3);
  678. chars:=JLString(s).toCharArray;
  679. i:=UnicodeToUtf8(pchar(hs),length(hs)+1,pwidechar(chars),length(s));
  680. if i>0 then
  681. begin
  682. SetLength(hs,i-1);
  683. result:=hs;
  684. end;
  685. end;
  686. {$define FPC_HAS_UTF8DECODE_UNICODESTRING}
  687. function UTF8Decode(const s : RawByteString): UnicodeString;
  688. var
  689. i : SizeInt;
  690. chars: array of widechar;
  691. begin
  692. result:='';
  693. if s='' then
  694. exit;
  695. SetLength(chars,length(s)+1);
  696. i:=Utf8ToUnicode(pwidechar(chars),length(s)+1,pchar(s),length(s));
  697. if i>0 then
  698. result:=JLString.Create(chars,0,i-1);
  699. end;
  700. {$define FPC_HAS_UCS4STRING_TO_UNICODESTR}
  701. { concatenates an utf-32 char to a unicodestring. S *must* be unique when entering. }
  702. procedure ConcatUTF32ToUnicodeStr(const nc: UCS4Char; var S: JLStringBuilder; var index: SizeInt);
  703. begin
  704. { if nc > $ffff, we need two places }
  705. if (index+ord(nc > $ffff)>s.length) then
  706. if (s.length < 10*256) then
  707. s.setLength(s.length+10)
  708. else
  709. s.setlength(s.length+s.length shr 8);
  710. if (nc<$ffff) then
  711. begin
  712. s.setCharAt(index-1,unicodechar(nc));
  713. inc(index);
  714. end
  715. else if (dword(nc)<=$10ffff) then
  716. begin
  717. s.setCharAt(index-1,unicodechar((nc - $10000) shr 10 + $d800));
  718. s.setCharAt(index,unicodechar((nc - $10000) and $3ff + $dc00));
  719. inc(index,2);
  720. end
  721. else
  722. { invalid code point }
  723. begin
  724. s.setCharAt(index-1,'?');
  725. inc(index);
  726. end;
  727. end;
  728. function UCS4StringToUnicodeString(const s : UCS4String) : UnicodeString;
  729. var
  730. i : SizeInt;
  731. resindex : SizeInt;
  732. tmpres: JLStringBuilder;
  733. begin
  734. { skip terminating #0 }
  735. tmpres:=JLStringBuilder.Create(length(s)-1);
  736. resindex:=1;
  737. for i:=0 to high(s)-1 do
  738. ConcatUTF32ToUnicodeStr(s[i],tmpres,resindex);
  739. { adjust result length (may be too big due to growing }
  740. { for surrogate pairs) }
  741. tmpres.setLength(resindex-1);
  742. result:=tmpres.toString;
  743. end;
  744. procedure UCS4Encode(p: PWideChar; len: sizeint; out res: UCS4String); forward;
  745. {$define FPC_HAS_UCS4STRING_TO_UNICODESTR}
  746. function UnicodeStringToUCS4String(const s : UnicodeString) : UCS4String;
  747. begin
  748. UCS4Encode(PWideChar(JLString(s).toCharArray),Length(s),result);
  749. end;
  750. {$define FPC_HAS_WIDESTR_TO_UCS4STRING}
  751. function WideStringToUCS4String(const s : WideString) : UCS4String;
  752. begin
  753. UCS4Encode(PWideChar(JLString(s).toCharArray),Length(s),result);
  754. end;
  755. {$define FPC_HAS_UCS4STRING_TO_WIDESTR}
  756. function UCS4StringToWideString(const s : UCS4String) : WideString;
  757. begin
  758. result:=UCS4StringToUnicodeString(s);
  759. end;
  760. function StringElementSize(const S : UnicodeString): Word;
  761. begin
  762. result:=sizeof(unicodechar);
  763. end;
  764. function StringRefCount(const S : UnicodeString): SizeInt;
  765. begin
  766. if assigned(pointer(s)) then
  767. result:=1
  768. else
  769. result:=0;
  770. end;
  771. function StringCodePage(const S : UnicodeString): TSystemCodePage;
  772. begin
  773. if assigned(pointer(s)) then
  774. result:=CP_UTF16BE
  775. else
  776. result:=DefaultUnicodeCodePage;
  777. end;
  778. {$define FPC_HAS_TOSINGLEBYTEFILESYSTEMENCODEDFILENAME_UNICODESTRING}
  779. Function ToSingleByteFileSystemEncodedFileName(const Str: UnicodeString): RawByteString;
  780. Begin
  781. result:=AnsiString(AnsistringClass.Create(Str,DefaultFileSystemCodePage));
  782. End;
  783. {$define FPC_HAS_TOSINGLEBYTEFILESYSTEMENCODEDFILENAME_UNICODECHARARRAY}
  784. Function ToSingleByteFileSystemEncodedFileName(const arr: array of widechar): RawByteString;
  785. Begin
  786. result:=AnsiString(AnsistringClass.Create(arr,DefaultFileSystemCodePage));
  787. End;
  788. { *************************************************************************** }
  789. { ************************* Collator threadvar ****************************** }
  790. { *************************************************************************** }
  791. function TCollatorThreadVar.InitialValue: JLObject;
  792. begin
  793. { get a copy, since we modify the collator (e.g. setting the strength) }
  794. result:=JTCollator.getInstance.clone
  795. end;
  796. { *************************************************************************** }
  797. { ************************ Helpers for en/decode **************************** }
  798. { *************************************************************************** }
  799. function GetOrInsertNewEnDecoder(hm: JUWeakHashMap; cp: TSystemCodePage; decoder: boolean): JLObject;
  800. var
  801. cs: JNCCharSet;
  802. replacement: array[0..0] of jbyte;
  803. begin
  804. result:=hm.get(JLInteger.valueOf(cp));
  805. if not assigned(result) then
  806. begin
  807. try
  808. cs:=JNCCharSet.forName(win2javacs(cp));
  809. except
  810. { does not exist or not supported, fall back to ASCII like on other
  811. platforms}
  812. cs:=JNCCharset.forName('US-ASCII')
  813. end;
  814. if decoder then
  815. begin
  816. result:=cs.newDecoder;
  817. JNCCharsetDecoder(result).replaceWith('?');
  818. end
  819. else
  820. begin
  821. result:=cs.newEncoder;
  822. replacement[0]:=ord('?');
  823. JNCCharsetEncoder(result).replaceWith(replacement);
  824. end;
  825. { store in weak hashmap for future (possible) reuse }
  826. hm.put(JLInteger.Create(cp),result);
  827. end;
  828. end;
  829. { *************************************************************************** }
  830. { ************************** Decoder threadvar ****************************** }
  831. { *************************************************************************** }
  832. function TCharsetDecoderThreadvar.InitialValue: JLObject;
  833. begin
  834. result:=JUWeakHashMap.Create;
  835. end;
  836. function TCharsetDecoderThreadvar.getForCodePage(cp: TSystemCodePage): JNCCharsetDecoder;
  837. var
  838. hm: JUWeakHashMap;
  839. begin
  840. hm:=JUWeakHashMap(get);
  841. result:=JNCCharsetDecoder(GetOrInsertNewEnDecoder(hm,cp,true));
  842. end;
  843. { *************************************************************************** }
  844. { ************************** Encoder threadvar ****************************** }
  845. { *************************************************************************** }
  846. function TCharsetEncoderThreadvar.InitialValue: JLObject;
  847. begin
  848. result:=JUWeakHashMap.Create;
  849. end;
  850. function TCharsetEncoderThreadvar.getForCodePage(cp: TSystemCodePage): JNCCharsetEncoder;
  851. var
  852. hm: JUWeakHashMap;
  853. begin
  854. hm:=JUWeakHashMap(get);
  855. result:=JNCCharsetEncoder(GetOrInsertNewEnDecoder(hm,cp,false));
  856. end;
  857. { *************************************************************************** }
  858. { ************************ TUnicodeStringManager **************************** }
  859. { *************************************************************************** }
  860. class constructor TUnicodeStringManager.ClassCreate;
  861. begin
  862. collator:=TCollatorThreadVar.Create;
  863. decoder:=TCharsetDecoderThreadVar.Create;
  864. encoder:=TCharsetEncoderThreadVar.Create;
  865. DefaultSystemCodePage:=javacs2win(JNCCharset.defaultCharset.name);
  866. { unknown/unsupported -> default to ASCII (this will be used to parse
  867. stdin etc, so setting this to utf-8 or so won't help) }
  868. if DefaultSystemCodePage=65535 then
  869. DefaultSystemCodePage:=20127;
  870. DefaultFileSystemCodePage:=DefaultSystemCodePage;
  871. DefaultRTLFileSystemCodePage:=DefaultFileSystemCodePage;
  872. DefaultUnicodeCodePage:=CP_UTF16BE;
  873. end;
  874. procedure TUnicodeStringManager.Wide2AnsiMoveProc(source:pwidechar;var dest:RawByteString;cp : TSystemCodePage;len:SizeInt);
  875. begin
  876. DefaultUnicode2AnsiMove(source,dest,cp,len);
  877. end;
  878. procedure TUnicodeStringManager.Ansi2WideMoveProc(source:pchar;cp : TSystemCodePage;var dest:widestring;len:SizeInt);
  879. begin
  880. DefaultAnsi2UnicodeMove(source,cp,dest,len);
  881. end;
  882. function TUnicodeStringManager.UpperWideStringProc(const S: WideString): WideString;
  883. begin
  884. result:=upcase(s);
  885. end;
  886. function TUnicodeStringManager.LowerWideStringProc(const S: WideString): WideString;
  887. begin
  888. result:=lowercase(s);
  889. end;
  890. function TUnicodeStringManager.CompareWideStringProc(const s1, s2 : WideString) : PtrInt;
  891. var
  892. localcollator: JTCollator;
  893. begin
  894. localcollator:=JTCollator(collator.get);
  895. localcollator.setStrength(JTCollator.IDENTICAL);
  896. result:=localcollator.compare(s1,s2);
  897. end;
  898. function TUnicodeStringManager.CompareTextWideStringProc(const s1, s2 : WideString): PtrInt;
  899. var
  900. localcollator: JTCollator;
  901. begin
  902. localcollator:=JTCollator(collator.get);
  903. localcollator.setStrength(JTCollator.TERTIARY);
  904. result:=localcollator.compare(s1,s2);
  905. end;
  906. function TUnicodeStringManager.CharLengthPCharProc(const Str: PChar; Index: PtrInt): PtrInt;
  907. var
  908. localdecoder: JNCCharsetDecoder;
  909. begin
  910. localdecoder:=JNCCharsetDecoder(decoder.get);
  911. localdecoder.reset;
  912. localdecoder.onMalformedInput(JNCCodingErrorAction.fREPLACE);
  913. localdecoder.onUnmappableCharacter(JNCCodingErrorAction.fREPLACE);
  914. result:=localdecoder.decode(JNByteBuffer.wrap(TJByteArray(Str),Index,length(Str)-Index)).length;
  915. end;
  916. function TUnicodeStringManager.CodePointLengthProc(const Str: PChar; Index, MaxLookAhead: PtrInt): Ptrint;
  917. var
  918. localdecoder: JNCCharsetDecoder;
  919. inbuf: JNByteBuffer;
  920. outbuf: JNCharBuffer;
  921. coderres: JNCCoderResult;
  922. limit, maxlimit: longint;
  923. begin
  924. localdecoder:=JNCCharsetDecoder(decoder.get);
  925. localdecoder.reset;
  926. localdecoder.onMalformedInput(JNCCodingErrorAction.fREPORT);
  927. localdecoder.onUnmappableCharacter(JNCCodingErrorAction.fREPORT);
  928. localdecoder.reset;
  929. limit:=0;
  930. maxlimit:=min(length(Str)-Index,MaxLookAhead);
  931. { end of pchar? }
  932. if maxlimit=0 then
  933. begin
  934. result:=0;
  935. exit;
  936. end;
  937. inbuf:=JNByteBuffer.wrap(TJByteArray(Str),Index,Index+maxlimit);
  938. { we will get at most 2 output characters (when decoding from UTF-32 to
  939. UTF-16) }
  940. outbuf:=JNCharBuffer.allocate(2);
  941. { keep trying to decode until we managed to decode one character or
  942. reached the limit }
  943. repeat
  944. inc(limit);
  945. inbuf.limit(limit);
  946. coderres:=localdecoder.decode(inbuf,outbuf,true);
  947. until not coderres.isError or
  948. (limit=MaxLookAhead);
  949. if not coderres.isError then
  950. result:=inbuf.limit
  951. else
  952. result:=-1;
  953. end;
  954. function TUnicodeStringManager.UpperAnsiStringProc(const s : ansistring) : ansistring;
  955. begin
  956. result:=UpperWideStringProc(s);
  957. end;
  958. function TUnicodeStringManager.LowerAnsiStringProc(const s : ansistring) : ansistring;
  959. begin
  960. result:=LowerWideStringProc(s);
  961. end;
  962. function TUnicodeStringManager.CompareStrAnsiStringProc(const S1, S2: ansistring): PtrInt;
  963. begin
  964. result:=CompareUnicodeStringProc(S1,S2);
  965. end;
  966. function TUnicodeStringManager.CompareTextAnsiStringProc(const S1, S2: ansistring): PtrInt;
  967. begin
  968. result:=CompareTextUnicodeStringProc(S1,S2);
  969. end;
  970. function TUnicodeStringManager.StrCompAnsiStringProc(S1, S2: PChar): PtrInt;
  971. var
  972. str1,str2: unicodestring;
  973. begin
  974. str1:=JLString.Create(TJCharArray(S1),0,length(S1));
  975. str2:=JLString.Create(TJCharArray(S2),0,length(S2));
  976. result:=CompareUnicodeStringProc(str1,str2);
  977. end;
  978. function TUnicodeStringManager.StrICompAnsiStringProc(S1, S2: PChar): PtrInt;
  979. var
  980. str1,str2: unicodestring;
  981. begin
  982. str1:=JLString.Create(TJCharArray(S1),0,length(S1));
  983. str2:=JLString.Create(TJCharArray(S2),0,length(S2));
  984. result:=CompareTextUnicodeStringProc(str1,str2);
  985. end;
  986. function TUnicodeStringManager.StrLCompAnsiStringProc(S1, S2: PChar; MaxLen: PtrUInt): PtrInt;
  987. var
  988. str1,str2: unicodestring;
  989. begin
  990. str1:=JLString.Create(TJCharArray(S1),0,min(length(S1),MaxLen));
  991. str2:=JLString.Create(TJCharArray(S2),0,min(length(S2),MaxLen));
  992. result:=CompareUnicodeStringProc(str1,str2);
  993. end;
  994. function TUnicodeStringManager.StrLICompAnsiStringProc(S1, S2: PChar; MaxLen: PtrUInt): PtrInt;
  995. var
  996. str1,str2: unicodestring;
  997. begin
  998. str1:=JLString.Create(TJCharArray(S1),0,min(length(S1),MaxLen));
  999. str2:=JLString.Create(TJCharArray(S2),0,min(length(S2),MaxLen));
  1000. result:=CompareTextUnicodeStringProc(str1,str2);
  1001. end;
  1002. function TUnicodeStringManager.StrLowerAnsiStringProc(Str: PChar): PChar;
  1003. var
  1004. ustr: unicodestring;
  1005. begin
  1006. ustr:=JLString.Create(TJCharArray(Str),0,length(Str));
  1007. result:=PChar(AnsiStringClass(ansistring(LowerWideStringProc(ustr))).fdata);
  1008. end;
  1009. function TUnicodeStringManager.StrUpperAnsiStringProc(Str: PChar): PChar;
  1010. var
  1011. ustr: unicodestring;
  1012. begin
  1013. ustr:=JLString.Create(TJCharArray(Str),0,length(Str));
  1014. result:=PChar(AnsiStringClass(ansistring(UpperWideStringProc(ustr))).fdata);
  1015. end;
  1016. procedure TUnicodeStringManager.Unicode2AnsiMoveProc(source:punicodechar;var dest:RawByteString;cp : TSystemCodePage;len:SizeInt);
  1017. begin
  1018. DefaultUnicode2AnsiMove(source,dest,cp,len);
  1019. end;
  1020. procedure TUnicodeStringManager.Ansi2UnicodeMoveProc(source:pchar;cp : TSystemCodePage;var dest:unicodestring;len:SizeInt);
  1021. begin
  1022. DefaultAnsi2UnicodeMove(source,cp,dest,len);
  1023. end;
  1024. function TUnicodeStringManager.UpperUnicodeStringProc(const S: UnicodeString): UnicodeString;
  1025. begin
  1026. result:=UpperWideStringProc(S);
  1027. end;
  1028. function TUnicodeStringManager.LowerUnicodeStringProc(const S: UnicodeString): UnicodeString;
  1029. begin
  1030. result:=LowerWideStringProc(S);
  1031. end;
  1032. function TUnicodeStringManager.CompareUnicodeStringProc(const s1, s2 : UnicodeString) : PtrInt;
  1033. begin
  1034. result:=CompareWideStringProc(s1,s2);
  1035. end;
  1036. function TUnicodeStringManager.CompareTextUnicodeStringProc(const s1, s2 : UnicodeString): PtrInt;
  1037. begin
  1038. result:=CompareTextWideStringProc(s1,s2);
  1039. end;
  1040. procedure initunicodestringmanager;
  1041. begin
  1042. widestringmanager:=TUnicodeStringManager.Create;
  1043. end;