wstrings.inc 38 KB

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