wstrings.inc 41 KB

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