wstrings.inc 39 KB

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