wstrings.inc 34 KB

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