wstrings.inc 34 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417
  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. Dec (S,WideFirstOff);
  149. {$ifdef MSWINDOWS}
  150. if winwidestringalloc then
  151. SysFreeString(S)
  152. else
  153. {$endif MSWINDOWS}
  154. FreeMem (S);
  155. S:=Nil;
  156. end;
  157. Procedure fpc_WideStr_Decr_Ref (Var S : Pointer);[Public,Alias:'FPC_WIDESTR_DECR_REF']; compilerproc;
  158. {
  159. Decreases the ReferenceCount of a non constant widestring;
  160. If the reference count is zero, deallocate the string;
  161. }
  162. Type
  163. pSizeInt = ^SizeInt;
  164. Var
  165. l : pSizeInt;
  166. Begin
  167. { Zero string }
  168. if S=Nil then
  169. exit;
  170. {$ifndef FPC_WINLIKEWIDESTRING}
  171. { check for constant strings ...}
  172. l:=@PWideRec(S-WideFirstOff)^.Ref;
  173. if l^<0 then
  174. exit;
  175. { declocked does a MT safe dec and returns true, if the counter is 0 }
  176. if declocked(l^) then
  177. { Ref count dropped to zero ...
  178. ... remove }
  179. {$endif FPC_WINLIKEWIDESTRING}
  180. DisposeWideString(S);
  181. end;
  182. { alias for internal use }
  183. Procedure fpc_WideStr_Decr_Ref (Var S : Pointer);[external name 'FPC_WIDESTR_DECR_REF'];
  184. Procedure fpc_WideStr_Incr_Ref(Var S : Pointer);[Public,Alias:'FPC_WIDESTR_INCR_REF']; compilerproc;
  185. {$ifdef FPC_WINLIKEWIDESTRING}
  186. var
  187. p : pointer;
  188. {$endif FPC_WINLIKEWIDESTRING}
  189. Begin
  190. If S=Nil then
  191. exit;
  192. {$ifdef FPC_WINLIKEWIDESTRING}
  193. p:=s;
  194. fpc_WideStr_SetLength(WideString(s),length(WideString(p)));
  195. move(p^,s^,length(WideString(p))*sizeof(widechar));
  196. {$else FPC_WINLIKEWIDESTRING}
  197. { Let's be paranoid : Constant string ??}
  198. If PWideRec(S-WideFirstOff)^.Ref<0 then exit;
  199. inclocked(PWideRec(S-WideFirstOff)^.Ref);
  200. {$endif FPC_WINLIKEWIDESTRING}
  201. end;
  202. { alias for internal use }
  203. Procedure fpc_WideStr_Incr_Ref (S : Pointer);[external name 'FPC_WIDESTR_INCR_REF'];
  204. function fpc_WideStr_To_ShortStr (high_of_res: SizeInt;const S2 : WideString): shortstring;[Public, alias: 'FPC_WIDESTR_TO_SHORTSTR']; compilerproc;
  205. {
  206. Converts a WideString to a ShortString;
  207. }
  208. Var
  209. Size : SizeInt;
  210. temp : ansistring;
  211. begin
  212. if S2='' then
  213. fpc_WideStr_To_ShortStr:=''
  214. else
  215. begin
  216. Size:=Length(S2);
  217. If Size>high_of_res then
  218. Size:=high_of_res;
  219. widestringmanager.Wide2AnsiMoveProc(PWideChar(S2),temp,Size);
  220. fpc_WideStr_To_ShortStr:=temp;
  221. end;
  222. end;
  223. Function fpc_ShortStr_To_WideStr (Const S2 : ShortString): WideString;compilerproc;
  224. {
  225. Converts a ShortString to a WideString;
  226. }
  227. Var
  228. Size : SizeInt;
  229. begin
  230. Size:=Length(S2);
  231. if Size>0 then
  232. begin
  233. widestringmanager.Ansi2WideMoveProc(PChar(@S2[1]),fpc_ShortStr_To_WideStr,Size);
  234. { Terminating Zero }
  235. PWideChar(Pointer(fpc_ShortStr_To_WideStr)+Size*sizeof(WideChar))^:=#0;
  236. end;
  237. end;
  238. Function fpc_WideStr_To_AnsiStr (const S2 : WideString): AnsiString; compilerproc;
  239. {
  240. Converts a WideString to an AnsiString
  241. }
  242. Var
  243. Size : SizeInt;
  244. begin
  245. if s2='' then
  246. exit;
  247. Size:=Length(WideString(S2));
  248. if Size>0 then
  249. widestringmanager.Wide2AnsiMoveProc(PWideChar(Pointer(S2)),fpc_WideStr_To_AnsiStr,Size);
  250. end;
  251. Function fpc_AnsiStr_To_WideStr (Const S2 : AnsiString): WideString; compilerproc;
  252. {
  253. Converts an AnsiString to a WideString;
  254. }
  255. Var
  256. Size : SizeInt;
  257. begin
  258. if s2='' then
  259. exit;
  260. Size:=Length(S2);
  261. if Size>0 then
  262. begin
  263. widestringmanager.Ansi2WideMoveProc(PChar(S2),result,Size);
  264. { Terminating Zero }
  265. // PWideChar(Pointer(result)+Size*sizeof(WideChar))^:=#0;
  266. end;
  267. end;
  268. { compilers with widestrings should have compiler procs }
  269. Function fpc_PWideChar_To_AnsiStr(const p : pwidechar): ansistring; compilerproc;
  270. var
  271. Size : SizeInt;
  272. begin
  273. if p=nil then
  274. exit;
  275. Size := IndexWord(p^, -1, 0);
  276. if Size>0 then
  277. widestringmanager.Wide2AnsiMoveProc(P,result,Size);
  278. end;
  279. Function fpc_PWideChar_To_WideStr(const p : pwidechar): widestring; compilerproc;
  280. var
  281. Size : SizeInt;
  282. begin
  283. if p=nil then
  284. exit;
  285. Size := IndexWord(p^, -1, 0);
  286. Setlength(result,Size);
  287. if Size>0 then
  288. begin
  289. Move(p^,PWideChar(Pointer(result))^,Size*sizeof(WideChar));
  290. { Terminating Zero }
  291. PWideChar(Pointer(result)+Size*sizeof(WideChar))^:=#0;
  292. end;
  293. end;
  294. Function fpc_PWideChar_To_ShortStr(const p : pwidechar): shortstring; compilerproc;
  295. var
  296. Size : SizeInt;
  297. temp: ansistring;
  298. begin
  299. if p=nil then
  300. begin
  301. fpc_PWideChar_To_ShortStr:='';
  302. exit;
  303. end;
  304. Size := IndexWord(p^, $7fffffff, 0);
  305. if Size>0 then
  306. widestringmanager.Wide2AnsiMoveProc(p,temp,Size);
  307. result := temp
  308. end;
  309. { checked against the ansistring routine, 2001-05-27 (FK) }
  310. Procedure fpc_WideStr_Assign (Var S1 : Pointer;S2 : Pointer);[Public,Alias:'FPC_WIDESTR_ASSIGN']; compilerproc;
  311. {
  312. Assigns S2 to S1 (S1:=S2), taking in account reference counts.
  313. }
  314. begin
  315. {$ifndef FPC_WINLIKEWIDESTRING}
  316. If S2<>nil then
  317. If PWideRec(S2-WideFirstOff)^.Ref>0 then
  318. inclocked(PWideRec(S2-WideFirstOff)^.ref);
  319. {$endif FPC_WINLIKEWIDESTRING}
  320. { Decrease the reference count on the old S1 }
  321. fpc_widestr_decr_ref (S1);
  322. { And finally, have S1 pointing to S2 (or its copy) }
  323. {$ifdef FPC_WINLIKEWIDESTRING}
  324. fpc_WideStr_SetLength(WideString(s1),length(WideString(s2)));
  325. move(s2^,s1^,length(WideString(s1))*sizeof(widechar));
  326. {$else FPC_WINLIKEWIDESTRING}
  327. S1:=S2;
  328. {$endif FPC_WINLIKEWIDESTRING}
  329. end;
  330. { alias for internal use }
  331. Procedure fpc_WideStr_Assign (Var S1 : Pointer;S2 : Pointer);[external name 'FPC_WIDESTR_ASSIGN'];
  332. function fpc_WideStr_Concat (const S1,S2 : WideString): WideString; compilerproc;
  333. Var
  334. Size,Location : SizeInt;
  335. pc : pwidechar;
  336. begin
  337. { only assign if s1 or s2 is empty }
  338. if (S1='') then
  339. begin
  340. result:=s2;
  341. exit;
  342. end;
  343. if (S2='') then
  344. begin
  345. result:=s1;
  346. exit;
  347. end;
  348. Location:=Length(S1);
  349. Size:=length(S2);
  350. SetLength(result,Size+Location);
  351. pc:=pwidechar(result);
  352. Move(S1[1],pc^,Location*sizeof(WideChar));
  353. inc(pc,location);
  354. Move(S2[1],pc^,(Size+1)*sizeof(WideChar));
  355. end;
  356. function fpc_WideStr_Concat_multi (const sarr:array of Widestring): widestring; compilerproc;
  357. Var
  358. i : Longint;
  359. p : pointer;
  360. pc : pwidechar;
  361. Size,NewSize : SizeInt;
  362. begin
  363. { First calculate size of the result so we can do
  364. a single call to SetLength() }
  365. NewSize:=0;
  366. for i:=low(sarr) to high(sarr) do
  367. inc(Newsize,length(sarr[i]));
  368. SetLength(result,NewSize);
  369. pc:=pwidechar(result);
  370. for i:=low(sarr) to high(sarr) do
  371. begin
  372. p:=pointer(sarr[i]);
  373. if assigned(p) then
  374. begin
  375. Size:=length(widestring(p));
  376. Move(pwidechar(p)^,pc^,(Size+1)*sizeof(WideChar));
  377. inc(pc,size);
  378. end;
  379. end;
  380. end;
  381. Function fpc_Char_To_WideStr(const c : WideChar): WideString; compilerproc;
  382. {
  383. Converts a Char to a WideString;
  384. }
  385. begin
  386. if c = #0 then
  387. { result is automatically set to '' }
  388. exit;
  389. Setlength(fpc_Char_To_WideStr,1);
  390. fpc_Char_To_WideStr[1]:=c;
  391. { Terminating Zero }
  392. PWideChar(Pointer(fpc_Char_To_WideStr)+sizeof(WideChar))^:=#0;
  393. end;
  394. Function fpc_PChar_To_WideStr(const p : pchar): WideString; compilerproc;
  395. Var
  396. L : SizeInt;
  397. begin
  398. if (not assigned(p)) or (p[0]=#0) Then
  399. { result is automatically set to '' }
  400. exit;
  401. l:=IndexChar(p^,-1,#0);
  402. widestringmanager.Ansi2WideMoveProc(P,fpc_PChar_To_WideStr,l);
  403. end;
  404. Function fpc_CharArray_To_WideStr(const arr: array of char; zerobased: boolean = true): WideString; compilerproc;
  405. var
  406. i : SizeInt;
  407. begin
  408. if (zerobased) then
  409. begin
  410. if (arr[0]=#0) Then
  411. { result is automatically set to '' }
  412. exit;
  413. i:=IndexChar(arr,high(arr)+1,#0);
  414. if i = -1 then
  415. i := high(arr)+1;
  416. end
  417. else
  418. i := high(arr)+1;
  419. SetLength(fpc_CharArray_To_WideStr,i);
  420. widestringmanager.Ansi2WideMoveProc (pchar(@arr),fpc_CharArray_To_WideStr,i);
  421. end;
  422. function fpc_WideCharArray_To_ShortStr(const arr: array of widechar; zerobased: boolean = true): shortstring;[public,alias:'FPC_WIDECHARARRAY_TO_SHORTSTR']; compilerproc;
  423. var
  424. l: longint;
  425. index: longint;
  426. len: byte;
  427. temp: ansistring;
  428. begin
  429. l := high(arr)+1;
  430. if l>=256 then
  431. l:=255
  432. else if l<0 then
  433. l:=0;
  434. if zerobased then
  435. begin
  436. index:=IndexWord(arr[0],l,0);
  437. if (index < 0) then
  438. len := l
  439. else
  440. len := index;
  441. end
  442. else
  443. len := l;
  444. widestringmanager.Wide2AnsiMoveProc (pwidechar(@arr),temp,len);
  445. fpc_WideCharArray_To_ShortStr := temp;
  446. end;
  447. Function fpc_WideCharArray_To_AnsiStr(const arr: array of widechar; zerobased: boolean = true): AnsiString; compilerproc;
  448. var
  449. i : SizeInt;
  450. begin
  451. if (zerobased) then
  452. begin
  453. i:=IndexWord(arr,high(arr)+1,0);
  454. if i = -1 then
  455. i := high(arr)+1;
  456. end
  457. else
  458. i := high(arr)+1;
  459. SetLength(fpc_WideCharArray_To_AnsiStr,i);
  460. widestringmanager.Wide2AnsiMoveProc (pwidechar(@arr),fpc_WideCharArray_To_AnsiStr,i);
  461. end;
  462. Function fpc_WideCharArray_To_WideStr(const arr: array of widechar; zerobased: boolean = true): WideString; compilerproc;
  463. var
  464. i : SizeInt;
  465. begin
  466. if (zerobased) then
  467. begin
  468. i:=IndexWord(arr,high(arr)+1,0);
  469. if i = -1 then
  470. i := high(arr)+1;
  471. end
  472. else
  473. i := high(arr)+1;
  474. SetLength(fpc_WideCharArray_To_WideStr,i);
  475. Move(pwidechar(@arr)^, PWideChar(Pointer(@fpc_WideCharArray_To_WideStr[1]))^,i*sizeof(WideChar));
  476. { Terminating Zero }
  477. PWideChar(Pointer(@fpc_WideCharArray_To_WideStr[1])+i*sizeof(WideChar))^:=#0;
  478. end;
  479. { inside the compiler, the resulttype is modified to that of the actual }
  480. { chararray we're converting to (JM) }
  481. function fpc_widestr_to_chararray(arraysize: SizeInt; const src: WideString): fpc_big_chararray;[public,alias: 'FPC_WIDESTR_TO_CHARARRAY']; compilerproc;
  482. var
  483. len: SizeInt;
  484. temp: ansistring;
  485. begin
  486. len := length(src);
  487. { make sure we don't dereference src if it can be nil (JM) }
  488. if len > 0 then
  489. widestringmanager.wide2ansimoveproc(pwidechar(@src[1]),temp,len);
  490. len := length(temp);
  491. if len > arraysize then
  492. len := arraysize;
  493. move(temp[1],fpc_widestr_to_chararray[0],len);
  494. fillchar(fpc_widestr_to_chararray[len],arraysize-len,0);
  495. end;
  496. { inside the compiler, the resulttype is modified to that of the actual }
  497. { widechararray we're converting to (JM) }
  498. function fpc_widestr_to_widechararray(arraysize: SizeInt; const src: WideString): fpc_big_widechararray;[public,alias: 'FPC_WIDESTR_TO_WIDECHARARRAY']; compilerproc;
  499. var
  500. len: SizeInt;
  501. begin
  502. len := length(src);
  503. if len > arraysize then
  504. len := arraysize;
  505. { make sure we don't try to access element 1 of the ansistring if it's nil }
  506. if len > 0 then
  507. move(src[1],fpc_widestr_to_widechararray[0],len*SizeOf(WideChar));
  508. fillchar(fpc_widestr_to_widechararray[len],(arraysize-len)*SizeOf(WideChar),0);
  509. end;
  510. { inside the compiler, the resulttype is modified to that of the actual }
  511. { chararray we're converting to (JM) }
  512. function fpc_ansistr_to_widechararray(arraysize: SizeInt; const src: AnsiString): fpc_big_widechararray;[public,alias: 'FPC_ANSISTR_TO_WIDECHARARRAY']; compilerproc;
  513. var
  514. len: SizeInt;
  515. temp: widestring;
  516. begin
  517. len := length(src);
  518. { make sure we don't dereference src if it can be nil (JM) }
  519. if len > 0 then
  520. widestringmanager.ansi2widemoveproc(pchar(@src[1]),temp,len);
  521. len := length(temp);
  522. if len > arraysize then
  523. len := arraysize;
  524. move(temp[1],fpc_ansistr_to_widechararray[0],len*sizeof(widechar));
  525. fillchar(fpc_ansistr_to_widechararray[len],(arraysize-len)*SizeOf(WideChar),0);
  526. end;
  527. function fpc_shortstr_to_widechararray(arraysize: SizeInt; const src: ShortString): fpc_big_widechararray;[public,alias: 'FPC_SHORTSTR_TO_WIDECHARARRAY']; compilerproc;
  528. var
  529. len: longint;
  530. temp : widestring;
  531. begin
  532. len := length(src);
  533. { make sure we don't access char 1 if length is 0 (JM) }
  534. if len > 0 then
  535. widestringmanager.ansi2widemoveproc(pchar(@src[1]),temp,len);
  536. len := length(temp);
  537. if len > arraysize then
  538. len := arraysize;
  539. move(temp[1],fpc_shortstr_to_widechararray[0],len*sizeof(widechar));
  540. fillchar(fpc_shortstr_to_widechararray[len],(arraysize-len)*SizeOf(WideChar),0);
  541. end;
  542. Function fpc_WideStr_Compare(const S1,S2 : WideString): SizeInt;[Public,Alias : 'FPC_WIDESTR_COMPARE']; compilerproc;
  543. {
  544. Compares 2 WideStrings;
  545. The result is
  546. <0 if S1<S2
  547. 0 if S1=S2
  548. >0 if S1>S2
  549. }
  550. Var
  551. MaxI,Temp : SizeInt;
  552. begin
  553. if pointer(S1)=pointer(S2) then
  554. begin
  555. fpc_WideStr_Compare:=0;
  556. exit;
  557. end;
  558. Maxi:=Length(S1);
  559. temp:=Length(S2);
  560. If MaxI>Temp then
  561. MaxI:=Temp;
  562. Temp:=CompareWord(S1[1],S2[1],MaxI);
  563. if temp=0 then
  564. temp:=Length(S1)-Length(S2);
  565. fpc_WideStr_Compare:=Temp;
  566. end;
  567. Procedure fpc_WideStr_CheckZero(p : pointer);[Public,Alias : 'FPC_WIDESTR_CHECKZERO']; compilerproc;
  568. begin
  569. if p=nil then
  570. HandleErrorFrame(201,get_frame);
  571. end;
  572. Procedure fpc_WideStr_CheckRange(len,index : SizeInt);[Public,Alias : 'FPC_WIDESTR_RANGECHECK']; compilerproc;
  573. begin
  574. if (index>len) or (Index<1) then
  575. HandleErrorFrame(201,get_frame);
  576. end;
  577. Procedure fpc_WideStr_SetLength(Var S : WideString; l : SizeInt);[Public,Alias : 'FPC_WIDESTR_SETLENGTH']; compilerproc;
  578. {
  579. Sets The length of string S to L.
  580. Makes sure S is unique, and contains enough room.
  581. }
  582. Var
  583. Temp : Pointer;
  584. movelen: SizeInt;
  585. begin
  586. if (l>0) then
  587. begin
  588. if Pointer(S)=nil then
  589. begin
  590. { Need a complete new string...}
  591. Pointer(s):=NewWideString(l);
  592. end
  593. { windows doesn't support reallocing widestrings, this code
  594. is anyways subject to be removed because widestrings shouldn't be
  595. ref. counted anymore (FK) }
  596. else
  597. {$ifndef FPC_WINLIKEWIDESTRING}
  598. if
  599. {$ifdef MSWINDOWS}
  600. not winwidestringalloc and
  601. {$endif MSWINDOWS}
  602. (PWideRec(Pointer(S)-WideFirstOff)^.Ref = 1) then
  603. begin
  604. Dec(Pointer(S),WideFirstOff);
  605. if L*sizeof(WideChar)+WideRecLen>MemSize(Pointer(S)) then
  606. reallocmem(pointer(S), L*sizeof(WideChar)+WideRecLen);
  607. Inc(Pointer(S), WideFirstOff);
  608. end
  609. else
  610. {$endif FPC_WINLIKEWIDESTRING}
  611. begin
  612. { Reallocation is needed... }
  613. Temp:=Pointer(NewWideString(L));
  614. if Length(S)>0 then
  615. begin
  616. if l < succ(length(s)) then
  617. movelen := l
  618. { also move terminating null }
  619. else
  620. movelen := succ(length(s));
  621. Move(Pointer(S)^,Temp^,movelen * Sizeof(WideChar));
  622. end;
  623. fpc_widestr_decr_ref(Pointer(S));
  624. Pointer(S):=Temp;
  625. end
  626. ;
  627. { Force nil termination in case it gets shorter }
  628. PWord(Pointer(S)+l*sizeof(WideChar))^:=0;
  629. PWideRec(Pointer(S)-FirstOff)^.Len:=l*sizeof(WideChar);
  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;