wstrings.inc 32 KB

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