wstrings.inc 42 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717
  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. Freemem(S);
  154. {$else MSWINDOWS}
  155. if winwidestringalloc then
  156. SysFreeString(S)
  157. else
  158. begin
  159. Dec (S,WideFirstOff);
  160. Freemem(S);
  161. end;
  162. {$endif MSWINDOWS}
  163. S:=Nil;
  164. end;
  165. Procedure fpc_WideStr_Decr_Ref (Var S : Pointer);[Public,Alias:'FPC_WIDESTR_DECR_REF']; compilerproc;
  166. {
  167. Decreases the ReferenceCount of a non constant widestring;
  168. If the reference count is zero, deallocate the string;
  169. }
  170. Type
  171. pSizeInt = ^SizeInt;
  172. {$ifndef FPC_WINLIKEWIDESTRING}
  173. Var
  174. l : pSizeInt;
  175. {$endif FPC_WINLIKEWIDESTRING}
  176. Begin
  177. { Zero string }
  178. if S=Nil then
  179. exit;
  180. {$ifndef FPC_WINLIKEWIDESTRING}
  181. { check for constant strings ...}
  182. l:=@PWideRec(S-WideFirstOff)^.Ref;
  183. if l^<0 then
  184. exit;
  185. { declocked does a MT safe dec and returns true, if the counter is 0 }
  186. if declocked(l^) then
  187. { Ref count dropped to zero ...
  188. ... remove }
  189. {$else}
  190. { Here we check if widestring is constant (located in .data section).
  191. initialstklen variable is compiler generated and always located at the beginning of .data section.
  192. ExitCode is zero initialized variable and located somewhere in .bss section which is followed
  193. by .data section in memory.
  194. If widestring points to the address space between initialstklen and ExitCode then it is constant
  195. and there is no need to dispose it. }
  196. if (S<@initialstklen) or (S>@ExitCode) then
  197. {$endif FPC_WINLIKEWIDESTRING}
  198. DisposeWideString(S);
  199. end;
  200. { alias for internal use }
  201. Procedure fpc_WideStr_Decr_Ref (Var S : Pointer);[external name 'FPC_WIDESTR_DECR_REF'];
  202. Procedure fpc_WideStr_Incr_Ref(Var S : Pointer);[Public,Alias:'FPC_WIDESTR_INCR_REF']; compilerproc;
  203. {$ifdef FPC_WINLIKEWIDESTRING}
  204. var
  205. p : pointer;
  206. {$endif FPC_WINLIKEWIDESTRING}
  207. Begin
  208. If S=Nil then
  209. exit;
  210. {$ifdef FPC_WINLIKEWIDESTRING}
  211. p:=NewWidestring(length(WideString(S)));
  212. move(s^,p^,(length(WideString(s))+1)*sizeof(widechar)); // double #0 too
  213. s:=p;
  214. {$else FPC_WINLIKEWIDESTRING}
  215. { Let's be paranoid : Constant string ??}
  216. If PWideRec(S-WideFirstOff)^.Ref<0 then
  217. exit;
  218. inclocked(PWideRec(S-WideFirstOff)^.Ref);
  219. {$endif FPC_WINLIKEWIDESTRING}
  220. end;
  221. { alias for internal use }
  222. Procedure fpc_WideStr_Incr_Ref (Var S : Pointer);[external name 'FPC_WIDESTR_INCR_REF'];
  223. function fpc_WideStr_To_ShortStr (high_of_res: SizeInt;const S2 : WideString): shortstring;[Public, alias: 'FPC_WIDESTR_TO_SHORTSTR']; compilerproc;
  224. {
  225. Converts a WideString to a ShortString;
  226. }
  227. Var
  228. Size : SizeInt;
  229. temp : ansistring;
  230. begin
  231. result:='';
  232. Size:=Length(S2);
  233. if Size>0 then
  234. begin
  235. If Size>high_of_res then
  236. Size:=high_of_res;
  237. widestringmanager.Wide2AnsiMoveProc(PWideChar(S2),temp,Size);
  238. result:=temp;
  239. end;
  240. end;
  241. Function fpc_ShortStr_To_WideStr (Const S2 : ShortString): WideString;compilerproc;
  242. {
  243. Converts a ShortString to a WideString;
  244. }
  245. Var
  246. Size : SizeInt;
  247. begin
  248. result:='';
  249. Size:=Length(S2);
  250. if Size>0 then
  251. begin
  252. widestringmanager.Ansi2WideMoveProc(PChar(@S2[1]),result,Size);
  253. { Terminating Zero }
  254. PWideChar(Pointer(fpc_ShortStr_To_WideStr)+Size*sizeof(WideChar))^:=#0;
  255. end;
  256. end;
  257. Function fpc_WideStr_To_AnsiStr (const S2 : WideString): AnsiString; compilerproc;
  258. {
  259. Converts a WideString to an AnsiString
  260. }
  261. Var
  262. Size : SizeInt;
  263. begin
  264. result:='';
  265. Size:=Length(S2);
  266. if Size>0 then
  267. widestringmanager.Wide2AnsiMoveProc(PWideChar(Pointer(S2)),result,Size);
  268. end;
  269. Function fpc_AnsiStr_To_WideStr (Const S2 : AnsiString): WideString; compilerproc;
  270. {
  271. Converts an AnsiString to a WideString;
  272. }
  273. Var
  274. Size : SizeInt;
  275. begin
  276. result:='';
  277. Size:=Length(S2);
  278. if Size>0 then
  279. widestringmanager.Ansi2WideMoveProc(PChar(S2),result,Size);
  280. end;
  281. Function fpc_PWideChar_To_AnsiStr(const p : pwidechar): ansistring; compilerproc;
  282. var
  283. Size : SizeInt;
  284. begin
  285. result:='';
  286. if p=nil then
  287. exit;
  288. Size := IndexWord(p^, -1, 0);
  289. if Size>0 then
  290. widestringmanager.Wide2AnsiMoveProc(P,result,Size);
  291. end;
  292. Function fpc_PWideChar_To_WideStr(const p : pwidechar): widestring; compilerproc;
  293. var
  294. Size : SizeInt;
  295. begin
  296. result:='';
  297. if p=nil then
  298. exit;
  299. Size := IndexWord(p^, -1, 0);
  300. Setlength(result,Size);
  301. if Size>0 then
  302. begin
  303. Move(p^,PWideChar(Pointer(result))^,Size*sizeof(WideChar));
  304. { Terminating Zero }
  305. PWideChar(Pointer(result)+Size*sizeof(WideChar))^:=#0;
  306. end;
  307. end;
  308. Function fpc_PWideChar_To_ShortStr(const p : pwidechar): shortstring; compilerproc;
  309. var
  310. Size : SizeInt;
  311. temp: ansistring;
  312. begin
  313. result:='';
  314. if p=nil then
  315. exit;
  316. Size := IndexWord(p^, $7fffffff, 0);
  317. if Size>0 then
  318. begin
  319. widestringmanager.Wide2AnsiMoveProc(p,temp,Size);
  320. result:=temp;
  321. end;
  322. end;
  323. { checked against the ansistring routine, 2001-05-27 (FK) }
  324. Procedure fpc_WideStr_Assign (Var S1 : Pointer;S2 : Pointer);[Public,Alias:'FPC_WIDESTR_ASSIGN']; compilerproc;
  325. {
  326. Assigns S2 to S1 (S1:=S2), taking in account reference counts.
  327. }
  328. begin
  329. {$ifdef FPC_WINLIKEWIDESTRING}
  330. if S1=S2 then exit;
  331. { Decrease the reference count on the old S1 }
  332. fpc_widestr_decr_ref (S1);
  333. if S2<>nil then
  334. begin
  335. S1:=NewWidestring(length(WideString(S2)));
  336. move(s2^,s1^,(length(WideString(s1))+1)*sizeof(widechar));
  337. end
  338. else
  339. S1:=nil;
  340. {$else FPC_WINLIKEWIDESTRING}
  341. If S2<>nil then
  342. If PWideRec(S2-WideFirstOff)^.Ref>0 then
  343. inclocked(PWideRec(S2-WideFirstOff)^.ref);
  344. { Decrease the reference count on the old S1 }
  345. fpc_widestr_decr_ref (S1);
  346. s1:=s2;
  347. {$endif FPC_WINLIKEWIDESTRING}
  348. end;
  349. { alias for internal use }
  350. Procedure fpc_WideStr_Assign (Var S1 : Pointer;S2 : Pointer);[external name 'FPC_WIDESTR_ASSIGN'];
  351. {$ifndef STR_CONCAT_PROCS}
  352. function fpc_WideStr_Concat (const S1,S2 : WideString): WideString; compilerproc;
  353. Var
  354. Size,Location : SizeInt;
  355. pc : pwidechar;
  356. begin
  357. { only assign if s1 or s2 is empty }
  358. if (S1='') then
  359. begin
  360. result:=s2;
  361. exit;
  362. end;
  363. if (S2='') then
  364. begin
  365. result:=s1;
  366. exit;
  367. end;
  368. Location:=Length(S1);
  369. Size:=length(S2);
  370. SetLength(result,Size+Location);
  371. pc:=pwidechar(result);
  372. Move(S1[1],pc^,Location*sizeof(WideChar));
  373. inc(pc,location);
  374. Move(S2[1],pc^,(Size+1)*sizeof(WideChar));
  375. end;
  376. function fpc_WideStr_Concat_multi (const sarr:array of Widestring): widestring; compilerproc;
  377. Var
  378. i : Longint;
  379. p : pointer;
  380. pc : pwidechar;
  381. Size,NewSize : SizeInt;
  382. begin
  383. { First calculate size of the result so we can do
  384. a single call to SetLength() }
  385. NewSize:=0;
  386. for i:=low(sarr) to high(sarr) do
  387. inc(Newsize,length(sarr[i]));
  388. SetLength(result,NewSize);
  389. pc:=pwidechar(result);
  390. for i:=low(sarr) to high(sarr) do
  391. begin
  392. p:=pointer(sarr[i]);
  393. if assigned(p) then
  394. begin
  395. Size:=length(widestring(p));
  396. Move(pwidechar(p)^,pc^,(Size+1)*sizeof(WideChar));
  397. inc(pc,size);
  398. end;
  399. end;
  400. end;
  401. {$else STR_CONCAT_PROCS}
  402. procedure fpc_WideStr_Concat (var DestS:Widestring;const S1,S2 : WideString); compilerproc;
  403. Var
  404. Size,Location : SizeInt;
  405. same : boolean;
  406. begin
  407. { only assign if s1 or s2 is empty }
  408. if (S1='') then
  409. begin
  410. DestS:=s2;
  411. exit;
  412. end;
  413. if (S2='') then
  414. begin
  415. DestS:=s1;
  416. exit;
  417. end;
  418. Location:=Length(S1);
  419. Size:=length(S2);
  420. { Use Pointer() typecasts to prevent extra conversion code }
  421. if Pointer(DestS)=Pointer(S1) then
  422. begin
  423. same:=Pointer(S1)=Pointer(S2);
  424. SetLength(DestS,Size+Location);
  425. if same then
  426. Move(Pointer(DestS)^,(Pointer(DestS)+Location*sizeof(WideChar))^,(Size)*sizeof(WideChar))
  427. else
  428. Move(Pointer(S2)^,(Pointer(DestS)+Location*sizeof(WideChar))^,(Size+1)*sizeof(WideChar));
  429. end
  430. else if Pointer(DestS)=Pointer(S2) then
  431. begin
  432. SetLength(DestS,Size+Location);
  433. Move(Pointer(DestS)^,(Pointer(DestS)+Location*sizeof(WideChar))^,(Size+1)*sizeof(WideChar));
  434. Move(Pointer(S1)^,Pointer(DestS)^,Location*sizeof(WideChar));
  435. end
  436. else
  437. begin
  438. DestS:='';
  439. SetLength(DestS,Size+Location);
  440. Move(Pointer(S1)^,Pointer(DestS)^,Location*sizeof(WideChar));
  441. Move(Pointer(S2)^,(Pointer(DestS)+Location*sizeof(WideChar))^,(Size+1)*sizeof(WideChar));
  442. end;
  443. end;
  444. procedure fpc_WideStr_Concat_multi (var DestS:Widestring;const sarr:array of Widestring); compilerproc;
  445. Var
  446. lowstart,i : Longint;
  447. p,pc : pointer;
  448. Size,NewLen,
  449. OldDestLen : SizeInt;
  450. destcopy : widestring;
  451. begin
  452. if high(sarr)=0 then
  453. begin
  454. DestS:='';
  455. exit;
  456. end;
  457. lowstart:=low(sarr);
  458. if Pointer(DestS)=Pointer(sarr[lowstart]) then
  459. inc(lowstart);
  460. { Check for another reuse, then we can't use
  461. the append optimization }
  462. for i:=lowstart to high(sarr) do
  463. begin
  464. if Pointer(DestS)=Pointer(sarr[i]) then
  465. begin
  466. { if DestS is used somewhere in the middle of the expression,
  467. we need to make sure the original string still exists after
  468. we empty/modify DestS }
  469. destcopy:=dests;
  470. lowstart:=low(sarr);
  471. break;
  472. end;
  473. end;
  474. { Start with empty DestS if we start with concatting
  475. the first array element }
  476. if lowstart=low(sarr) then
  477. DestS:='';
  478. OldDestLen:=length(DestS);
  479. { Calculate size of the result so we can do
  480. a single call to SetLength() }
  481. NewLen:=0;
  482. for i:=low(sarr) to high(sarr) do
  483. inc(NewLen,length(sarr[i]));
  484. SetLength(DestS,NewLen);
  485. { Concat all strings, except the string we already
  486. copied in DestS }
  487. pc:=Pointer(DestS)+OldDestLen*sizeof(WideChar);
  488. for i:=lowstart to high(sarr) do
  489. begin
  490. p:=pointer(sarr[i]);
  491. if assigned(p) then
  492. begin
  493. Size:=length(widestring(p));
  494. Move(p^,pc^,(Size+1)*sizeof(WideChar));
  495. inc(pc,size*sizeof(WideChar));
  496. end;
  497. end;
  498. end;
  499. {$endif STR_CONCAT_PROCS}
  500. Function fpc_Char_To_WideStr(const c : WideChar): WideString; compilerproc;
  501. {
  502. Converts a Char to a WideString;
  503. }
  504. begin
  505. if c = #0 then
  506. { result is automatically set to '' }
  507. exit;
  508. Setlength(fpc_Char_To_WideStr,1);
  509. fpc_Char_To_WideStr[1]:=c;
  510. { Terminating Zero }
  511. PWideChar(Pointer(fpc_Char_To_WideStr)+sizeof(WideChar))^:=#0;
  512. end;
  513. Function fpc_PChar_To_WideStr(const p : pchar): WideString; compilerproc;
  514. Var
  515. L : SizeInt;
  516. begin
  517. if (not assigned(p)) or (p[0]=#0) Then
  518. { result is automatically set to '' }
  519. exit;
  520. l:=IndexChar(p^,-1,#0);
  521. widestringmanager.Ansi2WideMoveProc(P,fpc_PChar_To_WideStr,l);
  522. end;
  523. Function fpc_CharArray_To_WideStr(const arr: array of char; zerobased: boolean = true): WideString; compilerproc;
  524. var
  525. i : SizeInt;
  526. begin
  527. if (zerobased) then
  528. begin
  529. if (arr[0]=#0) Then
  530. { result is automatically set to '' }
  531. exit;
  532. i:=IndexChar(arr,high(arr)+1,#0);
  533. if i = -1 then
  534. i := high(arr)+1;
  535. end
  536. else
  537. i := high(arr)+1;
  538. SetLength(fpc_CharArray_To_WideStr,i);
  539. widestringmanager.Ansi2WideMoveProc (pchar(@arr),fpc_CharArray_To_WideStr,i);
  540. end;
  541. function fpc_WideCharArray_To_ShortStr(const arr: array of widechar; zerobased: boolean = true): shortstring;[public,alias:'FPC_WIDECHARARRAY_TO_SHORTSTR']; compilerproc;
  542. var
  543. l: longint;
  544. index: longint;
  545. len: byte;
  546. temp: ansistring;
  547. begin
  548. l := high(arr)+1;
  549. if l>=256 then
  550. l:=255
  551. else if l<0 then
  552. l:=0;
  553. if zerobased then
  554. begin
  555. index:=IndexWord(arr[0],l,0);
  556. if (index < 0) then
  557. len := l
  558. else
  559. len := index;
  560. end
  561. else
  562. len := l;
  563. widestringmanager.Wide2AnsiMoveProc (pwidechar(@arr),temp,len);
  564. fpc_WideCharArray_To_ShortStr := temp;
  565. end;
  566. Function fpc_WideCharArray_To_AnsiStr(const arr: array of widechar; zerobased: boolean = true): AnsiString; compilerproc;
  567. var
  568. i : SizeInt;
  569. begin
  570. if (zerobased) then
  571. begin
  572. i:=IndexWord(arr,high(arr)+1,0);
  573. if i = -1 then
  574. i := high(arr)+1;
  575. end
  576. else
  577. i := high(arr)+1;
  578. SetLength(fpc_WideCharArray_To_AnsiStr,i);
  579. widestringmanager.Wide2AnsiMoveProc (pwidechar(@arr),fpc_WideCharArray_To_AnsiStr,i);
  580. end;
  581. Function fpc_WideCharArray_To_WideStr(const arr: array of widechar; zerobased: boolean = true): WideString; compilerproc;
  582. var
  583. i : SizeInt;
  584. begin
  585. if (zerobased) then
  586. begin
  587. i:=IndexWord(arr,high(arr)+1,0);
  588. if i = -1 then
  589. i := high(arr)+1;
  590. end
  591. else
  592. i := high(arr)+1;
  593. SetLength(fpc_WideCharArray_To_WideStr,i);
  594. Move(pwidechar(@arr)^, PWideChar(Pointer(@fpc_WideCharArray_To_WideStr[1]))^,i*sizeof(WideChar));
  595. { Terminating Zero }
  596. PWideChar(Pointer(@fpc_WideCharArray_To_WideStr[1])+i*sizeof(WideChar))^:=#0;
  597. end;
  598. {$ifndef FPC_STRTOCHARARRAYPROC}
  599. { inside the compiler, the resulttype is modified to that of the actual }
  600. { chararray we're converting to (JM) }
  601. function fpc_widestr_to_chararray(arraysize: SizeInt; const src: WideString): fpc_big_chararray;[public,alias: 'FPC_WIDESTR_TO_CHARARRAY']; compilerproc;
  602. var
  603. len: SizeInt;
  604. temp: ansistring;
  605. begin
  606. len := length(src);
  607. { make sure we don't dereference src if it can be nil (JM) }
  608. if len > 0 then
  609. widestringmanager.wide2ansimoveproc(pwidechar(@src[1]),temp,len);
  610. len := length(temp);
  611. if len > arraysize then
  612. len := arraysize;
  613. {$r-}
  614. move(temp[1],fpc_widestr_to_chararray[0],len);
  615. fillchar(fpc_widestr_to_chararray[len],arraysize-len,0);
  616. {$ifdef RangeCheckWasOn}
  617. {$r+}
  618. {$endif}
  619. end;
  620. { inside the compiler, the resulttype is modified to that of the actual }
  621. { widechararray we're converting to (JM) }
  622. function fpc_widestr_to_widechararray(arraysize: SizeInt; const src: WideString): fpc_big_widechararray;[public,alias: 'FPC_WIDESTR_TO_WIDECHARARRAY']; compilerproc;
  623. var
  624. len: SizeInt;
  625. begin
  626. len := length(src);
  627. if len > arraysize then
  628. len := arraysize;
  629. {$r-}
  630. { make sure we don't try to access element 1 of the ansistring if it's nil }
  631. if len > 0 then
  632. move(src[1],fpc_widestr_to_widechararray[0],len*SizeOf(WideChar));
  633. fillchar(fpc_widestr_to_widechararray[len],(arraysize-len)*SizeOf(WideChar),0);
  634. {$ifdef RangeCheckWasOn}
  635. {$r+}
  636. {$endif}
  637. end;
  638. { inside the compiler, the resulttype is modified to that of the actual }
  639. { chararray we're converting to (JM) }
  640. function fpc_ansistr_to_widechararray(arraysize: SizeInt; const src: AnsiString): fpc_big_widechararray;[public,alias: 'FPC_ANSISTR_TO_WIDECHARARRAY']; compilerproc;
  641. var
  642. len: SizeInt;
  643. temp: widestring;
  644. begin
  645. len := length(src);
  646. { make sure we don't dereference src if it can be nil (JM) }
  647. if len > 0 then
  648. widestringmanager.ansi2widemoveproc(pchar(@src[1]),temp,len);
  649. len := length(temp);
  650. if len > arraysize then
  651. len := arraysize;
  652. {$r-}
  653. move(temp[1],fpc_ansistr_to_widechararray[0],len*sizeof(widechar));
  654. fillchar(fpc_ansistr_to_widechararray[len],(arraysize-len)*SizeOf(WideChar),0);
  655. {$ifdef RangeCheckWasOn}
  656. {$r+}
  657. {$endif}
  658. end;
  659. function fpc_shortstr_to_widechararray(arraysize: SizeInt; const src: ShortString): fpc_big_widechararray;[public,alias: 'FPC_SHORTSTR_TO_WIDECHARARRAY']; compilerproc;
  660. var
  661. len: longint;
  662. temp : widestring;
  663. begin
  664. len := length(src);
  665. { make sure we don't access char 1 if length is 0 (JM) }
  666. if len > 0 then
  667. widestringmanager.ansi2widemoveproc(pchar(@src[1]),temp,len);
  668. len := length(temp);
  669. if len > arraysize then
  670. len := arraysize;
  671. {$r-}
  672. move(temp[1],fpc_shortstr_to_widechararray[0],len*sizeof(widechar));
  673. fillchar(fpc_shortstr_to_widechararray[len],(arraysize-len)*SizeOf(WideChar),0);
  674. {$ifdef RangeCheckWasOn}
  675. {$r+}
  676. {$endif}
  677. end;
  678. {$else ndef FPC_STRTOCHARARRAYPROC}
  679. procedure fpc_widestr_to_chararray(out res: array of char; const src: WideString); compilerproc;
  680. var
  681. len: SizeInt;
  682. temp: ansistring;
  683. begin
  684. len := length(src);
  685. { make sure we don't dereference src if it can be nil (JM) }
  686. if len > 0 then
  687. widestringmanager.wide2ansimoveproc(pwidechar(@src[1]),temp,len);
  688. len := length(temp);
  689. if len > length(res) then
  690. len := length(res);
  691. {$r-}
  692. move(temp[1],res[0],len);
  693. fillchar(res[len],length(res)-len,0);
  694. {$ifdef RangeCheckWasOn}
  695. {$r+}
  696. {$endif}
  697. end;
  698. procedure fpc_widestr_to_widechararray(out res: array of widechar; const src: WideString); compilerproc;
  699. var
  700. len: SizeInt;
  701. begin
  702. len := length(src);
  703. if len > length(res) then
  704. len := length(res);
  705. {$r-}
  706. { make sure we don't try to access element 1 of the ansistring if it's nil }
  707. if len > 0 then
  708. move(src[1],res[0],len*SizeOf(WideChar));
  709. fillchar(res[len],(length(res)-len)*SizeOf(WideChar),0);
  710. {$ifdef RangeCheckWasOn}
  711. {$r+}
  712. {$endif}
  713. end;
  714. procedure fpc_ansistr_to_widechararray(out res: array of widechar; const src: AnsiString); compilerproc;
  715. var
  716. len: SizeInt;
  717. temp: widestring;
  718. begin
  719. len := length(src);
  720. { make sure we don't dereference src if it can be nil (JM) }
  721. if len > 0 then
  722. widestringmanager.ansi2widemoveproc(pchar(@src[1]),temp,len);
  723. len := length(temp);
  724. if len > length(res) then
  725. len := length(res);
  726. {$r-}
  727. move(temp[1],res[0],len*sizeof(widechar));
  728. fillchar(res[len],(length(res)-len)*SizeOf(WideChar),0);
  729. {$ifdef RangeCheckWasOn}
  730. {$r+}
  731. {$endif}
  732. end;
  733. procedure fpc_shortstr_to_widechararray(out res: array of widechar; const src: ShortString); compilerproc;
  734. var
  735. len: longint;
  736. temp : widestring;
  737. begin
  738. len := length(src);
  739. { make sure we don't access char 1 if length is 0 (JM) }
  740. if len > 0 then
  741. widestringmanager.ansi2widemoveproc(pchar(@src[1]),temp,len);
  742. len := length(temp);
  743. if len > length(res) then
  744. len := length(res);
  745. {$r-}
  746. move(temp[1],res[0],len*sizeof(widechar));
  747. fillchar(res[len],(length(res)-len)*SizeOf(WideChar),0);
  748. {$ifdef RangeCheckWasOn}
  749. {$r+}
  750. {$endif}
  751. end;
  752. {$endif ndef FPC_STRTOCHARARRAYPROC}
  753. Function fpc_WideStr_Compare(const S1,S2 : WideString): SizeInt;[Public,Alias : 'FPC_WIDESTR_COMPARE']; compilerproc;
  754. {
  755. Compares 2 WideStrings;
  756. The result is
  757. <0 if S1<S2
  758. 0 if S1=S2
  759. >0 if S1>S2
  760. }
  761. Var
  762. MaxI,Temp : SizeInt;
  763. begin
  764. if pointer(S1)=pointer(S2) then
  765. begin
  766. fpc_WideStr_Compare:=0;
  767. exit;
  768. end;
  769. Maxi:=Length(S1);
  770. temp:=Length(S2);
  771. If MaxI>Temp then
  772. MaxI:=Temp;
  773. Temp:=CompareWord(S1[1],S2[1],MaxI);
  774. if temp=0 then
  775. temp:=Length(S1)-Length(S2);
  776. fpc_WideStr_Compare:=Temp;
  777. end;
  778. Function fpc_WideStr_Compare_Equal(const S1,S2 : WideString): SizeInt;[Public,Alias : 'FPC_WIDESTR_COMPARE_EQUAL']; compilerproc;
  779. {
  780. Compares 2 WideStrings for equality only;
  781. The result is
  782. 0 if S1=S2
  783. <>0 if S1<>S2
  784. }
  785. Var
  786. MaxI : SizeInt;
  787. begin
  788. if pointer(S1)=pointer(S2) then
  789. exit(0);
  790. Maxi:=Length(S1);
  791. If MaxI<>Length(S2) then
  792. exit(-1)
  793. else
  794. exit(CompareWord(S1[1],S2[1],MaxI));
  795. end;
  796. Procedure fpc_WideStr_CheckZero(p : pointer);[Public,Alias : 'FPC_WIDESTR_CHECKZERO']; compilerproc;
  797. begin
  798. if p=nil then
  799. HandleErrorFrame(201,get_frame);
  800. end;
  801. Procedure fpc_WideStr_CheckRange(len,index : SizeInt);[Public,Alias : 'FPC_WIDESTR_RANGECHECK']; compilerproc;
  802. begin
  803. if (index>len) or (Index<1) then
  804. HandleErrorFrame(201,get_frame);
  805. end;
  806. Procedure fpc_WideStr_SetLength(Var S : WideString; l : SizeInt);[Public,Alias : 'FPC_WIDESTR_SETLENGTH']; compilerproc;
  807. {
  808. Sets The length of string S to L.
  809. Makes sure S is unique, and contains enough room.
  810. }
  811. Var
  812. Temp : Pointer;
  813. movelen: SizeInt;
  814. begin
  815. if (l>0) then
  816. begin
  817. if Pointer(S)=nil then
  818. begin
  819. { Need a complete new string...}
  820. Pointer(s):=NewWideString(l);
  821. end
  822. { windows doesn't support reallocing widestrings, this code
  823. is anyways subject to be removed because widestrings shouldn't be
  824. ref. counted anymore (FK) }
  825. else
  826. {$ifndef FPC_WINLIKEWIDESTRING}
  827. if
  828. {$ifdef MSWINDOWS}
  829. not winwidestringalloc and
  830. {$endif MSWINDOWS}
  831. (PWideRec(Pointer(S)-WideFirstOff)^.Ref = 1) then
  832. begin
  833. Dec(Pointer(S),WideFirstOff);
  834. if L*sizeof(WideChar)+WideRecLen>MemSize(Pointer(S)) then
  835. reallocmem(pointer(S), L*sizeof(WideChar)+WideRecLen);
  836. Inc(Pointer(S), WideFirstOff);
  837. end
  838. else
  839. {$endif FPC_WINLIKEWIDESTRING}
  840. begin
  841. { Reallocation is needed... }
  842. Temp:=Pointer(NewWideString(L));
  843. if Length(S)>0 then
  844. begin
  845. if l < succ(length(s)) then
  846. movelen := l
  847. { also move terminating null }
  848. else
  849. movelen := succ(length(s));
  850. Move(Pointer(S)^,Temp^,movelen * Sizeof(WideChar));
  851. end;
  852. fpc_widestr_decr_ref(Pointer(S));
  853. Pointer(S):=Temp;
  854. end;
  855. { Force nil termination in case it gets shorter }
  856. PWord(Pointer(S)+l*sizeof(WideChar))^:=0;
  857. {$ifndef FPC_WINLIKEWIDESTRING}
  858. PWideRec(Pointer(S)-WideFirstOff)^.Len:=l*sizeof(WideChar);
  859. {$endif FPC_WINLIKEWIDESTRING}
  860. end
  861. else
  862. begin
  863. { Length=0 }
  864. if Pointer(S)<>nil then
  865. fpc_widestr_decr_ref (Pointer(S));
  866. Pointer(S):=Nil;
  867. end;
  868. end;
  869. {*****************************************************************************
  870. Public functions, In interface.
  871. *****************************************************************************}
  872. function WideCharToString(S : PWideChar) : AnsiString;
  873. begin
  874. result:=WideCharLenToString(s,Length(WideString(s)));
  875. end;
  876. function StringToWideChar(const Src : AnsiString;Dest : PWideChar;DestSize : SizeInt) : PWideChar;
  877. var
  878. temp:widestring;
  879. begin
  880. widestringmanager.Ansi2WideMoveProc(PChar(Src),temp,Length(Src));
  881. if Length(temp)<DestSize then
  882. move(temp[1],Dest^,Length(temp)*SizeOf(WideChar))
  883. else
  884. move(temp[1],Dest^,(DestSize-1)*SizeOf(WideChar));
  885. Dest[DestSize-1]:=#0;
  886. result:=Dest;
  887. end;
  888. function WideCharLenToString(S : PWideChar;Len : SizeInt) : AnsiString;
  889. begin
  890. //SetLength(result,Len);
  891. widestringmanager.Wide2AnsiMoveproc(S,result,Len);
  892. end;
  893. procedure WideCharLenToStrVar(Src : PWideChar;Len : SizeInt;out Dest : AnsiString);
  894. begin
  895. Dest:=WideCharLenToString(Src,Len);
  896. end;
  897. procedure WideCharToStrVar(S : PWideChar;out Dest : AnsiString);
  898. begin
  899. Dest:=WideCharToString(S);
  900. end;
  901. Function fpc_widestr_Unique(Var S : Pointer): Pointer; [Public,Alias : 'FPC_WIDESTR_UNIQUE']; compilerproc;
  902. {$ifdef FPC_WINLIKEWIDESTRING}
  903. begin
  904. pointer(result) := pointer(s);
  905. end;
  906. {$else FPC_WINLIKEWIDESTRING}
  907. {
  908. Make sure reference count of S is 1,
  909. using copy-on-write semantics.
  910. }
  911. Var
  912. SNew : Pointer;
  913. L : SizeInt;
  914. begin
  915. pointer(result) := pointer(s);
  916. If Pointer(S)=Nil then
  917. exit;
  918. if PWideRec(Pointer(S)-WideFirstOff)^.Ref<>1 then
  919. begin
  920. L:=PWideRec(Pointer(S)-WideFirstOff)^.len div sizeof(WideChar);
  921. SNew:=NewWideString (L);
  922. Move (PWideChar(S)^,SNew^,(L+1)*sizeof(WideChar));
  923. PWideRec(SNew-WideFirstOff)^.len:=L * sizeof(WideChar);
  924. fpc_widestr_decr_ref (Pointer(S)); { Thread safe }
  925. pointer(S):=SNew;
  926. pointer(result):=SNew;
  927. end;
  928. end;
  929. {$endif FPC_WINLIKEWIDESTRING}
  930. Function Fpc_WideStr_Copy (Const S : WideString; Index,Size : SizeInt) : WideString;compilerproc;
  931. var
  932. ResultAddress : Pointer;
  933. begin
  934. ResultAddress:=Nil;
  935. dec(index);
  936. if Index < 0 then
  937. Index := 0;
  938. { Check Size. Accounts for Zero-length S, the double check is needed because
  939. Size can be maxint and will get <0 when adding index }
  940. if (Size>Length(S)) or
  941. (Index+Size>Length(S)) then
  942. Size:=Length(S)-Index;
  943. If Size>0 then
  944. begin
  945. If Index<0 Then
  946. Index:=0;
  947. ResultAddress:=Pointer(NewWideString (Size));
  948. if ResultAddress<>Nil then
  949. begin
  950. Move (PWideChar(S)[Index],ResultAddress^,Size*sizeof(WideChar));
  951. PWideRec(ResultAddress-WideFirstOff)^.Len:=Size*sizeof(WideChar);
  952. PWideChar(ResultAddress+Size*sizeof(WideChar))^:=#0;
  953. end;
  954. end;
  955. Pointer(fpc_widestr_Copy):=ResultAddress;
  956. end;
  957. Function Pos (Const Substr : WideString; Const Source : WideString) : SizeInt;
  958. var
  959. i,MaxLen : SizeInt;
  960. pc : pwidechar;
  961. begin
  962. Pos:=0;
  963. if Length(SubStr)>0 then
  964. begin
  965. MaxLen:=Length(source)-Length(SubStr);
  966. i:=0;
  967. pc:=@source[1];
  968. while (i<=MaxLen) do
  969. begin
  970. inc(i);
  971. if (SubStr[1]=pc^) and
  972. (CompareWord(Substr[1],pc^,Length(SubStr))=0) then
  973. begin
  974. Pos:=i;
  975. exit;
  976. end;
  977. inc(pc);
  978. end;
  979. end;
  980. end;
  981. { Faster version for a widechar alone }
  982. Function Pos (c : WideChar; Const s : WideString) : SizeInt;
  983. var
  984. i: SizeInt;
  985. pc : pwidechar;
  986. begin
  987. pc:=@s[1];
  988. for i:=1 to length(s) do
  989. begin
  990. if pc^=c then
  991. begin
  992. pos:=i;
  993. exit;
  994. end;
  995. inc(pc);
  996. end;
  997. pos:=0;
  998. end;
  999. Function Pos (c : WideChar; Const s : AnsiString) : SizeInt;
  1000. var
  1001. i: SizeInt;
  1002. pc : pchar;
  1003. begin
  1004. pc:=@s[1];
  1005. for i:=1 to length(s) do
  1006. begin
  1007. if widechar(pc^)=c then
  1008. begin
  1009. pos:=i;
  1010. exit;
  1011. end;
  1012. inc(pc);
  1013. end;
  1014. pos:=0;
  1015. end;
  1016. Function Pos (c : AnsiString; Const s : WideString) : SizeInt;{$ifdef SYSTEMINLINE}inline;{$endif}
  1017. begin
  1018. result:=Pos(WideString(c),s);
  1019. end;
  1020. Function Pos (c : ShortString; Const s : WideString) : SizeInt;{$ifdef SYSTEMINLINE}inline;{$endif}
  1021. begin
  1022. result:=Pos(WideString(c),s);
  1023. end;
  1024. Function Pos (c : WideString; Const s : AnsiString) : SizeInt;{$ifdef SYSTEMINLINE}inline;{$endif}
  1025. begin
  1026. result:=Pos(c,WideString(s));
  1027. end;
  1028. { Faster version for a char alone. Must be implemented because }
  1029. { pos(c: char; const s: shortstring) also exists, so otherwise }
  1030. { using pos(char,pchar) will always call the shortstring version }
  1031. { (exact match for first argument), also with $h+ (JM) }
  1032. Function Pos (c : Char; Const s : WideString) : SizeInt;
  1033. var
  1034. i: SizeInt;
  1035. wc : widechar;
  1036. pc : pwidechar;
  1037. begin
  1038. wc:=c;
  1039. pc:=@s[1];
  1040. for i:=1 to length(s) do
  1041. begin
  1042. if pc^=wc then
  1043. begin
  1044. pos:=i;
  1045. exit;
  1046. end;
  1047. inc(pc);
  1048. end;
  1049. pos:=0;
  1050. end;
  1051. Procedure Delete (Var S : WideString; Index,Size: SizeInt);
  1052. Var
  1053. LS : SizeInt;
  1054. begin
  1055. If Length(S)=0 then
  1056. exit;
  1057. if index<=0 then
  1058. exit;
  1059. LS:=PWideRec(Pointer(S)-WideFirstOff)^.Len div sizeof(WideChar);
  1060. if (Index<=LS) and (Size>0) then
  1061. begin
  1062. UniqueString (S);
  1063. if Size+Index>LS then
  1064. Size:=LS-Index+1;
  1065. if Index+Size<=LS then
  1066. begin
  1067. Dec(Index);
  1068. Move(PWideChar(S)[Index+Size],PWideChar(S)[Index],(LS-Index+1)*sizeof(WideChar));
  1069. end;
  1070. Setlength(s,LS-Size);
  1071. end;
  1072. end;
  1073. Procedure Insert (Const Source : WideString; Var S : WideString; Index : SizeInt);
  1074. var
  1075. Temp : WideString;
  1076. LS : SizeInt;
  1077. begin
  1078. If Length(Source)=0 then
  1079. exit;
  1080. if index <= 0 then
  1081. index := 1;
  1082. Ls:=Length(S);
  1083. if index > LS then
  1084. index := LS+1;
  1085. Dec(Index);
  1086. Pointer(Temp) := NewWideString(Length(Source)+LS);
  1087. SetLength(Temp,Length(Source)+LS);
  1088. If Index>0 then
  1089. move (PWideChar(S)^,PWideChar(Temp)^,Index*sizeof(WideChar));
  1090. Move (PWideChar(Source)^,PWideChar(Temp)[Index],Length(Source)*sizeof(WideChar));
  1091. If (LS-Index)>0 then
  1092. Move(PWideChar(S)[Index],PWideChar(temp)[Length(Source)+index],(LS-Index)*sizeof(WideChar));
  1093. S:=Temp;
  1094. end;
  1095. function UpCase(const s : WideString) : WideString;
  1096. begin
  1097. result:=widestringmanager.UpperWideStringProc(s);
  1098. end;
  1099. Procedure SetString (Out S : WideString; Buf : PWideChar; Len : SizeInt);
  1100. var
  1101. BufLen: SizeInt;
  1102. begin
  1103. SetLength(S,Len);
  1104. If (Buf<>Nil) and (Len>0) then
  1105. begin
  1106. BufLen := IndexWord(Buf^, Len+1, 0);
  1107. If (BufLen>0) and (BufLen < Len) then
  1108. Len := BufLen;
  1109. Move (Buf[0],S[1],Len*sizeof(WideChar));
  1110. PWideChar(Pointer(S)+Len*sizeof(WideChar))^:=#0;
  1111. end;
  1112. end;
  1113. Procedure SetString (Out S : WideString; Buf : PChar; Len : SizeInt);
  1114. var
  1115. BufLen: SizeInt;
  1116. begin
  1117. SetLength(S,Len);
  1118. If (Buf<>Nil) and (Len>0) then
  1119. begin
  1120. BufLen := IndexByte(Buf^, Len+1, 0);
  1121. If (BufLen>0) and (BufLen < Len) then
  1122. Len := BufLen;
  1123. widestringmanager.Ansi2WideMoveProc(Buf,S,Len);
  1124. //PWideChar(Pointer(S)+Len*sizeof(WideChar))^:=#0;
  1125. end;
  1126. end;
  1127. Function fpc_Val_Real_WideStr(Const S : WideString; out Code : ValSInt): ValReal; [public, alias:'FPC_VAL_REAL_WIDESTR']; compilerproc;
  1128. Var
  1129. SS : String;
  1130. begin
  1131. fpc_Val_Real_WideStr := 0;
  1132. if length(S) > 255 then
  1133. code := 256
  1134. else
  1135. begin
  1136. SS := S;
  1137. Val(SS,fpc_Val_Real_WideStr,code);
  1138. end;
  1139. end;
  1140. function fpc_val_enum_widestr(str2ordindex:pointer;const s:widestring;out code:valsint):longint;compilerproc;
  1141. var ss:shortstring;
  1142. begin
  1143. if length(s)>255 then
  1144. code:=256
  1145. else
  1146. begin
  1147. ss:=s;
  1148. val(ss,fpc_val_enum_widestr,code);
  1149. end;
  1150. end;
  1151. Function fpc_Val_Currency_WideStr(Const S : WideString; out Code : ValSInt): Currency; [public, alias:'FPC_VAL_CURRENCY_WIDESTR']; compilerproc;
  1152. Var
  1153. SS : String;
  1154. begin
  1155. if length(S) > 255 then
  1156. begin
  1157. fpc_Val_Currency_WideStr:=0;
  1158. code := 256;
  1159. end
  1160. else
  1161. begin
  1162. SS := S;
  1163. Val(SS,fpc_Val_Currency_WideStr,code);
  1164. end;
  1165. end;
  1166. Function fpc_Val_UInt_WideStr (Const S : WideString; out Code : ValSInt): ValUInt; [public, alias:'FPC_VAL_UINT_WIDESTR']; compilerproc;
  1167. Var
  1168. SS : ShortString;
  1169. begin
  1170. fpc_Val_UInt_WideStr := 0;
  1171. if length(S) > 255 then
  1172. code := 256
  1173. else
  1174. begin
  1175. SS := S;
  1176. Val(SS,fpc_Val_UInt_WideStr,code);
  1177. end;
  1178. end;
  1179. Function fpc_Val_SInt_WideStr (DestSize: SizeInt; Const S : WideString; out Code : ValSInt): ValSInt; [public, alias:'FPC_VAL_SINT_WIDESTR']; compilerproc;
  1180. Var
  1181. SS : ShortString;
  1182. begin
  1183. fpc_Val_SInt_WideStr:=0;
  1184. if length(S)>255 then
  1185. code:=256
  1186. else
  1187. begin
  1188. SS := S;
  1189. fpc_Val_SInt_WideStr := int_Val_SInt_ShortStr(DestSize,SS,Code);
  1190. end;
  1191. end;
  1192. {$ifndef CPU64}
  1193. Function fpc_Val_qword_WideStr (Const S : WideString; out Code : ValSInt): qword; [public, alias:'FPC_VAL_QWORD_WIDESTR']; compilerproc;
  1194. Var
  1195. SS : ShortString;
  1196. begin
  1197. fpc_Val_qword_WideStr:=0;
  1198. if length(S)>255 then
  1199. code:=256
  1200. else
  1201. begin
  1202. SS := S;
  1203. Val(SS,fpc_Val_qword_WideStr,Code);
  1204. end;
  1205. end;
  1206. Function fpc_Val_int64_WideStr (Const S : WideString; out Code : ValSInt): Int64; [public, alias:'FPC_VAL_INT64_WIDESTR']; compilerproc;
  1207. Var
  1208. SS : ShortString;
  1209. begin
  1210. fpc_Val_int64_WideStr:=0;
  1211. if length(S)>255 then
  1212. code:=256
  1213. else
  1214. begin
  1215. SS := S;
  1216. Val(SS,fpc_Val_int64_WideStr,Code);
  1217. end;
  1218. end;
  1219. {$endif CPU64}
  1220. procedure fpc_WideStr_Float(d : ValReal;len,fr,rt : SizeInt;out s : WideString);compilerproc;
  1221. var
  1222. ss : shortstring;
  1223. begin
  1224. str_real(len,fr,d,treal_type(rt),ss);
  1225. s:=ss;
  1226. end;
  1227. procedure fpc_widestr_enum(ordinal,len:sizeint;typinfo,ord2strindex:pointer;out s:widestring);compilerproc;
  1228. var ss:shortstring;
  1229. begin
  1230. fpc_shortstr_enum(ordinal,len,typinfo,ord2strindex,ss);
  1231. s:=ss;
  1232. end;
  1233. {$ifdef FPC_HAS_STR_CURRENCY}
  1234. procedure fpc_WideStr_Currency(c : Currency;len,fr : SizeInt;out s : WideString);compilerproc;
  1235. var
  1236. ss : shortstring;
  1237. begin
  1238. str(c:len:fr,ss);
  1239. s:=ss;
  1240. end;
  1241. {$endif FPC_HAS_STR_CURRENCY}
  1242. Procedure fpc_WideStr_SInt(v : ValSint; Len : SizeInt; out S : WideString);compilerproc;
  1243. Var
  1244. SS : ShortString;
  1245. begin
  1246. Str (v:Len,SS);
  1247. S:=SS;
  1248. end;
  1249. Procedure fpc_WideStr_UInt(v : ValUInt;Len : SizeInt; out S : WideString);compilerproc;
  1250. Var
  1251. SS : ShortString;
  1252. begin
  1253. str(v:Len,SS);
  1254. S:=SS;
  1255. end;
  1256. {$ifndef CPU64}
  1257. Procedure fpc_WideStr_Int64(v : Int64; Len : SizeInt; out S : WideString);compilerproc;
  1258. Var
  1259. SS : ShortString;
  1260. begin
  1261. Str (v:Len,SS);
  1262. S:=SS;
  1263. end;
  1264. Procedure fpc_WideStr_Qword(v : Qword;Len : SizeInt; out S : WideString);compilerproc;
  1265. Var
  1266. SS : ShortString;
  1267. begin
  1268. str(v:Len,SS);
  1269. S:=SS;
  1270. end;
  1271. {$endif CPU64}
  1272. function UnicodeToUtf8(Dest: PChar; Source: PWideChar; MaxBytes: SizeInt): SizeInt;{$ifdef SYSTEMINLINE}inline;{$endif}
  1273. begin
  1274. if assigned(Source) then
  1275. Result:=UnicodeToUtf8(Dest,MaxBytes,Source,IndexWord(Source^,-1,0))
  1276. else
  1277. Result:=0;
  1278. end;
  1279. function UnicodeToUtf8(Dest: PChar; MaxDestBytes: SizeUInt; Source: PWideChar; SourceChars: SizeUInt): SizeUInt;
  1280. var
  1281. i,j : SizeUInt;
  1282. w : word;
  1283. begin
  1284. result:=0;
  1285. if source=nil then
  1286. exit;
  1287. i:=0;
  1288. j:=0;
  1289. if assigned(Dest) then
  1290. begin
  1291. while (i<SourceChars) and (j<MaxDestBytes) do
  1292. begin
  1293. w:=word(Source[i]);
  1294. case w of
  1295. 0..$7f:
  1296. begin
  1297. Dest[j]:=char(w);
  1298. inc(j);
  1299. end;
  1300. $80..$7ff:
  1301. begin
  1302. if j+1>=MaxDestBytes then
  1303. break;
  1304. Dest[j]:=char($c0 or (w shr 6));
  1305. Dest[j+1]:=char($80 or (w and $3f));
  1306. inc(j,2);
  1307. end;
  1308. else
  1309. begin
  1310. if j+2>=MaxDestBytes then
  1311. break;
  1312. Dest[j]:=char($e0 or (w shr 12));
  1313. Dest[j+1]:=char($80 or ((w shr 6)and $3f));
  1314. Dest[j+2]:=char($80 or (w and $3f));
  1315. inc(j,3);
  1316. end;
  1317. end;
  1318. inc(i);
  1319. end;
  1320. if j>MaxDestBytes-1 then
  1321. j:=MaxDestBytes-1;
  1322. Dest[j]:=#0;
  1323. end
  1324. else
  1325. begin
  1326. while i<SourceChars do
  1327. begin
  1328. case word(Source[i]) of
  1329. $0..$7f:
  1330. inc(j);
  1331. $80..$7ff:
  1332. inc(j,2);
  1333. else
  1334. inc(j,3);
  1335. end;
  1336. end;
  1337. end;
  1338. result:=j+1;
  1339. end;
  1340. function Utf8ToUnicode(Dest: PWideChar; Source: PChar; MaxChars: SizeInt): SizeInt;{$ifdef SYSTEMINLINE}inline;{$endif}
  1341. begin
  1342. if assigned(Source) then
  1343. Result:=Utf8ToUnicode(Dest,MaxChars,Source,strlen(Source))
  1344. else
  1345. Result:=0;
  1346. end;
  1347. function Utf8ToUnicode(Dest: PWideChar; MaxDestChars: SizeUInt; Source: PChar; SourceBytes: SizeUInt): SizeUInt;
  1348. var
  1349. i,j : SizeUInt;
  1350. w: SizeUInt;
  1351. b : byte;
  1352. begin
  1353. if not assigned(Source) then
  1354. begin
  1355. result:=0;
  1356. exit;
  1357. end;
  1358. result:=SizeUInt(-1);
  1359. i:=0;
  1360. j:=0;
  1361. if assigned(Dest) then
  1362. begin
  1363. while (j<MaxDestChars) and (i<SourceBytes) do
  1364. begin
  1365. b:=byte(Source[i]);
  1366. w:=b;
  1367. inc(i);
  1368. // 2 or 3 bytes?
  1369. if b>=$80 then
  1370. begin
  1371. w:=b and $3f;
  1372. if i>=SourceBytes then
  1373. exit;
  1374. // 3 bytes?
  1375. if (b and $20)<>0 then
  1376. begin
  1377. b:=byte(Source[i]);
  1378. inc(i);
  1379. if i>=SourceBytes then
  1380. exit;
  1381. if (b and $c0)<>$80 then
  1382. exit;
  1383. w:=(w shl 6) or (b and $3f);
  1384. end;
  1385. b:=byte(Source[i]);
  1386. w:=(w shl 6) or (b and $3f);
  1387. if (b and $c0)<>$80 then
  1388. exit;
  1389. inc(i);
  1390. end;
  1391. Dest[j]:=WideChar(w);
  1392. inc(j);
  1393. end;
  1394. if j>=MaxDestChars then j:=MaxDestChars-1;
  1395. Dest[j]:=#0;
  1396. end
  1397. else
  1398. begin
  1399. while i<SourceBytes do
  1400. begin
  1401. b:=byte(Source[i]);
  1402. inc(i);
  1403. // 2 or 3 bytes?
  1404. if b>=$80 then
  1405. begin
  1406. if i>=SourceBytes then
  1407. exit;
  1408. // 3 bytes?
  1409. b := b and $3f;
  1410. if (b and $20)<>0 then
  1411. begin
  1412. b:=byte(Source[i]);
  1413. inc(i);
  1414. if i>=SourceBytes then
  1415. exit;
  1416. if (b and $c0)<>$80 then
  1417. exit;
  1418. end;
  1419. if (byte(Source[i]) and $c0)<>$80 then
  1420. exit;
  1421. inc(i);
  1422. end;
  1423. inc(j);
  1424. end;
  1425. end;
  1426. result:=j+1;
  1427. end;
  1428. function UTF8Encode(const s : WideString) : UTF8String;
  1429. var
  1430. i : SizeInt;
  1431. hs : UTF8String;
  1432. begin
  1433. result:='';
  1434. if s='' then
  1435. exit;
  1436. SetLength(hs,length(s)*3);
  1437. i:=UnicodeToUtf8(pchar(hs),length(hs)+1,PWideChar(s),length(s));
  1438. if i>0 then
  1439. begin
  1440. SetLength(hs,i-1);
  1441. result:=hs;
  1442. end;
  1443. end;
  1444. function UTF8Decode(const s : UTF8String): WideString;
  1445. var
  1446. i : SizeInt;
  1447. hs : WideString;
  1448. begin
  1449. result:='';
  1450. if s='' then
  1451. exit;
  1452. SetLength(hs,length(s));
  1453. i:=Utf8ToUnicode(PWideChar(hs),length(hs)+1,pchar(s),length(s));
  1454. if i>0 then
  1455. begin
  1456. SetLength(hs,i-1);
  1457. result:=hs;
  1458. end;
  1459. end;
  1460. function AnsiToUtf8(const s : ansistring): UTF8String;{$ifdef SYSTEMINLINE}inline;{$endif}
  1461. begin
  1462. Result:=Utf8Encode(s);
  1463. end;
  1464. function Utf8ToAnsi(const s : UTF8String) : ansistring;{$ifdef SYSTEMINLINE}inline;{$endif}
  1465. begin
  1466. Result:=Utf8Decode(s);
  1467. end;
  1468. function WideStringToUCS4String(const s : WideString) : UCS4String;
  1469. var
  1470. i : SizeInt;
  1471. begin
  1472. setlength(result,length(s)+1);
  1473. for i:=1 to length(s) do
  1474. result[i-1]:=UCS4Char(s[i]);
  1475. result[length(s)]:=UCS4Char(0);
  1476. end;
  1477. function UCS4StringToWideString(const s : UCS4String) : WideString;
  1478. var
  1479. i : SizeInt;
  1480. begin
  1481. setlength(result,length(s)-1);
  1482. for i:=1 to length(s)-1 do
  1483. result[i]:=WideChar(s[i-1]);
  1484. end;
  1485. procedure unimplementedwidestring;
  1486. begin
  1487. HandleErrorFrame(215,get_frame);
  1488. end;
  1489. {$warnings off}
  1490. function GenericWideCase(const s : WideString) : WideString;
  1491. begin
  1492. unimplementedwidestring;
  1493. end;
  1494. function CompareWideString(const s1, s2 : WideString) : PtrInt;
  1495. begin
  1496. unimplementedwidestring;
  1497. end;
  1498. function CompareTextWideString(const s1, s2 : WideString): PtrInt;
  1499. begin
  1500. unimplementedwidestring;
  1501. end;
  1502. function CharLengthPChar(const Str: PChar): PtrInt;
  1503. begin
  1504. unimplementedwidestring;
  1505. end;
  1506. {$warnings on}
  1507. procedure initwidestringmanager;
  1508. begin
  1509. fillchar(widestringmanager,sizeof(widestringmanager),0);
  1510. {$ifndef HAS_WIDESTRINGMANAGER}
  1511. widestringmanager.Wide2AnsiMoveProc:=@defaultWide2AnsiMove;
  1512. widestringmanager.Ansi2WideMoveProc:=@defaultAnsi2WideMove;
  1513. widestringmanager.UpperWideStringProc:=@GenericWideCase;
  1514. widestringmanager.LowerWideStringProc:=@GenericWideCase;
  1515. {$endif HAS_WIDESTRINGMANAGER}
  1516. widestringmanager.CompareWideStringProc:=@CompareWideString;
  1517. widestringmanager.CompareTextWideStringProc:=@CompareTextWideString;
  1518. widestringmanager.CharLengthPCharProc:=@CharLengthPChar;
  1519. end;