wstrings.inc 34 KB

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