wstrings.inc 39 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523
  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. GetMem(P,Len*sizeof(WideChar)+WideRecLen);
  122. If P<>Nil then
  123. begin
  124. PWideRec(P)^.Len:=0; { Initial length }
  125. PWideRec(P)^.Ref:=1; { Set reference count }
  126. PWideRec(P)^.First:=#0; { Terminating #0 }
  127. inc(p,WideFirstOff); { Points to string now }
  128. end;
  129. NewWideString:=P;
  130. end;
  131. Procedure DisposeWideString(Var S : Pointer);
  132. {
  133. Deallocates a WideString From the heap.
  134. }
  135. begin
  136. If S=Nil then
  137. exit;
  138. Dec (S,WideFirstOff);
  139. FreeMem (S);
  140. S:=Nil;
  141. end;
  142. Procedure fpc_WideStr_Decr_Ref (Var S : Pointer);{$ifndef NOSAVEREGISTERS}saveregisters;{$endif}[Public,Alias:'FPC_WIDESTR_DECR_REF']; {$ifdef hascompilerproc} compilerproc; {$endif}
  143. {
  144. Decreases the ReferenceCount of a non constant widestring;
  145. If the reference count is zero, deallocate the string;
  146. }
  147. Type
  148. pSizeInt = ^SizeInt;
  149. Var
  150. l : pSizeInt;
  151. Begin
  152. { Zero string }
  153. If S=Nil then exit;
  154. { check for constant strings ...}
  155. l:=@PWIDEREC(S-WideFirstOff)^.Ref;
  156. If l^<0 then exit;
  157. { declocked does a MT safe dec and returns true, if the counter is 0 }
  158. If declocked(l^) then
  159. { Ref count dropped to zero }
  160. DisposeWideString (S); { Remove...}
  161. {$ifndef decrrefnotnil}
  162. s:=nil;
  163. {$endif}
  164. end;
  165. {$ifdef hascompilerproc}
  166. { alias for internal use }
  167. Procedure fpc_WideStr_Decr_Ref (Var S : Pointer);{$ifndef NOSAVEREGISTERS}saveregisters;{$endif}[external name 'FPC_WIDESTR_DECR_REF'];
  168. {$endif compilerproc}
  169. {$ifdef hascompilerproc}
  170. Procedure fpc_WideStr_Incr_Ref (S : Pointer);{$ifndef NOSAVEREGISTERS}saveregisters;{$endif}[Public,Alias:'FPC_WIDESTR_INCR_REF']; {$ifdef hascompilerproc} compilerproc; {$endif}
  171. {$else}
  172. Procedure fpc_WideStr_Incr_Ref (Var S : Pointer);{$ifndef NOSAVEREGISTERS}saveregisters;{$endif}[Public,Alias:'FPC_WIDESTR_INCR_REF'];
  173. {$endif compilerproc}
  174. Begin
  175. If S=Nil then
  176. exit;
  177. { Let's be paranoid : Constant string ??}
  178. If PWideRec(S-WideFirstOff)^.Ref<0 then exit;
  179. inclocked(PWideRec(S-WideFirstOff)^.Ref);
  180. end;
  181. {$ifdef hascompilerproc}
  182. { alias for internal use }
  183. Procedure fpc_WideStr_Incr_Ref (S : Pointer);{$ifndef NOSAVEREGISTERS}saveregisters;{$endif}[external name 'FPC_WIDESTR_INCR_REF'];
  184. {$endif compilerproc}
  185. function fpc_WideStr_To_ShortStr (high_of_res: SizeInt;const S2 : WideString): shortstring;[Public, alias: 'FPC_WIDESTR_TO_SHORTSTR']; {$ifdef hascompilerproc} compilerproc; {$endif}
  186. {
  187. Converts a WideString to a ShortString;
  188. }
  189. Var
  190. Size : SizeInt;
  191. temp : ansistring;
  192. begin
  193. if S2='' then
  194. fpc_WideStr_To_ShortStr:=''
  195. else
  196. begin
  197. Size:=Length(S2);
  198. If Size>high_of_res then
  199. Size:=high_of_res;
  200. widestringmanager.Wide2AnsiMoveProc(PWideChar(S2),temp,Size);
  201. fpc_WideStr_To_ShortStr:=temp;
  202. end;
  203. end;
  204. Function fpc_ShortStr_To_WideStr (Const S2 : ShortString): WideString;{$ifdef hascompilerproc} compilerproc; {$endif}
  205. {
  206. Converts a ShortString to a WideString;
  207. }
  208. Var
  209. Size : SizeInt;
  210. begin
  211. Size:=Length(S2);
  212. //Setlength (fpc_ShortStr_To_WideStr,Size);
  213. if Size>0 then
  214. begin
  215. widestringmanager.Ansi2WideMoveProc(PChar(@S2[1]),fpc_ShortStr_To_WideStr,Size);
  216. { Terminating Zero }
  217. PWideChar(Pointer(fpc_ShortStr_To_WideStr)+Size*sizeof(WideChar))^:=#0;
  218. end;
  219. end;
  220. { old style helper }
  221. {$ifndef hascompilerproc}
  222. Procedure fpc_ShortStr_To_WideStr (Var S1 : Pointer; Const S2 : ShortString);[Public, alias: 'FPC_SHORTSTR_TO_WIDESTR'];
  223. begin
  224. s1 := pointer(fpc_ShortStr_To_WideStr(s2));
  225. end;
  226. {$endif hascompilerproc}
  227. Function fpc_WideStr_To_AnsiStr (const S2 : WideString): AnsiString; {$ifdef hascompilerproc} compilerproc; {$endif}
  228. {
  229. Converts a WideString to an AnsiString
  230. }
  231. Var
  232. Size : SizeInt;
  233. begin
  234. if s2='' then
  235. exit;
  236. Size:=Length(WideString(S2));
  237. // Setlength (fpc_WideStr_To_AnsiStr,Size);
  238. if Size>0 then
  239. begin
  240. widestringmanager.Wide2AnsiMoveProc(PWideChar(Pointer(S2)),fpc_WideStr_To_AnsiStr,Size);
  241. { Terminating Zero }
  242. // PChar(Pointer(fpc_WideStr_To_AnsiStr)+Size)^:=#0;
  243. end;
  244. end;
  245. { old style helper }
  246. {$ifndef hascompilerproc}
  247. Procedure fpc_WideStr_To_AnsiStr (Var S1 : Pointer;const S2 : WideString);[Public, alias: 'FPC_WIDESTR_TO_ANSISTR'];
  248. begin
  249. s1 := pointer(fpc_WideStr_To_AnsiStr(s2));
  250. end;
  251. {$endif hascompilerproc}
  252. Function fpc_AnsiStr_To_WideStr (Const S2 : AnsiString): WideString; {$ifdef hascompilerproc} compilerproc; {$endif}
  253. {
  254. Converts an AnsiString to a WideString;
  255. }
  256. Var
  257. Size : SizeInt;
  258. begin
  259. if s2='' then
  260. exit;
  261. Size:=Length(S2);
  262. // Setlength (result,Size);
  263. if Size>0 then
  264. begin
  265. widestringmanager.Ansi2WideMoveProc(PChar(S2),result,Size);
  266. { Terminating Zero }
  267. // PWideChar(Pointer(result)+Size*sizeof(WideChar))^:=#0;
  268. end;
  269. end;
  270. { compilers with widestrings should have compiler procs }
  271. Function fpc_PWideChar_To_AnsiStr(const p : pwidechar): ansistring; compilerproc;
  272. var
  273. Size : SizeInt;
  274. begin
  275. if p=nil then
  276. exit;
  277. Size := IndexWord(p^, -1, 0);
  278. // Setlength (result,Size);
  279. if Size>0 then
  280. begin
  281. widestringmanager.Wide2AnsiMoveProc(P,result,Size);
  282. { Terminating Zero }
  283. // PChar(Pointer(result)+Size)^:=#0;
  284. end;
  285. end;
  286. Function fpc_PWideChar_To_WideStr(const p : pwidechar): widestring; compilerproc;
  287. var
  288. Size : SizeInt;
  289. begin
  290. if p=nil then
  291. exit;
  292. Size := IndexWord(p^, -1, 0);
  293. Setlength (result,Size);
  294. if Size>0 then
  295. begin
  296. Move(p^,PWideChar(Pointer(result))^,Size*sizeof(WideChar));
  297. { Terminating Zero }
  298. PWideChar(Pointer(result)+Size*sizeof(WideChar))^:=#0;
  299. end;
  300. end;
  301. Function fpc_PWideChar_To_ShortStr(const p : pwidechar): shortstring; compilerproc;
  302. var
  303. Size : SizeInt;
  304. temp: ansistring;
  305. begin
  306. if p=nil then
  307. begin
  308. fpc_PWideChar_To_ShortStr:='';
  309. exit;
  310. end;
  311. Size := IndexWord(p^, $7fffffff, 0);
  312. // Setlength (result,Size+1);
  313. if Size>0 then
  314. begin
  315. // If Size>255 then
  316. // Size:=255;
  317. widestringmanager.Wide2AnsiMoveProc(p,temp,Size);
  318. // byte(result[0]):=byte(Size);
  319. end;
  320. result := temp
  321. end;
  322. { old style helper }
  323. {$ifndef hascompilerproc}
  324. Procedure fpc_AnsiStr_To_WideStr (Var S1 : Pointer; Const S2 : AnsiString);[Public, alias: 'FPC_ANSISTR_TO_WIDESTR'];
  325. begin
  326. s1 := pointer(fpc_AnsiStr_To_WideStr(s2));
  327. end;
  328. {$endif hascompilerproc}
  329. { checked against the ansistring routine, 2001-05-27 (FK) }
  330. Procedure fpc_WideStr_Assign (Var S1 : Pointer;S2 : Pointer);[Public,Alias:'FPC_WIDESTR_ASSIGN']; {$ifdef hascompilerproc} compilerproc; {$endif}
  331. {
  332. Assigns S2 to S1 (S1:=S2), taking in account reference counts.
  333. }
  334. begin
  335. If S2<>nil then
  336. If PWideRec(S2-WideFirstOff)^.Ref>0 then
  337. Inc(PWideRec(S2-WideFirstOff)^.ref);
  338. { Decrease the reference count on the old S1 }
  339. fpc_widestr_decr_ref (S1);
  340. { And finally, have S1 pointing to S2 (or its copy) }
  341. S1:=S2;
  342. end;
  343. {$ifdef hascompilerproc}
  344. { alias for internal use }
  345. Procedure fpc_WideStr_Assign (Var S1 : Pointer;S2 : Pointer);[external name 'FPC_WIDESTR_ASSIGN'];
  346. {$endif hascompilerproc}
  347. { checked against the ansistring routine, 2001-05-27 (FK) }
  348. {$ifdef hascompilerproc}
  349. function fpc_WideStr_Concat (const S1,S2 : WideString): WideString; compilerproc;
  350. var
  351. S3: WideString absolute result;
  352. {$else hascompilerproc}
  353. Procedure fpc_WideStr_Concat (S1,S2 : WideString;var S3 : WideString);[Public, alias: 'FPC_WIDESTR_CONCAT'];
  354. {$endif hascompilerproc}
  355. {
  356. Concatenates 2 WideStrings : S1+S2.
  357. Result Goes to S3;
  358. }
  359. Var
  360. Size,Location : SizeInt;
  361. begin
  362. { only assign if s1 or s2 is empty }
  363. if (S1='') then
  364. S3 := S2
  365. else
  366. if (S2='') then
  367. S3 := S1
  368. else
  369. begin
  370. { create new result }
  371. Size:=Length(S2);
  372. Location:=Length(S1);
  373. SetLength (S3,Size+Location);
  374. Move (S1[1],S3[1],Location*sizeof(WideChar));
  375. Move (S2[1],S3[location+1],(Size+1)*sizeof(WideChar));
  376. end;
  377. end;
  378. Function fpc_Char_To_WideStr(const c : WideChar): WideString; {$ifdef hascompilerproc} compilerproc; {$endif}
  379. {
  380. Converts a Char to a WideString;
  381. }
  382. begin
  383. if c = #0 then
  384. { result is automatically set to '' }
  385. exit;
  386. Setlength (fpc_Char_To_WideStr,1);
  387. fpc_Char_To_WideStr[1]:=c;
  388. { Terminating Zero }
  389. PWideChar(Pointer(fpc_Char_To_WideStr)+sizeof(WideChar))^:=#0;
  390. end;
  391. { old style helper }
  392. {$ifndef hascompilerproc}
  393. Procedure fpc_Char_To_WideStr(var S1 : Pointer; c : WideChar);[Public, alias: 'FPC_CHAR_TO_WIDESTR'];
  394. begin
  395. s1 := pointer(fpc_Char_To_WideStr(c));
  396. end;
  397. {$endif hascompilerproc}
  398. Function fpc_PChar_To_WideStr(const p : pchar): WideString; {$ifdef hascompilerproc} compilerproc; {$endif}
  399. Var
  400. L : SizeInt;
  401. begin
  402. if (not assigned(p)) or (p[0]=#0) Then
  403. { result is automatically set to '' }
  404. exit;
  405. l:=IndexChar(p^,-1,#0);
  406. //SetLength(fpc_PChar_To_WideStr,L);
  407. widestringmanager.Ansi2WideMoveProc(P,fpc_PChar_To_WideStr,l);
  408. end;
  409. { old style helper }
  410. {$ifndef hascompilerproc}
  411. Procedure fpc_PChar_To_WideStr(var a : WideString;p : pchar);[Public,Alias : 'FPC_PCHAR_TO_WIDESTR']; {$ifdef hascompilerproc} compilerproc; {$endif}
  412. begin
  413. pointer(a) := pointer(fpc_PChar_To_WideStr(p));
  414. end;
  415. {$endif hascompilerproc}
  416. Function fpc_CharArray_To_WideStr(const arr: array of char): WideString; {$ifdef hascompilerproc} compilerproc; {$endif}
  417. var
  418. i : SizeInt;
  419. begin
  420. if arr[0]=#0 Then
  421. { result is automatically set to '' }
  422. exit;
  423. i:=IndexChar(arr,high(arr)+1,#0);
  424. if i = -1 then
  425. i := high(arr)+1;
  426. SetLength(fpc_CharArray_To_WideStr,i);
  427. widestringmanager.Ansi2WideMoveProc (pchar(@arr),fpc_CharArray_To_WideStr,i);
  428. end;
  429. { old style helper }
  430. {$ifndef hascompilerproc}
  431. Procedure fpc_CharArray_To_WideStr(var a : WideString; p: pointer; len: SizeInt); [Public,Alias : 'FPC_CHARARRAY_TO_WIDESTR']; {$ifdef hascompilerproc} compilerproc; {$endif}
  432. var
  433. src: pchar;
  434. i: SizeInt;
  435. begin
  436. src := pchar(p);
  437. if src[0]=#0 Then
  438. begin
  439. pointer(a) := nil;
  440. exit;
  441. end;
  442. i:=IndexChar(src^,len,#0);
  443. if i = -1 then
  444. i := len;
  445. pointer(a) := NewWideString(i);
  446. widestringmanager.Ansi2WideMoveProc (src,a,i);
  447. end;
  448. {$endif not hascompilerproc}
  449. {$ifdef hascompilerproc}
  450. function fpc_WideCharArray_To_ShortStr(const arr: array of widechar): shortstring;[public,alias:'FPC_WIDECHARARRAY_TO_SHORTSTR']; compilerproc;
  451. var
  452. l: longint;
  453. {$else hascompilerproc}
  454. function fpc_WideCharArray_To_ShortStr(arr:pwidechar; l : longint):shortstring;[public,alias:'FPC_WIDECHARARRAY_TO_SHORTSTR'];
  455. var
  456. {$endif hascompilerproc}
  457. index: longint;
  458. len: byte;
  459. temp: ansistring;
  460. begin
  461. {$ifdef hascompilerproc}
  462. l := high(arr)+1;
  463. {$endif hascompilerproc}
  464. if l>=256 then
  465. l:=255
  466. else if l<0 then
  467. l:=0;
  468. index:=IndexWord(arr[0],l,0);
  469. if (index < 0) then
  470. len := l
  471. else
  472. len := index;
  473. {$ifdef hascompilerproc}
  474. widestringmanager.Wide2AnsiMoveProc (pwidechar(@arr),temp,len);
  475. {$else}
  476. widestringmanager.Wide2AnsiMoveProc (arr, temp,len);
  477. {$endif}
  478. fpc_WideCharArray_To_ShortStr := temp;
  479. //fpc_WideCharArray_To_ShortStr[0]:=chr(len);
  480. end;
  481. Function fpc_WideCharArray_To_AnsiStr(const arr: array of widechar): AnsiString; {$ifdef hascompilerproc} compilerproc; {$endif}
  482. var
  483. i : SizeInt;
  484. begin
  485. if arr[0]=#0 Then
  486. { result is automatically set to '' }
  487. exit;
  488. i:=IndexWord(arr,high(arr)+1,0);
  489. if i = -1 then
  490. i := high(arr)+1;
  491. SetLength(fpc_WideCharArray_To_AnsiStr,i);
  492. widestringmanager.Wide2AnsiMoveProc (pwidechar(@arr),fpc_WideCharArray_To_AnsiStr,i);
  493. end;
  494. { old style helper }
  495. {$ifndef hascompilerproc}
  496. Procedure fpc_WideCharArray_To_AnsiStr(var a : AnsiString; p: pointer; len: SizeInt); [Public,Alias : 'FPC_WIDECHARARRAY_TO_ANSISTR']; {$ifdef hascompilerproc} compilerproc; {$endif}
  497. var
  498. src: pwidechar;
  499. i: SizeInt;
  500. begin
  501. src := pwidechar(p);
  502. if src[0]=#0 Then
  503. begin
  504. pointer(a) := nil;
  505. exit;
  506. end;
  507. i:=IndexWord(src^,len,0);
  508. if i = -1 then
  509. i := len;
  510. pointer(a) := NewAnsiString(i);
  511. widestringmanager.Wide2AnsiMoveProc (src,a,i);
  512. end;
  513. {$endif not hascompilerproc}
  514. Function fpc_WideCharArray_To_WideStr(const arr: array of widechar): WideString; {$ifdef hascompilerproc} compilerproc; {$endif}
  515. var
  516. i : SizeInt;
  517. begin
  518. if arr[0]=#0 Then
  519. { result is automatically set to '' }
  520. exit;
  521. i:=IndexWord(arr,high(arr)+1,0);
  522. if i = -1 then
  523. i := high(arr)+1;
  524. SetLength(fpc_WideCharArray_To_WideStr,i);
  525. Move(pwidechar(@arr)^, PWideChar(Pointer(@fpc_WideCharArray_To_WideStr[1]))^,i*sizeof(WideChar));
  526. { Terminating Zero }
  527. PWideChar(Pointer(@fpc_WideCharArray_To_WideStr[1])+i*sizeof(WideChar))^:=#0;
  528. end;
  529. { old style helper }
  530. {$ifndef hascompilerproc}
  531. Procedure fpc_WideCharArray_To_WideStr(var a : WideString; p: pointer; len: SizeInt); [Public,Alias : 'FPC_WIDECHARARRAY_TO_WIDESTR']; {$ifdef hascompilerproc} compilerproc; {$endif}
  532. var
  533. src: pwidechar;
  534. i: SizeInt;
  535. begin
  536. src := pwidechar(p);
  537. if src[0]=#0 Then
  538. begin
  539. pointer(a) := nil;
  540. exit;
  541. end;
  542. i:=IndexWord(src^,len,#0);
  543. if i = -1 then
  544. i := len;
  545. pointer(a) := NewWideString(i);
  546. Move(p^, PWideChar(Pointer(@a[1]))^,i*sizeof(WideChar));
  547. { Terminating Zero }
  548. PWideChar(Pointer(@a[1])+i*sizeof(WideChar))^:=#0;
  549. end;
  550. {$endif not hascompilerproc}
  551. {$ifdef hascompilerproc}
  552. { inside the compiler, the resulttype is modified to that of the actual }
  553. { chararray we're converting to (JM) }
  554. function fpc_widestr_to_chararray(arraysize: SizeInt; const src: WideString): fpc_big_chararray;[public,alias: 'FPC_WIDESTR_TO_CHARARRAY']; compilerproc;
  555. var
  556. len: SizeInt;
  557. temp: ansistring;
  558. begin
  559. len := length(src);
  560. { make sure we don't dereference src if it can be nil (JM) }
  561. if len > 0 then
  562. widestringmanager.wide2ansimoveproc(pwidechar(@src[1]),temp,len);
  563. len := length(temp);
  564. if len > arraysize then
  565. len := arraysize;
  566. move(temp[1],fpc_widestr_to_chararray[0],len);
  567. fillchar(fpc_widestr_to_chararray[len],arraysize-len,0);
  568. end;
  569. {$endif hascompilerproc}
  570. {$ifdef hascompilerproc}
  571. { inside the compiler, the resulttype is modified to that of the actual }
  572. { widechararray we're converting to (JM) }
  573. function fpc_widestr_to_widechararray(arraysize: SizeInt; const src: WideString): fpc_big_widechararray;[public,alias: 'FPC_WIDESTR_TO_WIDECHARARRAY']; compilerproc;
  574. var
  575. len: SizeInt;
  576. begin
  577. len := length(src);
  578. if len > arraysize then
  579. len := arraysize;
  580. { make sure we don't try to access element 1 of the ansistring if it's nil }
  581. if len > 0 then
  582. move(src[1],fpc_widestr_to_widechararray[0],len*SizeOf(WideChar));
  583. fillchar(fpc_widestr_to_widechararray[len],(arraysize-len)*SizeOf(WideChar),0);
  584. end;
  585. {$endif hascompilerproc}
  586. {$ifdef hascompilerproc}
  587. { inside the compiler, the resulttype is modified to that of the actual }
  588. { chararray we're converting to (JM) }
  589. function fpc_ansistr_to_widechararray(arraysize: SizeInt; const src: AnsiString): fpc_big_widechararray;[public,alias: 'FPC_ANSISTR_TO_WIDECHARARRAY']; compilerproc;
  590. var
  591. len: SizeInt;
  592. temp: widestring;
  593. begin
  594. len := length(src);
  595. { make sure we don't dereference src if it can be nil (JM) }
  596. if len > 0 then
  597. widestringmanager.ansi2widemoveproc(pchar(@src[1]),temp,len);
  598. len := length(temp);
  599. if len > arraysize then
  600. len := arraysize;
  601. move(temp[1],fpc_ansistr_to_widechararray[0],len*sizeof(widechar));
  602. fillchar(fpc_ansistr_to_widechararray[len],(arraysize-len)*SizeOf(WideChar),0);
  603. end;
  604. {$endif hascompilerproc}
  605. {$ifdef hascompilerproc}
  606. function fpc_shortstr_to_widechararray(arraysize: SizeInt; const src: ShortString): fpc_big_widechararray;[public,alias: 'FPC_SHORTSTR_TO_WIDECHARARRAY']; compilerproc;
  607. var
  608. len: longint;
  609. temp : widestring;
  610. begin
  611. len := length(src);
  612. { make sure we don't access char 1 if length is 0 (JM) }
  613. if len > 0 then
  614. widestringmanager.ansi2widemoveproc(pchar(@src[1]),temp,len);
  615. len := length(temp);
  616. if len > arraysize then
  617. len := arraysize;
  618. move(temp[1],fpc_shortstr_to_widechararray[0],len*sizeof(widechar));
  619. fillchar(fpc_shortstr_to_widechararray[len],(arraysize-len)*SizeOf(WideChar),0);
  620. end;
  621. {$endif hascompilerproc}
  622. Function fpc_WideStr_Compare(const S1,S2 : WideString): SizeInt;[Public,Alias : 'FPC_WIDESTR_COMPARE']; {$ifdef hascompilerproc} compilerproc; {$endif}
  623. {
  624. Compares 2 WideStrings;
  625. The result is
  626. <0 if S1<S2
  627. 0 if S1=S2
  628. >0 if S1>S2
  629. }
  630. Var
  631. MaxI,Temp : SizeInt;
  632. begin
  633. if pointer(S1)=pointer(S2) then
  634. begin
  635. fpc_WideStr_Compare:=0;
  636. exit;
  637. end;
  638. Maxi:=Length(S1);
  639. temp:=Length(S2);
  640. If MaxI>Temp then
  641. MaxI:=Temp;
  642. Temp:=CompareWord(S1[1],S2[1],MaxI);
  643. if temp=0 then
  644. temp:=Length(S1)-Length(S2);
  645. fpc_WideStr_Compare:=Temp;
  646. end;
  647. Procedure fpc_WideStr_CheckZero(p : pointer);[Public,Alias : 'FPC_WIDESTR_CHECKZERO']; {$ifdef hascompilerproc} compilerproc; {$endif}
  648. begin
  649. if p=nil then
  650. HandleErrorFrame(201,get_frame);
  651. end;
  652. Procedure fpc_WideStr_CheckRange(len,index : SizeInt);[Public,Alias : 'FPC_WIDESTR_RANGECHECK']; {$ifdef hascompilerproc} compilerproc; {$endif}
  653. begin
  654. if (index>len) or (Index<1) then
  655. HandleErrorFrame(201,get_frame);
  656. end;
  657. {$ifndef INTERNSETLENGTH}
  658. Procedure SetLength (Var S : WideString; l : SizeInt);
  659. {$else INTERNSETLENGTH}
  660. Procedure fpc_WideStr_SetLength (Var S : WideString; l : SizeInt);[Public,Alias : 'FPC_WIDESTR_SETLENGTH']; {$ifdef hascompilerproc} compilerproc; {$endif}
  661. {$endif INTERNSETLENGTH}
  662. {
  663. Sets The length of string S to L.
  664. Makes sure S is unique, and contains enough room.
  665. }
  666. Var
  667. Temp : Pointer;
  668. movelen: SizeInt;
  669. begin
  670. if (l>0) then
  671. begin
  672. if Pointer(S)=nil then
  673. begin
  674. { Need a complete new string...}
  675. Pointer(s):=NewWideString(l);
  676. end
  677. else if (PWideRec(Pointer(S)-WideFirstOff)^.Ref = 1) then
  678. begin
  679. Dec(Pointer(S),WideFirstOff);
  680. if L*sizeof(WideChar)+WideRecLen>MemSize(Pointer(S)) then
  681. reallocmem(pointer(S), L*sizeof(WideChar)+WideRecLen);
  682. Inc(Pointer(S), WideFirstOff);
  683. end
  684. else
  685. begin
  686. { Reallocation is needed... }
  687. Temp:=Pointer(NewWideString(L));
  688. if Length(S)>0 then
  689. begin
  690. if l < succ(length(s)) then
  691. movelen := l
  692. { also move terminating null }
  693. else movelen := succ(length(s));
  694. Move(Pointer(S)^,Temp^,movelen * Sizeof(WideChar));
  695. end;
  696. fpc_widestr_decr_ref(Pointer(S));
  697. Pointer(S):=Temp;
  698. end;
  699. { Force nil termination in case it gets shorter }
  700. PWord(Pointer(S)+l*sizeof(WideChar))^:=0;
  701. PWideRec(Pointer(S)-FirstOff)^.Len:=l;
  702. end
  703. else
  704. begin
  705. { Length=0 }
  706. if Pointer(S)<>nil then
  707. fpc_widestr_decr_ref (Pointer(S));
  708. Pointer(S):=Nil;
  709. end;
  710. end;
  711. {*****************************************************************************
  712. Public functions, In interface.
  713. *****************************************************************************}
  714. function WideCharToString(S : PWideChar) : AnsiString;
  715. begin
  716. result:=WideCharLenToString(s,Length(WideString(s)));
  717. end;
  718. function StringToWideChar(const Src : AnsiString;Dest : PWideChar;DestSize : SizeInt) : PWideChar;
  719. var
  720. temp:widestring;
  721. begin
  722. widestringmanager.Ansi2WideMoveProc(PChar(Src),temp,Length(Src));
  723. if Length(temp)<DestSize then
  724. move(temp[1],Dest^,Length(temp))
  725. else
  726. move(temp[1],Dest^,destsize);
  727. result:=Dest;
  728. end;
  729. function WideCharLenToString(S : PWideChar;Len : SizeInt) : AnsiString;
  730. begin
  731. //SetLength(result,Len);
  732. widestringmanager.Wide2AnsiMoveproc(S,result,Len);
  733. end;
  734. procedure WideCharLenToStrVar(Src : PWideChar;Len : SizeInt;var Dest : AnsiString);
  735. begin
  736. Dest:=WideCharLenToString(Src,Len);
  737. end;
  738. procedure WideCharToStrVar(S : PWideChar;var Dest : AnsiString);
  739. begin
  740. Dest:=WideCharToString(S);
  741. end;
  742. {$ifndef INTERNLENGTH}
  743. Function Length (Const S : WideString) : SizeInt;
  744. {
  745. Returns the length of an WideString.
  746. Takes in acount that zero strings are NIL;
  747. }
  748. begin
  749. If Pointer(S)=Nil then
  750. Length:=0
  751. else
  752. Length:=PWideRec(Pointer(S)-WideFirstOff)^.Len;
  753. end;
  754. {$endif INTERNLENGTH}
  755. Function fpc_widestr_Unique(Var S : Pointer): Pointer; [Public,Alias : 'FPC_WIDESTR_UNIQUE']; {$ifdef hascompilerproc} compilerproc; {$endif}
  756. {
  757. Make sure reference count of S is 1,
  758. using copy-on-write semantics.
  759. }
  760. Var
  761. SNew : Pointer;
  762. L : SizeInt;
  763. begin
  764. pointer(result) := pointer(s);
  765. If Pointer(S)=Nil then
  766. exit;
  767. if PWideRec(Pointer(S)-WideFirstOff)^.Ref<>1 then
  768. begin
  769. L:=PWideRec(Pointer(S)-WideFirstOff)^.len;
  770. SNew:=NewWideString (L);
  771. Move (PWideChar(S)^,SNew^,(L+1)*sizeof(WideChar));
  772. PWideRec(SNew-WideFirstOff)^.len:=L;
  773. fpc_widestr_decr_ref (Pointer(S)); { Thread safe }
  774. pointer(S):=SNew;
  775. pointer(result):=SNew;
  776. end;
  777. end;
  778. {$ifdef interncopy}
  779. Function Fpc_WideStr_Copy (Const S : WideString; Index,Size : SizeInt) : WideString;compilerproc;
  780. {$else}
  781. Function Copy (Const S : WideString; Index,Size : SizeInt) : WideString;
  782. {$endif}
  783. var
  784. ResultAddress : Pointer;
  785. begin
  786. ResultAddress:=Nil;
  787. dec(index);
  788. if Index < 0 then
  789. Index := 0;
  790. { Check Size. Accounts for Zero-length S, the double check is needed because
  791. Size can be maxint and will get <0 when adding index }
  792. if (Size>Length(S)) or
  793. (Index+Size>Length(S)) then
  794. Size:=Length(S)-Index;
  795. If Size>0 then
  796. begin
  797. If Index<0 Then
  798. Index:=0;
  799. ResultAddress:=Pointer(NewWideString (Size));
  800. if ResultAddress<>Nil then
  801. begin
  802. Move (PWideChar(S)[Index],ResultAddress^,Size*sizeof(WideChar));
  803. PWideRec(ResultAddress-WideFirstOff)^.Len:=Size;
  804. PWideChar(ResultAddress+Size*sizeof(WideChar))^:=#0;
  805. end;
  806. end;
  807. {$ifdef interncopy}
  808. Pointer(fpc_widestr_Copy):=ResultAddress;
  809. {$else}
  810. Pointer(Copy):=ResultAddress;
  811. {$endif}
  812. end;
  813. Function Pos (Const Substr : WideString; Const Source : WideString) : SizeInt;
  814. var
  815. i,MaxLen : SizeInt;
  816. pc : pwidechar;
  817. begin
  818. Pos:=0;
  819. if Length(SubStr)>0 then
  820. begin
  821. MaxLen:=Length(source)-Length(SubStr);
  822. i:=0;
  823. pc:=@source[1];
  824. while (i<=MaxLen) do
  825. begin
  826. inc(i);
  827. if (SubStr[1]=pc^) and
  828. (CompareWord(Substr[1],pc^,Length(SubStr))=0) then
  829. begin
  830. Pos:=i;
  831. exit;
  832. end;
  833. inc(pc);
  834. end;
  835. end;
  836. end;
  837. { Faster version for a widechar alone }
  838. Function Pos (c : WideChar; Const s : WideString) : SizeInt;
  839. var
  840. i: SizeInt;
  841. pc : pwidechar;
  842. begin
  843. pc:=@s[1];
  844. for i:=1 to length(s) do
  845. begin
  846. if pc^=c then
  847. begin
  848. pos:=i;
  849. exit;
  850. end;
  851. inc(pc);
  852. end;
  853. pos:=0;
  854. end;
  855. Function Pos (c : WideChar; Const s : AnsiString) : SizeInt;
  856. var
  857. i: SizeInt;
  858. pc : pchar;
  859. begin
  860. pc:=@s[1];
  861. for i:=1 to length(s) do
  862. begin
  863. if widechar(pc^)=c then
  864. begin
  865. pos:=i;
  866. exit;
  867. end;
  868. inc(pc);
  869. end;
  870. pos:=0;
  871. end;
  872. { Faster version for a char alone. Must be implemented because }
  873. { pos(c: char; const s: shortstring) also exists, so otherwise }
  874. { using pos(char,pchar) will always call the shortstring version }
  875. { (exact match for first argument), also with $h+ (JM) }
  876. Function Pos (c : Char; Const s : WideString) : SizeInt;
  877. var
  878. i: SizeInt;
  879. wc : widechar;
  880. pc : pwidechar;
  881. begin
  882. wc:=c;
  883. pc:=@s[1];
  884. for i:=1 to length(s) do
  885. begin
  886. if pc^=wc then
  887. begin
  888. pos:=i;
  889. exit;
  890. end;
  891. inc(pc);
  892. end;
  893. pos:=0;
  894. end;
  895. Procedure Delete (Var S : WideString; Index,Size: SizeInt);
  896. Var
  897. LS : SizeInt;
  898. begin
  899. If Length(S)=0 then
  900. exit;
  901. if index<=0 then
  902. exit;
  903. LS:=PWideRec(Pointer(S)-WideFirstOff)^.Len;
  904. if (Index<=LS) and (Size>0) then
  905. begin
  906. UniqueString (S);
  907. if Size+Index>LS then
  908. Size:=LS-Index+1;
  909. if Index+Size<=LS then
  910. begin
  911. Dec(Index);
  912. Move(PWideChar(S)[Index+Size],PWideChar(S)[Index],(LS-Index+1)*sizeof(WideChar));
  913. end;
  914. Setlength(s,LS-Size);
  915. end;
  916. end;
  917. Procedure Insert (Const Source : WideString; Var S : WideString; Index : SizeInt);
  918. var
  919. Temp : WideString;
  920. LS : SizeInt;
  921. begin
  922. If Length(Source)=0 then
  923. exit;
  924. if index <= 0 then
  925. index := 1;
  926. Ls:=Length(S);
  927. if index > LS then
  928. index := LS+1;
  929. Dec(Index);
  930. Pointer(Temp) := NewWideString(Length(Source)+LS);
  931. SetLength(Temp,Length(Source)+LS);
  932. If Index>0 then
  933. move (PWideChar(S)^,PWideChar(Temp)^,Index*sizeof(WideChar));
  934. Move (PWideChar(Source)^,PWideChar(Temp)[Index],Length(Source)*sizeof(WideChar));
  935. If (LS-Index)>0 then
  936. Move(PWideChar(S)[Index],PWideChar(temp)[Length(Source)+index],(LS-Index)*sizeof(WideChar));
  937. S:=Temp;
  938. end;
  939. function UpCase(const s : WideString) : WideString;
  940. begin
  941. result:=widestringmanager.UpperWideStringProc(s);
  942. end;
  943. Procedure SetString (Var S : WideString; Buf : PWideChar; Len : SizeInt);
  944. var
  945. BufLen: SizeInt;
  946. begin
  947. SetLength(S,Len);
  948. If (Buf<>Nil) and (Len>0) then
  949. begin
  950. BufLen := IndexWord(Buf^, Len+1, 0);
  951. If (BufLen>0) and (BufLen < Len) then
  952. Len := BufLen;
  953. Move (Buf[0],S[1],Len*sizeof(WideChar));
  954. PWideChar(Pointer(S)+Len*sizeof(WideChar))^:=#0;
  955. end;
  956. end;
  957. Procedure SetString (Var S : WideString; Buf : PChar; Len : SizeInt);
  958. var
  959. BufLen: SizeInt;
  960. begin
  961. SetLength(S,Len);
  962. If (Buf<>Nil) and (Len>0) then
  963. begin
  964. BufLen := IndexByte(Buf^, Len+1, 0);
  965. If (BufLen>0) and (BufLen < Len) then
  966. Len := BufLen;
  967. widestringmanager.Ansi2WideMoveProc(Buf,S,Len);
  968. //PWideChar(Pointer(S)+Len*sizeof(WideChar))^:=#0;
  969. end;
  970. end;
  971. Function fpc_Val_Real_WideStr(Const S : WideString; Var Code : ValSInt): ValReal; [public, alias:'FPC_VAL_REAL_WIDESTR']; {$ifdef hascompilerproc} compilerproc; {$endif}
  972. Var
  973. SS : String;
  974. begin
  975. fpc_Val_Real_WideStr := 0;
  976. if length(S) > 255 then
  977. code := 256
  978. else
  979. begin
  980. SS := S;
  981. Val(SS,fpc_Val_Real_WideStr,code);
  982. end;
  983. end;
  984. Function fpc_Val_UInt_WideStr (Const S : WideString; Var Code : ValSInt): ValUInt; [public, alias:'FPC_VAL_UINT_WIDESTR']; {$ifdef hascompilerproc} compilerproc; {$endif}
  985. Var
  986. SS : ShortString;
  987. begin
  988. fpc_Val_UInt_WideStr := 0;
  989. if length(S) > 255 then
  990. code := 256
  991. else
  992. begin
  993. SS := S;
  994. Val(SS,fpc_Val_UInt_WideStr,code);
  995. end;
  996. end;
  997. Function fpc_Val_SInt_WideStr (DestSize: SizeInt; Const S : WideString; Var Code : ValSInt): ValSInt; [public, alias:'FPC_VAL_SINT_WIDESTR']; {$ifdef hascompilerproc} compilerproc; {$endif}
  998. Var
  999. SS : ShortString;
  1000. begin
  1001. fpc_Val_SInt_WideStr:=0;
  1002. if length(S)>255 then
  1003. code:=256
  1004. else
  1005. begin
  1006. SS := S;
  1007. fpc_Val_SInt_WideStr := int_Val_SInt_ShortStr(DestSize,SS,Code);
  1008. end;
  1009. end;
  1010. {$ifndef CPU64}
  1011. Function fpc_Val_qword_WideStr (Const S : WideString; Var Code : ValSInt): qword; [public, alias:'FPC_VAL_QWORD_WIDESTR']; {$ifdef hascompilerproc} compilerproc; {$endif}
  1012. Var
  1013. SS : ShortString;
  1014. begin
  1015. fpc_Val_qword_WideStr:=0;
  1016. if length(S)>255 then
  1017. code:=256
  1018. else
  1019. begin
  1020. SS := S;
  1021. Val(SS,fpc_Val_qword_WideStr,Code);
  1022. end;
  1023. end;
  1024. Function fpc_Val_int64_WideStr (Const S : WideString; Var Code : ValSInt): Int64; [public, alias:'FPC_VAL_INT64_WIDESTR']; {$ifdef hascompilerproc} compilerproc; {$endif}
  1025. Var
  1026. SS : ShortString;
  1027. begin
  1028. fpc_Val_int64_WideStr:=0;
  1029. if length(S)>255 then
  1030. code:=256
  1031. else
  1032. begin
  1033. SS := S;
  1034. Val(SS,fpc_Val_int64_WideStr,Code);
  1035. end;
  1036. end;
  1037. {$endif CPU64}
  1038. procedure fpc_WideStr_Float(d : ValReal;len,fr,rt : SizeInt;var s : WideString);{$ifdef hascompilerproc} compilerproc; {$endif}
  1039. var
  1040. ss : shortstring;
  1041. begin
  1042. str_real(len,fr,d,treal_type(rt),ss);
  1043. s:=ss;
  1044. end;
  1045. {$ifdef STR_USES_VALINT}
  1046. Procedure fpc_WideStr_SInt(v : ValSint; Len : SizeInt; Var S : WideString);{$ifdef hascompilerproc} compilerproc; {$endif}
  1047. {$else}
  1048. Procedure fpc_WideStr_Longint(v : Longint; Len : SizeInt; Var S : WideString);{$ifdef hascompilerproc} compilerproc; {$endif}
  1049. {$endif}
  1050. Var
  1051. SS : ShortString;
  1052. begin
  1053. Str (v:Len,SS);
  1054. S:=SS;
  1055. end;
  1056. {$ifdef STR_USES_VALINT}
  1057. Procedure fpc_WideStr_UInt(v : ValUInt;Len : SizeInt; Var S : WideString);{$ifdef hascompilerproc} compilerproc; {$endif}
  1058. {$else}
  1059. Procedure fpc_WideStr_Longword(v : Longword;Len : SizeInt; Var S : WideString);{$ifdef hascompilerproc} compilerproc; {$endif}
  1060. {$endif}
  1061. Var
  1062. SS : ShortString;
  1063. begin
  1064. str(v:Len,SS);
  1065. S:=SS;
  1066. end;
  1067. {$ifndef CPU64}
  1068. Procedure fpc_WideStr_Int64(v : Int64; Len : SizeInt; Var S : WideString);{$ifdef hascompilerproc} compilerproc; {$endif}
  1069. Var
  1070. SS : ShortString;
  1071. begin
  1072. Str (v:Len,SS);
  1073. S:=SS;
  1074. end;
  1075. Procedure fpc_WideStr_Qword(v : Qword;Len : SizeInt; Var S : WideString);{$ifdef hascompilerproc} compilerproc; {$endif}
  1076. Var
  1077. SS : ShortString;
  1078. begin
  1079. str(v:Len,SS);
  1080. S:=SS;
  1081. end;
  1082. {$endif CPU64}
  1083. function UnicodeToUtf8(Dest: PChar; Source: PWideChar; MaxBytes: SizeInt): SizeInt;{$ifdef SYSTEMINLINE}inline;{$endif}
  1084. begin
  1085. if assigned(Source) then
  1086. Result:=UnicodeToUtf8(Dest,MaxBytes,Source,IndexWord(Source^,-1,0))
  1087. else
  1088. Result:=0;
  1089. end;
  1090. function UnicodeToUtf8(Dest: PChar; MaxDestBytes: SizeUInt; Source: PWideChar; SourceChars: SizeUInt): SizeUInt;
  1091. var
  1092. i,j : SizeUInt;
  1093. w : word;
  1094. begin
  1095. result:=0;
  1096. if source=nil then
  1097. exit;
  1098. i:=0;
  1099. j:=0;
  1100. if assigned(Dest) then
  1101. begin
  1102. while (i<SourceChars) and (j<MaxDestBytes) do
  1103. begin
  1104. w:=word(Source[i]);
  1105. case w of
  1106. 0..$7f:
  1107. begin
  1108. Dest[j]:=char(w);
  1109. inc(j);
  1110. end;
  1111. $80..$7ff:
  1112. begin
  1113. if j+1>=MaxDestBytes then
  1114. break;
  1115. Dest[j]:=char($c0 or (w shr 6));
  1116. Dest[j+1]:=char($80 or (w and $3f));
  1117. inc(j,2);
  1118. end;
  1119. else
  1120. begin
  1121. if j+2>=MaxDestBytes then
  1122. break;
  1123. Dest[j]:=char($e0 or (w shr 12));
  1124. Dest[j+1]:=char($80 or ((w shr 6)and $3f));
  1125. Dest[j+2]:=char($80 or (w and $3f));
  1126. inc(j,3);
  1127. end;
  1128. end;
  1129. inc(i);
  1130. end;
  1131. if j>MaxDestBytes-1 then
  1132. j:=MaxDestBytes-1;
  1133. Dest[j]:=#0;
  1134. end
  1135. else
  1136. begin
  1137. while i<SourceChars do
  1138. begin
  1139. case word(Source[i]) of
  1140. $0..$7f:
  1141. inc(j);
  1142. $80..$7ff:
  1143. inc(j,2);
  1144. else
  1145. inc(j,3);
  1146. end;
  1147. end;
  1148. end;
  1149. result:=j+1;
  1150. end;
  1151. function Utf8ToUnicode(Dest: PWideChar; Source: PChar; MaxChars: SizeInt): SizeInt;{$ifdef SYSTEMINLINE}inline;{$endif}
  1152. begin
  1153. if assigned(Source) then
  1154. Result:=Utf8ToUnicode(Dest,MaxChars,Source,strlen(Source))
  1155. else
  1156. Result:=0;
  1157. end;
  1158. function Utf8ToUnicode(Dest: PWideChar; MaxDestChars: SizeUInt; Source: PChar; SourceBytes: SizeUInt): SizeUInt;
  1159. var
  1160. i,j : SizeUInt;
  1161. w: SizeUInt;
  1162. b : byte;
  1163. begin
  1164. if not assigned(Source) then
  1165. begin
  1166. result:=0;
  1167. exit;
  1168. end;
  1169. result:=SizeUInt(-1);
  1170. i:=0;
  1171. j:=0;
  1172. if assigned(Dest) then
  1173. begin
  1174. while (j<MaxDestChars) and (i<SourceBytes) do
  1175. begin
  1176. b:=byte(Source[i]);
  1177. w:=b;
  1178. inc(i);
  1179. // 2 or 3 bytes?
  1180. if b>=$80 then
  1181. begin
  1182. w:=b and $3f;
  1183. if i>=SourceBytes then
  1184. exit;
  1185. // 3 bytes?
  1186. if (b and $20)<>0 then
  1187. begin
  1188. b:=byte(Source[i]);
  1189. inc(i);
  1190. if i>=SourceBytes then
  1191. exit;
  1192. if (b and $c0)<>$80 then
  1193. exit;
  1194. w:=(w shl 6) or (b and $3f);
  1195. end;
  1196. b:=byte(Source[i]);
  1197. w:=(w shl 6) or (b and $3f);
  1198. if (b and $c0)<>$80 then
  1199. exit;
  1200. inc(i);
  1201. end;
  1202. Dest[j]:=WideChar(w);
  1203. inc(j);
  1204. end;
  1205. if j>=MaxDestChars then j:=MaxDestChars-1;
  1206. Dest[j]:=#0;
  1207. end
  1208. else
  1209. begin
  1210. while i<SourceBytes do
  1211. begin
  1212. b:=byte(Source[i]);
  1213. inc(i);
  1214. // 2 or 3 bytes?
  1215. if b>=$80 then
  1216. begin
  1217. if i>=SourceBytes then
  1218. exit;
  1219. // 3 bytes?
  1220. b := b and $3f;
  1221. if (b and $20)<>0 then
  1222. begin
  1223. b:=byte(Source[i]);
  1224. inc(i);
  1225. if i>=SourceBytes then
  1226. exit;
  1227. if (b and $c0)<>$80 then
  1228. exit;
  1229. end;
  1230. if (byte(Source[i]) and $c0)<>$80 then
  1231. exit;
  1232. inc(i);
  1233. end;
  1234. inc(j);
  1235. end;
  1236. end;
  1237. result:=j+1;
  1238. end;
  1239. function UTF8Encode(const s : WideString) : UTF8String;
  1240. var
  1241. i : SizeInt;
  1242. hs : UTF8String;
  1243. begin
  1244. result:='';
  1245. if s='' then
  1246. exit;
  1247. SetLength(hs,length(s)*3);
  1248. i:=UnicodeToUtf8(pchar(hs),length(hs)+1,PWideChar(s),length(s));
  1249. if i>0 then
  1250. begin
  1251. SetLength(hs,i-1);
  1252. result:=hs;
  1253. end;
  1254. end;
  1255. function UTF8Decode(const s : UTF8String): WideString;
  1256. var
  1257. i : SizeInt;
  1258. hs : WideString;
  1259. begin
  1260. result:='';
  1261. if s='' then
  1262. exit;
  1263. SetLength(hs,length(s));
  1264. i:=Utf8ToUnicode(PWideChar(hs),length(hs)+1,pchar(s),length(s));
  1265. if i>0 then
  1266. begin
  1267. SetLength(hs,i-1);
  1268. result:=hs;
  1269. end;
  1270. end;
  1271. function AnsiToUtf8(const s : ansistring): UTF8String;{$ifdef SYSTEMINLINE}inline;{$endif}
  1272. begin
  1273. Result:=Utf8Encode(s);
  1274. end;
  1275. function Utf8ToAnsi(const s : UTF8String) : ansistring;{$ifdef SYSTEMINLINE}inline;{$endif}
  1276. begin
  1277. Result:=Utf8Decode(s);
  1278. end;
  1279. procedure unimplementedwidestring;
  1280. begin
  1281. HandleErrorFrame(215,get_frame);
  1282. end;
  1283. function GenericWideCase(const s : WideString) : WideString;
  1284. begin
  1285. unimplementedwidestring;
  1286. end;
  1287. function CompareWideString(const s1, s2 : WideString) : PtrInt;
  1288. begin
  1289. unimplementedwidestring;
  1290. end;
  1291. function CompareTextWideString(const s1, s2 : WideString): PtrInt;
  1292. begin
  1293. unimplementedwidestring;
  1294. end;
  1295. function CharLengthPChar(const Str: PChar): PtrInt;
  1296. begin
  1297. unimplementedwidestring;
  1298. end;
  1299. procedure initwidestringmanager;
  1300. begin
  1301. fillchar(widestringmanager,sizeof(widestringmanager),0);
  1302. widestringmanager.Wide2AnsiMoveProc:=@defaultWide2AnsiMove;
  1303. widestringmanager.Ansi2WideMoveProc:=@defaultAnsi2WideMove;
  1304. widestringmanager.UpperWideStringProc:=@GenericWideCase;
  1305. widestringmanager.LowerWideStringProc:=@GenericWideCase;
  1306. widestringmanager.CompareWideStringProc:=@CompareWideString;
  1307. widestringmanager.CompareTextWideStringProc:=@CompareTextWideString;
  1308. widestringmanager.CharLengthPCharProc:=@CharLengthPChar;
  1309. end;
  1310. {
  1311. $Log: wstrings.inc,v $
  1312. Revision 1.58 2005/05/04 10:34:48 michael
  1313. + Fix for Utf8ToUnicode from Lazarus bug tracker 888
  1314. Revision 1.57 2005/04/03 08:46:02 florian
  1315. * widestr->shortstr fixed
  1316. * wstrings to system unit dependencies added
  1317. Revision 1.56 2005/03/22 10:10:54 florian
  1318. * shortstr_to_widestring fixed
  1319. Revision 1.55 2005/03/14 21:32:04 florian
  1320. * utf8 to unicode (utf-16) fix from Matthias
  1321. Revision 1.54 2005/03/14 21:09:04 florian
  1322. * widestring manager can handle now ansi<->wide string conversions even if the lens don't match
  1323. Revision 1.53 2005/02/26 15:00:14 florian
  1324. + WideSameStr
  1325. Revision 1.52 2005/02/26 10:21:17 florian
  1326. + implemented WideFormat
  1327. + some Widestring stuff implemented
  1328. * some Widestring stuff fixed
  1329. Revision 1.51 2005/02/14 17:13:30 peter
  1330. * truncate log
  1331. Revision 1.50 2005/02/06 09:38:45 florian
  1332. + StrCharLength infrastructure
  1333. Revision 1.49 2005/02/03 18:40:50 florian
  1334. + infrastructure for WideCompareText implemented
  1335. Revision 1.48 2005/02/01 20:22:49 florian
  1336. * improved widestring infrastructure manager
  1337. Revision 1.47 2005/01/06 13:31:06 florian
  1338. * widecharray patch from Peter
  1339. }