wstrings.inc 39 KB

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