2
0

wstrings.inc 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2005 by Florian Klaempfl,
  4. member of the Free Pascal development team.
  5. This file implements support routines for WideStrings with FPC
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. {
  13. This file contains the implementation of the WideString type,
  14. and all things that are needed for it.
  15. WideString is defined as a 'silent' pwidechar :
  16. a pwidechar that points to :
  17. @-8 : SizeInt for reference count;
  18. @-4 : SizeInt for size; size=number of bytes, not the number of chars. Divide or multiply
  19. with sizeof(WideChar) to convert. This is needed to be compatible with Delphi and
  20. Windows COM BSTR.
  21. @ : String + Terminating #0;
  22. Pwidechar(Widestring) is a valid typecast.
  23. So WS[i] is converted to the address @WS+i-1.
  24. Constants should be assigned a reference count of -1
  25. Meaning that they can't be disposed of.
  26. }
  27. Type
  28. PWideRec = ^TWideRec;
  29. TWideRec = Packed Record
  30. Len : DWord;
  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. setlength(dest,len);
  46. for i:=1 to len do
  47. begin
  48. if word(source^)<256 then
  49. dest[i]:=char(word(source^))
  50. else
  51. dest[i]:='?';
  52. inc(source);
  53. end;
  54. end;
  55. procedure DefaultAnsi2WideMove(source:pchar;var dest:widestring;len:SizeInt);
  56. var
  57. i : SizeInt;
  58. begin
  59. setlength(dest,len);
  60. for i:=1 to len do
  61. begin
  62. dest[i]:=widechar(byte(source^));
  63. inc(source);
  64. end;
  65. end;
  66. Procedure GetWideStringManager (Var Manager : TWideStringManager);
  67. begin
  68. manager:=widestringmanager;
  69. end;
  70. Procedure SetWideStringManager (Const New : TWideStringManager; Var Old: TWideStringManager);
  71. begin
  72. Old:=widestringmanager;
  73. widestringmanager:=New;
  74. end;
  75. Procedure SetWideStringManager (Const New : TWideStringManager);
  76. begin
  77. widestringmanager:=New;
  78. end;
  79. (*
  80. Procedure UniqueWideString(Var S : WideString); [Public,Alias : 'FPC_WIDESTR_UNIQUE'];
  81. {
  82. Make sure reference count of S is 1,
  83. using copy-on-write semantics.
  84. }
  85. begin
  86. end;
  87. *)
  88. {****************************************************************************
  89. Internal functions, not in interface.
  90. ****************************************************************************}
  91. procedure WideStringError;
  92. begin
  93. HandleErrorFrame(204,get_frame);
  94. end;
  95. {$ifdef WideStrDebug}
  96. Procedure DumpWideRec(S : Pointer);
  97. begin
  98. If S=Nil then
  99. Writeln ('String is nil')
  100. Else
  101. Begin
  102. With PWideRec(S-WideFirstOff)^ do
  103. begin
  104. Write ('(Len:',len);
  105. Writeln (' Ref: ',ref,')');
  106. end;
  107. end;
  108. end;
  109. {$endif}
  110. Function NewWideString(Len : SizeInt) : Pointer;
  111. {
  112. Allocate a new WideString on the heap.
  113. initialize it to zero length and reference count 1.
  114. }
  115. Var
  116. P : Pointer;
  117. begin
  118. {$ifdef MSWINDOWS}
  119. if winwidestringalloc then
  120. begin
  121. P:=SysAllocStringLen(nil,Len);
  122. if P=nil then
  123. WideStringError;
  124. end
  125. else
  126. {$endif MSWINDOWS}
  127. begin
  128. GetMem(P,Len*sizeof(WideChar)+WideRecLen);
  129. If P<>Nil then
  130. begin
  131. PWideRec(P)^.Len:=Len*2; { Initial length }
  132. PWideRec(P)^.First:=#0; { Terminating #0 }
  133. inc(p,WideFirstOff); { Points to string now }
  134. end
  135. else
  136. WideStringError;
  137. end;
  138. NewWideString:=P;
  139. end;
  140. Procedure DisposeWideString(Var S : Pointer);
  141. {
  142. Deallocates a WideString From the heap.
  143. }
  144. begin
  145. If S=Nil then
  146. exit;
  147. {$ifndef MSWINDOWS}
  148. Dec (S,WideFirstOff);
  149. Freemem(S);
  150. {$else MSWINDOWS}
  151. if winwidestringalloc then
  152. SysFreeString(S)
  153. else
  154. begin
  155. Dec (S,WideFirstOff);
  156. Freemem(S);
  157. end;
  158. {$endif MSWINDOWS}
  159. S:=Nil;
  160. end;
  161. var
  162. __data_start: byte; external name '__data_start__';
  163. __data_end: byte; external name '__data_end__';
  164. function IsWideStringConstant(S: pointer): boolean;{$ifdef SYSTEMINLINE}inline;{$endif}
  165. {
  166. Returns True if widestring is constant (located in .data section);
  167. }
  168. begin
  169. Result:=(S>=@__data_start) and (S<@__data_end);
  170. end;
  171. Procedure fpc_WideStr_Decr_Ref (Var S : Pointer);[Public,Alias:'FPC_WIDESTR_DECR_REF']; compilerproc;
  172. {
  173. Decreases the ReferenceCount of a non constant widestring;
  174. If the reference count is zero, deallocate the string;
  175. }
  176. Type
  177. pSizeInt = ^SizeInt;
  178. Begin
  179. { Zero string }
  180. if S=Nil then
  181. exit;
  182. if not IsWideStringConstant(S) then
  183. DisposeWideString(S);
  184. end;
  185. { alias for internal use }
  186. Procedure fpc_WideStr_Decr_Ref (Var S : Pointer);[external name 'FPC_WIDESTR_DECR_REF'];
  187. Procedure fpc_WideStr_Incr_Ref(Var S : Pointer);[Public,Alias:'FPC_WIDESTR_INCR_REF']; compilerproc;
  188. var
  189. p : pointer;
  190. Begin
  191. If S=Nil then
  192. exit;
  193. p:=NewWidestring(length(WideString(S)));
  194. move(s^,p^,(length(WideString(s))+1)*sizeof(widechar)); // double #0 too
  195. s:=p;
  196. end;
  197. { alias for internal use }
  198. Procedure fpc_WideStr_Incr_Ref (Var S : Pointer);[external name 'FPC_WIDESTR_INCR_REF'];
  199. {$ifndef FPC_STRTOSHORTSTRINGPROC}
  200. function fpc_WideStr_To_ShortStr (high_of_res: SizeInt;const S2 : WideString): shortstring;[Public, alias: 'FPC_WIDESTR_TO_SHORTSTR']; compilerproc;
  201. {
  202. Converts a WideString to a ShortString;
  203. }
  204. Var
  205. Size : SizeInt;
  206. temp : ansistring;
  207. begin
  208. result:='';
  209. Size:=Length(S2);
  210. if Size>0 then
  211. begin
  212. If Size>high_of_res then
  213. Size:=high_of_res;
  214. widestringmanager.Wide2AnsiMoveProc(PWideChar(S2),temp,Size);
  215. result:=temp;
  216. end;
  217. end;
  218. {$else FPC_STRTOSHORTSTRINGPROC}
  219. procedure fpc_WideStr_To_ShortStr (out res: ShortString;const S2 : WideString); [Public, alias: 'FPC_WIDESTR_TO_SHORTSTR'];compilerproc;
  220. {
  221. Converts a WideString to a ShortString;
  222. }
  223. Var
  224. Size : SizeInt;
  225. temp : ansistring;
  226. begin
  227. res:='';
  228. Size:=Length(S2);
  229. if Size>0 then
  230. begin
  231. If Size>high(res) then
  232. Size:=high(res);
  233. widestringmanager.Wide2AnsiMoveProc(PWideChar(S2),temp,Size);
  234. res:=temp;
  235. end;
  236. end;
  237. {$endif FPC_STRTOSHORTSTRINGPROC}
  238. Function fpc_ShortStr_To_WideStr (Const S2 : ShortString): WideString;compilerproc;
  239. {
  240. Converts a ShortString to a WideString;
  241. }
  242. Var
  243. Size : SizeInt;
  244. begin
  245. result:='';
  246. Size:=Length(S2);
  247. if Size>0 then
  248. begin
  249. widestringmanager.Ansi2WideMoveProc(PChar(@S2[1]),result,Size);
  250. { Terminating Zero }
  251. PWideChar(Pointer(fpc_ShortStr_To_WideStr)+Size*sizeof(WideChar))^:=#0;
  252. end;
  253. end;
  254. Function fpc_WideStr_To_AnsiStr (const S2 : WideString): AnsiString; compilerproc;
  255. {
  256. Converts a WideString to an AnsiString
  257. }
  258. Var
  259. Size : SizeInt;
  260. begin
  261. result:='';
  262. Size:=Length(S2);
  263. if Size>0 then
  264. widestringmanager.Wide2AnsiMoveProc(PWideChar(Pointer(S2)),result,Size);
  265. end;
  266. Function fpc_AnsiStr_To_WideStr (Const S2 : AnsiString): WideString; compilerproc;
  267. {
  268. Converts an AnsiString to a WideString;
  269. }
  270. Var
  271. Size : SizeInt;
  272. begin
  273. result:='';
  274. Size:=Length(S2);
  275. if Size>0 then
  276. widestringmanager.Ansi2WideMoveProc(PChar(S2),result,Size);
  277. end;
  278. Function fpc_PWideChar_To_AnsiStr(const p : pwidechar): ansistring; compilerproc;
  279. var
  280. Size : SizeInt;
  281. begin
  282. result:='';
  283. if p=nil then
  284. exit;
  285. Size := IndexWord(p^, -1, 0);
  286. if Size>0 then
  287. widestringmanager.Wide2AnsiMoveProc(P,result,Size);
  288. end;
  289. Function fpc_PWideChar_To_WideStr(const p : pwidechar): widestring; compilerproc;
  290. var
  291. Size : SizeInt;
  292. begin
  293. result:='';
  294. if p=nil then
  295. exit;
  296. Size := IndexWord(p^, -1, 0);
  297. Setlength(result,Size);
  298. if Size>0 then
  299. begin
  300. Move(p^,PWideChar(Pointer(result))^,Size*sizeof(WideChar));
  301. { Terminating Zero }
  302. PWideChar(Pointer(result)+Size*sizeof(WideChar))^:=#0;
  303. end;
  304. end;
  305. {$ifndef FPC_STRTOSHORTSTRINGPROC}
  306. Function fpc_PWideChar_To_ShortStr(const p : pwidechar): shortstring; compilerproc;
  307. var
  308. Size : SizeInt;
  309. temp: ansistring;
  310. begin
  311. result:='';
  312. if p=nil then
  313. exit;
  314. Size := IndexWord(p^, $7fffffff, 0);
  315. if Size>0 then
  316. begin
  317. widestringmanager.Wide2AnsiMoveProc(p,temp,Size);
  318. result:=temp;
  319. end;
  320. end;
  321. {$else FPC_STRTOSHORTSTRINGPROC}
  322. procedure fpc_PWideChar_To_ShortStr(out res : shortstring;const p : pwidechar); compilerproc;
  323. var
  324. Size : SizeInt;
  325. temp: ansistring;
  326. begin
  327. res:='';
  328. if p=nil then
  329. exit;
  330. Size:=IndexWord(p^, high(PtrInt), 0);
  331. if Size>0 then
  332. begin
  333. widestringmanager.Wide2AnsiMoveProc(p,temp,Size);
  334. res:=temp;
  335. end;
  336. end;
  337. {$endif FPC_STRTOSHORTSTRINGPROC}
  338. { checked against the ansistring routine, 2001-05-27 (FK) }
  339. Procedure fpc_WideStr_Assign (Var S1 : Pointer;S2 : Pointer);[Public,Alias:'FPC_WIDESTR_ASSIGN']; compilerproc;
  340. {
  341. Assigns S2 to S1 (S1:=S2), taking in account reference counts.
  342. }
  343. begin
  344. if S1=S2 then exit;
  345. if S2<>nil then
  346. begin
  347. if IsWideStringConstant(S1) then
  348. begin
  349. S1:=NewWidestring(length(WideString(S2)));
  350. move(s2^,s1^,(length(WideString(s1))+1)*sizeof(widechar));
  351. end
  352. else
  353. {$ifdef MSWINDOWS}
  354. if winwidestringalloc then
  355. begin
  356. if SysReAllocStringLen(S1, S2, Length(WideString(S2))) = 0 then
  357. WideStringError;
  358. end
  359. else
  360. {$endif MSWINDOWS}
  361. begin
  362. SetLength(WideString(S1),length(WideString(S2)));
  363. move(s2^,s1^,(length(WideString(s1))+1)*sizeof(widechar));
  364. end;
  365. end
  366. else
  367. begin
  368. { Free S1 }
  369. fpc_widestr_decr_ref (S1);
  370. S1:=nil;
  371. end;
  372. end;
  373. { alias for internal use }
  374. Procedure fpc_WideStr_Assign (Var S1 : Pointer;S2 : Pointer);[external name 'FPC_WIDESTR_ASSIGN'];
  375. {$ifndef STR_CONCAT_PROCS}
  376. function fpc_WideStr_Concat (const S1,S2 : WideString): WideString; compilerproc;
  377. Var
  378. Size,Location : SizeInt;
  379. pc : pwidechar;
  380. begin
  381. { only assign if s1 or s2 is empty }
  382. if (S1='') then
  383. begin
  384. result:=s2;
  385. exit;
  386. end;
  387. if (S2='') then
  388. begin
  389. result:=s1;
  390. exit;
  391. end;
  392. Location:=Length(S1);
  393. Size:=length(S2);
  394. SetLength(result,Size+Location);
  395. pc:=pwidechar(result);
  396. Move(S1[1],pc^,Location*sizeof(WideChar));
  397. inc(pc,location);
  398. Move(S2[1],pc^,(Size+1)*sizeof(WideChar));
  399. end;
  400. function fpc_WideStr_Concat_multi (const sarr:array of Widestring): widestring; compilerproc;
  401. Var
  402. i : Longint;
  403. p : pointer;
  404. pc : pwidechar;
  405. Size,NewSize : SizeInt;
  406. begin
  407. { First calculate size of the result so we can do
  408. a single call to SetLength() }
  409. NewSize:=0;
  410. for i:=low(sarr) to high(sarr) do
  411. inc(Newsize,length(sarr[i]));
  412. SetLength(result,NewSize);
  413. pc:=pwidechar(result);
  414. for i:=low(sarr) to high(sarr) do
  415. begin
  416. p:=pointer(sarr[i]);
  417. if assigned(p) then
  418. begin
  419. Size:=length(widestring(p));
  420. Move(pwidechar(p)^,pc^,(Size+1)*sizeof(WideChar));
  421. inc(pc,size);
  422. end;
  423. end;
  424. end;
  425. {$else STR_CONCAT_PROCS}
  426. procedure fpc_WideStr_Concat (var DestS:Widestring;const S1,S2 : WideString); compilerproc;
  427. Var
  428. Size,Location : SizeInt;
  429. same : boolean;
  430. begin
  431. { only assign if s1 or s2 is empty }
  432. if (S1='') then
  433. begin
  434. DestS:=s2;
  435. exit;
  436. end;
  437. if (S2='') then
  438. begin
  439. DestS:=s1;
  440. exit;
  441. end;
  442. Location:=Length(S1);
  443. Size:=length(S2);
  444. { Use Pointer() typecasts to prevent extra conversion code }
  445. if Pointer(DestS)=Pointer(S1) then
  446. begin
  447. same:=Pointer(S1)=Pointer(S2);
  448. SetLength(DestS,Size+Location);
  449. if same then
  450. Move(Pointer(DestS)^,(Pointer(DestS)+Location*sizeof(WideChar))^,(Size)*sizeof(WideChar))
  451. else
  452. Move(Pointer(S2)^,(Pointer(DestS)+Location*sizeof(WideChar))^,(Size+1)*sizeof(WideChar));
  453. end
  454. else if Pointer(DestS)=Pointer(S2) then
  455. begin
  456. SetLength(DestS,Size+Location);
  457. Move(Pointer(DestS)^,(Pointer(DestS)+Location*sizeof(WideChar))^,(Size+1)*sizeof(WideChar));
  458. Move(Pointer(S1)^,Pointer(DestS)^,Location*sizeof(WideChar));
  459. end
  460. else
  461. begin
  462. DestS:='';
  463. SetLength(DestS,Size+Location);
  464. Move(Pointer(S1)^,Pointer(DestS)^,Location*sizeof(WideChar));
  465. Move(Pointer(S2)^,(Pointer(DestS)+Location*sizeof(WideChar))^,(Size+1)*sizeof(WideChar));
  466. end;
  467. end;
  468. procedure fpc_WideStr_Concat_multi (var DestS:Widestring;const sarr:array of Widestring); compilerproc;
  469. Var
  470. i : Longint;
  471. p,pc : pointer;
  472. Size,NewLen : SizeInt;
  473. DestTmp : Widestring;
  474. begin
  475. if high(sarr)=0 then
  476. begin
  477. DestS:='';
  478. exit;
  479. end;
  480. { First calculate size of the result so we can do
  481. a single call to SetLength() }
  482. NewLen:=0;
  483. for i:=low(sarr) to high(sarr) do
  484. inc(NewLen,length(sarr[i]));
  485. SetLength(DestTmp,NewLen);
  486. pc:=pwidechar(DestTmp);
  487. for i:=low(sarr) to high(sarr) do
  488. begin
  489. p:=pointer(sarr[i]);
  490. if assigned(p) then
  491. begin
  492. Size:=length(widestring(p));
  493. Move(p^,pc^,(Size+1)*sizeof(WideChar));
  494. inc(pc,size*sizeof(WideChar));
  495. end;
  496. end;
  497. DestS:=DestTmp;
  498. end;
  499. {$endif STR_CONCAT_PROCS}
  500. Function fpc_Char_To_WChar(const c : Char): WideChar; compilerproc;
  501. var
  502. w: widestring;
  503. begin
  504. widestringmanager.Ansi2WideMoveProc(@c, w, 1);
  505. fpc_Char_To_WChar:= w[1];
  506. end;
  507. Function fpc_Char_To_WideStr(const c : Char): WideString; compilerproc;
  508. {
  509. Converts a Char to a WideString;
  510. }
  511. begin
  512. Setlength(fpc_Char_To_WideStr,1);
  513. fpc_Char_To_WideStr[1]:=c;
  514. { Terminating Zero }
  515. PWideChar(Pointer(fpc_Char_To_WideStr)+sizeof(WideChar))^:=#0;
  516. end;
  517. Function fpc_WChar_To_Char(const c : WideChar): Char; compilerproc;
  518. {
  519. Converts a WideChar to a Char;
  520. }
  521. var
  522. s: ansistring;
  523. begin
  524. widestringmanager.Wide2AnsiMoveProc(@c, s, 1);
  525. if length(s)=1 then
  526. fpc_WChar_To_Char:= s[1]
  527. else
  528. fpc_WChar_To_Char:='?';
  529. end;
  530. Function fpc_WChar_To_WideStr(const c : WideChar): WideString; compilerproc;
  531. {
  532. Converts a WideChar to a WideString;
  533. }
  534. begin
  535. Setlength (fpc_WChar_To_WideStr,1);
  536. fpc_WChar_To_WideStr[1]:= c;
  537. end;
  538. Function fpc_WChar_To_AnsiStr(const c : WideChar): AnsiString; compilerproc;
  539. {
  540. Converts a WideChar to a AnsiString;
  541. }
  542. begin
  543. widestringmanager.Wide2AnsiMoveProc(@c, fpc_WChar_To_AnsiStr, 1);
  544. end;
  545. {$ifndef FPC_STRTOSHORTSTRINGPROC}
  546. Function fpc_WChar_To_ShortStr(const c : WideChar): ShortString; compilerproc;
  547. {
  548. Converts a WideChar to a ShortString;
  549. }
  550. var
  551. s: ansistring;
  552. begin
  553. widestringmanager.Wide2AnsiMoveProc(@c, s, 1);
  554. fpc_WChar_To_ShortStr:= s;
  555. end;
  556. {$else FPC_STRTOSHORTSTRINGPROC}
  557. procedure fpc_WChar_To_ShortStr(out res : shortstring;const c : WideChar) compilerproc;
  558. {
  559. Converts a WideChar to a ShortString;
  560. }
  561. var
  562. s: ansistring;
  563. begin
  564. widestringmanager.Wide2AnsiMoveProc(@c,s,1);
  565. res:=s;
  566. end;
  567. {$endif FPC_STRTOSHORTSTRINGPROC}
  568. Function fpc_PChar_To_WideStr(const p : pchar): WideString; compilerproc;
  569. Var
  570. L : SizeInt;
  571. begin
  572. if (not assigned(p)) or (p[0]=#0) Then
  573. begin
  574. fpc_pchar_to_widestr := '';
  575. exit;
  576. end;
  577. l:=IndexChar(p^,-1,#0);
  578. widestringmanager.Ansi2WideMoveProc(P,fpc_PChar_To_WideStr,l);
  579. end;
  580. Function fpc_CharArray_To_WideStr(const arr: array of char; zerobased: boolean = true): WideString; compilerproc;
  581. var
  582. i : SizeInt;
  583. begin
  584. if (zerobased) then
  585. begin
  586. if (arr[0]=#0) Then
  587. begin
  588. fpc_chararray_to_widestr := '';
  589. exit;
  590. end;
  591. i:=IndexChar(arr,high(arr)+1,#0);
  592. if i = -1 then
  593. i := high(arr)+1;
  594. end
  595. else
  596. i := high(arr)+1;
  597. SetLength(fpc_CharArray_To_WideStr,i);
  598. widestringmanager.Ansi2WideMoveProc (pchar(@arr),fpc_CharArray_To_WideStr,i);
  599. end;
  600. {$ifndef FPC_STRTOSHORTSTRINGPROC}
  601. function fpc_WideCharArray_To_ShortStr(const arr: array of widechar; zerobased: boolean = true): shortstring;[public,alias:'FPC_WIDECHARARRAY_TO_SHORTSTR']; compilerproc;
  602. var
  603. l: longint;
  604. index: longint;
  605. len: byte;
  606. temp: ansistring;
  607. begin
  608. l := high(arr)+1;
  609. if l>=256 then
  610. l:=255
  611. else if l<0 then
  612. l:=0;
  613. if zerobased then
  614. begin
  615. index:=IndexWord(arr[0],l,0);
  616. if (index < 0) then
  617. len := l
  618. else
  619. len := index;
  620. end
  621. else
  622. len := l;
  623. widestringmanager.Wide2AnsiMoveProc (pwidechar(@arr),temp,len);
  624. fpc_WideCharArray_To_ShortStr := temp;
  625. end;
  626. {$else FPC_STRTOSHORTSTRINGPROC}
  627. procedure fpc_WideCharArray_To_ShortStr(out res : shortstring;const arr: array of widechar; zerobased: boolean = true);[public,alias:'FPC_WIDECHARARRAY_TO_SHORTSTR']; compilerproc;
  628. var
  629. l: longint;
  630. index: ptrint;
  631. len: byte;
  632. temp: ansistring;
  633. begin
  634. l := high(arr)+1;
  635. if l>=high(res)+1 then
  636. l:=high(res)
  637. else if l<0 then
  638. l:=0;
  639. if zerobased then
  640. begin
  641. index:=IndexWord(arr[0],l,0);
  642. if index<0 then
  643. len:=l
  644. else
  645. len:=index;
  646. end
  647. else
  648. len:=l;
  649. widestringmanager.Wide2AnsiMoveProc (pwidechar(@arr),temp,len);
  650. res:=temp;
  651. end;
  652. {$endif FPC_STRTOSHORTSTRINGPROC}
  653. Function fpc_WideCharArray_To_AnsiStr(const arr: array of widechar; zerobased: boolean = true): AnsiString; compilerproc;
  654. var
  655. i : SizeInt;
  656. begin
  657. if (zerobased) then
  658. begin
  659. i:=IndexWord(arr,high(arr)+1,0);
  660. if i = -1 then
  661. i := high(arr)+1;
  662. end
  663. else
  664. i := high(arr)+1;
  665. SetLength(fpc_WideCharArray_To_AnsiStr,i);
  666. widestringmanager.Wide2AnsiMoveProc (pwidechar(@arr),fpc_WideCharArray_To_AnsiStr,i);
  667. end;
  668. Function fpc_WideCharArray_To_WideStr(const arr: array of widechar; zerobased: boolean = true): WideString; compilerproc;
  669. var
  670. i : SizeInt;
  671. begin
  672. if (zerobased) then
  673. begin
  674. i:=IndexWord(arr,high(arr)+1,0);
  675. if i = -1 then
  676. i := high(arr)+1;
  677. end
  678. else
  679. i := high(arr)+1;
  680. SetLength(fpc_WideCharArray_To_WideStr,i);
  681. Move(arr[0], Pointer(fpc_WideCharArray_To_WideStr)^,i*sizeof(WideChar));
  682. end;
  683. {$ifndef FPC_STRTOCHARARRAYPROC}
  684. { inside the compiler, the resulttype is modified to that of the actual }
  685. { chararray we're converting to (JM) }
  686. function fpc_widestr_to_chararray(arraysize: SizeInt; const src: WideString): fpc_big_chararray;[public,alias: 'FPC_WIDESTR_TO_CHARARRAY']; compilerproc;
  687. var
  688. len: SizeInt;
  689. temp: ansistring;
  690. begin
  691. len := length(src);
  692. { make sure we don't dereference src if it can be nil (JM) }
  693. if len > 0 then
  694. widestringmanager.wide2ansimoveproc(pwidechar(@src[1]),temp,len);
  695. len := length(temp);
  696. if len > arraysize then
  697. len := arraysize;
  698. {$r-}
  699. move(temp[1],fpc_widestr_to_chararray[0],len);
  700. fillchar(fpc_widestr_to_chararray[len],arraysize-len,0);
  701. {$ifdef RangeCheckWasOn}
  702. {$r+}
  703. {$endif}
  704. end;
  705. { inside the compiler, the resulttype is modified to that of the actual }
  706. { widechararray we're converting to (JM) }
  707. function fpc_widestr_to_widechararray(arraysize: SizeInt; const src: WideString): fpc_big_widechararray;[public,alias: 'FPC_WIDESTR_TO_WIDECHARARRAY']; compilerproc;
  708. var
  709. len: SizeInt;
  710. begin
  711. len := length(src);
  712. if len > arraysize then
  713. len := arraysize;
  714. {$r-}
  715. { make sure we don't try to access element 1 of the ansistring if it's nil }
  716. if len > 0 then
  717. move(src[1],fpc_widestr_to_widechararray[0],len*SizeOf(WideChar));
  718. fillchar(fpc_widestr_to_widechararray[len],(arraysize-len)*SizeOf(WideChar),0);
  719. {$ifdef RangeCheckWasOn}
  720. {$r+}
  721. {$endif}
  722. end;
  723. { inside the compiler, the resulttype is modified to that of the actual }
  724. { chararray we're converting to (JM) }
  725. function fpc_ansistr_to_widechararray(arraysize: SizeInt; const src: AnsiString): fpc_big_widechararray;[public,alias: 'FPC_ANSISTR_TO_WIDECHARARRAY']; compilerproc;
  726. var
  727. len: SizeInt;
  728. temp: widestring;
  729. begin
  730. len := length(src);
  731. { make sure we don't dereference src if it can be nil (JM) }
  732. if len > 0 then
  733. widestringmanager.ansi2widemoveproc(pchar(@src[1]),temp,len);
  734. len := length(temp);
  735. if len > arraysize then
  736. len := arraysize;
  737. {$r-}
  738. move(temp[1],fpc_ansistr_to_widechararray[0],len*sizeof(widechar));
  739. fillchar(fpc_ansistr_to_widechararray[len],(arraysize-len)*SizeOf(WideChar),0);
  740. {$ifdef RangeCheckWasOn}
  741. {$r+}
  742. {$endif}
  743. end;
  744. function fpc_shortstr_to_widechararray(arraysize: SizeInt; const src: ShortString): fpc_big_widechararray;[public,alias: 'FPC_SHORTSTR_TO_WIDECHARARRAY']; compilerproc;
  745. var
  746. len: longint;
  747. temp : widestring;
  748. begin
  749. len := length(src);
  750. { make sure we don't access char 1 if length is 0 (JM) }
  751. if len > 0 then
  752. widestringmanager.ansi2widemoveproc(pchar(@src[1]),temp,len);
  753. len := length(temp);
  754. if len > arraysize then
  755. len := arraysize;
  756. {$r-}
  757. move(temp[1],fpc_shortstr_to_widechararray[0],len*sizeof(widechar));
  758. fillchar(fpc_shortstr_to_widechararray[len],(arraysize-len)*SizeOf(WideChar),0);
  759. {$ifdef RangeCheckWasOn}
  760. {$r+}
  761. {$endif}
  762. end;
  763. {$else ndef FPC_STRTOCHARARRAYPROC}
  764. procedure fpc_widestr_to_chararray(out res: array of char; const src: WideString); compilerproc;
  765. var
  766. len: SizeInt;
  767. temp: ansistring;
  768. begin
  769. len := length(src);
  770. { make sure we don't dereference src if it can be nil (JM) }
  771. if len > 0 then
  772. widestringmanager.wide2ansimoveproc(pwidechar(@src[1]),temp,len);
  773. len := length(temp);
  774. if len > length(res) then
  775. len := length(res);
  776. {$r-}
  777. move(temp[1],res[0],len);
  778. fillchar(res[len],length(res)-len,0);
  779. {$ifdef RangeCheckWasOn}
  780. {$r+}
  781. {$endif}
  782. end;
  783. procedure fpc_widestr_to_widechararray(out res: array of widechar; const src: WideString); compilerproc;
  784. var
  785. len: SizeInt;
  786. begin
  787. len := length(src);
  788. if len > length(res) then
  789. len := length(res);
  790. {$r-}
  791. { make sure we don't try to access element 1 of the ansistring if it's nil }
  792. if len > 0 then
  793. move(src[1],res[0],len*SizeOf(WideChar));
  794. fillchar(res[len],(length(res)-len)*SizeOf(WideChar),0);
  795. {$ifdef RangeCheckWasOn}
  796. {$r+}
  797. {$endif}
  798. end;
  799. procedure fpc_ansistr_to_widechararray(out res: array of widechar; const src: AnsiString); compilerproc;
  800. var
  801. len: SizeInt;
  802. temp: widestring;
  803. begin
  804. len := length(src);
  805. { make sure we don't dereference src if it can be nil (JM) }
  806. if len > 0 then
  807. widestringmanager.ansi2widemoveproc(pchar(@src[1]),temp,len);
  808. len := length(temp);
  809. if len > length(res) then
  810. len := length(res);
  811. {$r-}
  812. move(temp[1],res[0],len*sizeof(widechar));
  813. fillchar(res[len],(length(res)-len)*SizeOf(WideChar),0);
  814. {$ifdef RangeCheckWasOn}
  815. {$r+}
  816. {$endif}
  817. end;
  818. procedure fpc_shortstr_to_widechararray(out res: array of widechar; const src: ShortString); compilerproc;
  819. var
  820. len: longint;
  821. temp : widestring;
  822. begin
  823. len := length(src);
  824. { make sure we don't access char 1 if length is 0 (JM) }
  825. if len > 0 then
  826. widestringmanager.ansi2widemoveproc(pchar(@src[1]),temp,len);
  827. len := length(temp);
  828. if len > length(res) then
  829. len := length(res);
  830. {$r-}
  831. move(temp[1],res[0],len*sizeof(widechar));
  832. fillchar(res[len],(length(res)-len)*SizeOf(WideChar),0);
  833. {$ifdef RangeCheckWasOn}
  834. {$r+}
  835. {$endif}
  836. end;
  837. {$endif ndef FPC_STRTOCHARARRAYPROC}
  838. Function fpc_WideStr_Compare(const S1,S2 : WideString): SizeInt;[Public,Alias : 'FPC_WIDESTR_COMPARE']; compilerproc;
  839. {
  840. Compares 2 WideStrings;
  841. The result is
  842. <0 if S1<S2
  843. 0 if S1=S2
  844. >0 if S1>S2
  845. }
  846. Var
  847. MaxI,Temp : SizeInt;
  848. begin
  849. if pointer(S1)=pointer(S2) then
  850. begin
  851. fpc_WideStr_Compare:=0;
  852. exit;
  853. end;
  854. Maxi:=Length(S1);
  855. temp:=Length(S2);
  856. If MaxI>Temp then
  857. MaxI:=Temp;
  858. Temp:=CompareWord(S1[1],S2[1],MaxI);
  859. if temp=0 then
  860. temp:=Length(S1)-Length(S2);
  861. fpc_WideStr_Compare:=Temp;
  862. end;
  863. Function fpc_WideStr_Compare_Equal(const S1,S2 : WideString): SizeInt;[Public,Alias : 'FPC_WIDESTR_COMPARE_EQUAL']; compilerproc;
  864. {
  865. Compares 2 WideStrings for equality only;
  866. The result is
  867. 0 if S1=S2
  868. <>0 if S1<>S2
  869. }
  870. Var
  871. MaxI : SizeInt;
  872. begin
  873. if pointer(S1)=pointer(S2) then
  874. exit(0);
  875. Maxi:=Length(S1);
  876. If MaxI<>Length(S2) then
  877. exit(-1)
  878. else
  879. exit(CompareWord(S1[1],S2[1],MaxI));
  880. end;
  881. Procedure fpc_WideStr_CheckZero(p : pointer);[Public,Alias : 'FPC_WIDESTR_CHECKZERO']; compilerproc;
  882. begin
  883. if p=nil then
  884. HandleErrorFrame(201,get_frame);
  885. end;
  886. Procedure fpc_WideStr_CheckRange(len,index : SizeInt);[Public,Alias : 'FPC_WIDESTR_RANGECHECK']; compilerproc;
  887. begin
  888. if (index>len div 2) or (Index<1) then
  889. HandleErrorFrame(201,get_frame);
  890. end;
  891. Procedure fpc_WideStr_SetLength(Var S : WideString; l : SizeInt);[Public,Alias : 'FPC_WIDESTR_SETLENGTH']; compilerproc;
  892. {
  893. Sets The length of string S to L.
  894. Makes sure S is unique, and contains enough room.
  895. }
  896. Var
  897. Temp : Pointer;
  898. movelen: SizeInt;
  899. begin
  900. if (l>0) then
  901. begin
  902. if Pointer(S)=nil then
  903. begin
  904. { Need a complete new string...}
  905. Pointer(s):=NewWideString(l);
  906. end
  907. { windows doesn't support reallocing widestrings, this code
  908. is anyways subject to be removed because widestrings shouldn't be
  909. ref. counted anymore (FK) }
  910. else
  911. if
  912. {$ifdef MSWINDOWS}
  913. not winwidestringalloc and
  914. {$endif MSWINDOWS}
  915. not IsWideStringConstant(pointer(S))
  916. then
  917. begin
  918. Dec(Pointer(S),WideFirstOff);
  919. if SizeUInt(L*sizeof(WideChar)+WideRecLen)>MemSize(Pointer(S)) then
  920. reallocmem(pointer(S), L*sizeof(WideChar)+WideRecLen);
  921. Inc(Pointer(S), WideFirstOff);
  922. end
  923. else
  924. begin
  925. { Reallocation is needed... }
  926. Temp:=Pointer(NewWideString(L));
  927. if Length(S)>0 then
  928. begin
  929. if l < succ(length(s)) then
  930. movelen := l
  931. { also move terminating null }
  932. else
  933. movelen := succ(length(s));
  934. Move(Pointer(S)^,Temp^,movelen * Sizeof(WideChar));
  935. end;
  936. fpc_widestr_decr_ref(Pointer(S));
  937. Pointer(S):=Temp;
  938. end;
  939. { Force nil termination in case it gets shorter }
  940. PWord(Pointer(S)+l*sizeof(WideChar))^:=0;
  941. {$ifdef MSWINDOWS}
  942. if not winwidestringalloc then
  943. {$endif MSWINDOWS}
  944. PWideRec(Pointer(S)-WideFirstOff)^.Len:=l*sizeof(WideChar);
  945. end
  946. else
  947. begin
  948. { Length=0 }
  949. if Pointer(S)<>nil then
  950. fpc_widestr_decr_ref (Pointer(S));
  951. Pointer(S):=Nil;
  952. end;
  953. end;
  954. {*****************************************************************************
  955. Public functions, In interface.
  956. *****************************************************************************}
  957. function WideCharToString(S : PWideChar) : AnsiString;
  958. begin
  959. result:=WideCharLenToString(s,Length(WideString(s)));
  960. end;
  961. function StringToWideChar(const Src : AnsiString;Dest : PWideChar;DestSize : SizeInt) : PWideChar;
  962. var
  963. temp:widestring;
  964. begin
  965. widestringmanager.Ansi2WideMoveProc(PChar(Src),temp,Length(Src));
  966. if Length(temp)<DestSize then
  967. move(temp[1],Dest^,Length(temp)*SizeOf(WideChar))
  968. else
  969. move(temp[1],Dest^,(DestSize-1)*SizeOf(WideChar));
  970. Dest[DestSize-1]:=#0;
  971. result:=Dest;
  972. end;
  973. function WideCharLenToString(S : PWideChar;Len : SizeInt) : AnsiString;
  974. begin
  975. //SetLength(result,Len);
  976. widestringmanager.Wide2AnsiMoveproc(S,result,Len);
  977. end;
  978. procedure WideCharLenToStrVar(Src : PWideChar;Len : SizeInt;out Dest : AnsiString);
  979. begin
  980. Dest:=WideCharLenToString(Src,Len);
  981. end;
  982. procedure WideCharToStrVar(S : PWideChar;out Dest : AnsiString);
  983. begin
  984. Dest:=WideCharToString(S);
  985. end;
  986. Function fpc_widestr_Unique(Var S : Pointer): Pointer; [Public,Alias : 'FPC_WIDESTR_UNIQUE']; compilerproc;
  987. begin
  988. pointer(result) := pointer(s);
  989. end;
  990. Function Fpc_WideStr_Copy (Const S : WideString; Index,Size : SizeInt) : WideString;compilerproc;
  991. var
  992. ResultAddress : Pointer;
  993. begin
  994. ResultAddress:=Nil;
  995. dec(index);
  996. if Index < 0 then
  997. Index := 0;
  998. { Check Size. Accounts for Zero-length S, the double check is needed because
  999. Size can be maxint and will get <0 when adding index }
  1000. if (Size>Length(S)) or
  1001. (Index+Size>Length(S)) then
  1002. Size:=Length(S)-Index;
  1003. If Size>0 then
  1004. begin
  1005. If Index<0 Then
  1006. Index:=0;
  1007. ResultAddress:=Pointer(NewWideString (Size));
  1008. if ResultAddress<>Nil then
  1009. begin
  1010. Move (PWideChar(S)[Index],ResultAddress^,Size*sizeof(WideChar));
  1011. PWideRec(ResultAddress-WideFirstOff)^.Len:=Size*sizeof(WideChar);
  1012. PWideChar(ResultAddress+Size*sizeof(WideChar))^:=#0;
  1013. end;
  1014. end;
  1015. fpc_widestr_decr_ref(Pointer(fpc_widestr_copy));
  1016. Pointer(fpc_widestr_Copy):=ResultAddress;
  1017. end;
  1018. Function Pos (Const Substr : WideString; Const Source : WideString) : SizeInt;
  1019. var
  1020. i,MaxLen : SizeInt;
  1021. pc : pwidechar;
  1022. begin
  1023. Pos:=0;
  1024. if Length(SubStr)>0 then
  1025. begin
  1026. MaxLen:=Length(source)-Length(SubStr);
  1027. i:=0;
  1028. pc:=@source[1];
  1029. while (i<=MaxLen) do
  1030. begin
  1031. inc(i);
  1032. if (SubStr[1]=pc^) and
  1033. (CompareWord(Substr[1],pc^,Length(SubStr))=0) then
  1034. begin
  1035. Pos:=i;
  1036. exit;
  1037. end;
  1038. inc(pc);
  1039. end;
  1040. end;
  1041. end;
  1042. { Faster version for a widechar alone }
  1043. Function Pos (c : WideChar; Const s : WideString) : SizeInt;
  1044. var
  1045. i: SizeInt;
  1046. pc : pwidechar;
  1047. begin
  1048. pc:=@s[1];
  1049. for i:=1 to length(s) do
  1050. begin
  1051. if pc^=c then
  1052. begin
  1053. pos:=i;
  1054. exit;
  1055. end;
  1056. inc(pc);
  1057. end;
  1058. pos:=0;
  1059. end;
  1060. Function Pos (c : WideChar; Const s : AnsiString) : SizeInt;
  1061. begin
  1062. result:=Pos(c,WideString(s));
  1063. end;
  1064. Function Pos (c : AnsiString; Const s : WideString) : SizeInt;{$ifdef SYSTEMINLINE}inline;{$endif}
  1065. begin
  1066. result:=Pos(WideString(c),s);
  1067. end;
  1068. Function Pos (c : ShortString; Const s : WideString) : SizeInt;{$ifdef SYSTEMINLINE}inline;{$endif}
  1069. begin
  1070. result:=Pos(WideString(c),s);
  1071. end;
  1072. Function Pos (c : WideString; Const s : AnsiString) : SizeInt;{$ifdef SYSTEMINLINE}inline;{$endif}
  1073. begin
  1074. result:=Pos(c,WideString(s));
  1075. end;
  1076. { Faster version for a char alone. Must be implemented because }
  1077. { pos(c: char; const s: shortstring) also exists, so otherwise }
  1078. { using pos(char,pchar) will always call the shortstring version }
  1079. { (exact match for first argument), also with $h+ (JM) }
  1080. Function Pos (c : Char; Const s : WideString) : SizeInt;
  1081. var
  1082. i: SizeInt;
  1083. wc : widechar;
  1084. pc : pwidechar;
  1085. begin
  1086. wc:=c;
  1087. pc:=@s[1];
  1088. for i:=1 to length(s) do
  1089. begin
  1090. if pc^=wc then
  1091. begin
  1092. pos:=i;
  1093. exit;
  1094. end;
  1095. inc(pc);
  1096. end;
  1097. pos:=0;
  1098. end;
  1099. Procedure Delete (Var S : WideString; Index,Size: SizeInt);
  1100. Var
  1101. LS : SizeInt;
  1102. begin
  1103. If Length(S)=0 then
  1104. exit;
  1105. if index<=0 then
  1106. exit;
  1107. LS:=PWideRec(Pointer(S)-WideFirstOff)^.Len div sizeof(WideChar);
  1108. if (Index<=LS) and (Size>0) then
  1109. begin
  1110. UniqueString (S);
  1111. if Size+Index>LS then
  1112. Size:=LS-Index+1;
  1113. if Index+Size<=LS then
  1114. begin
  1115. Dec(Index);
  1116. Move(PWideChar(S)[Index+Size],PWideChar(S)[Index],(LS-Index-Size+1)*sizeof(WideChar));
  1117. end;
  1118. Setlength(s,LS-Size);
  1119. end;
  1120. end;
  1121. Procedure Insert (Const Source : WideString; Var S : WideString; Index : SizeInt);
  1122. var
  1123. Temp : WideString;
  1124. LS : SizeInt;
  1125. begin
  1126. If Length(Source)=0 then
  1127. exit;
  1128. if index <= 0 then
  1129. index := 1;
  1130. Ls:=Length(S);
  1131. if index > LS then
  1132. index := LS+1;
  1133. Dec(Index);
  1134. Pointer(Temp) := NewWideString(Length(Source)+LS);
  1135. SetLength(Temp,Length(Source)+LS);
  1136. If Index>0 then
  1137. move (PWideChar(S)^,PWideChar(Temp)^,Index*sizeof(WideChar));
  1138. Move (PWideChar(Source)^,PWideChar(Temp)[Index],Length(Source)*sizeof(WideChar));
  1139. If (LS-Index)>0 then
  1140. Move(PWideChar(S)[Index],PWideChar(temp)[Length(Source)+index],(LS-Index)*sizeof(WideChar));
  1141. S:=Temp;
  1142. end;
  1143. function UpCase(const s : WideString) : WideString;
  1144. begin
  1145. result:=widestringmanager.UpperWideStringProc(s);
  1146. end;
  1147. Procedure SetString (Out S : WideString; Buf : PWideChar; Len : SizeInt);
  1148. var
  1149. BufLen: SizeInt;
  1150. begin
  1151. SetLength(S,Len);
  1152. If (Buf<>Nil) and (Len>0) then
  1153. begin
  1154. BufLen := IndexWord(Buf^, Len+1, 0);
  1155. If (BufLen>0) and (BufLen < Len) then
  1156. Len := BufLen;
  1157. Move (Buf[0],S[1],Len*sizeof(WideChar));
  1158. PWideChar(Pointer(S)+Len*sizeof(WideChar))^:=#0;
  1159. end;
  1160. end;
  1161. Procedure SetString (Out S : WideString; Buf : PChar; Len : SizeInt);
  1162. var
  1163. BufLen: SizeInt;
  1164. begin
  1165. SetLength(S,Len);
  1166. If (Buf<>Nil) and (Len>0) then
  1167. begin
  1168. BufLen := IndexByte(Buf^, Len+1, 0);
  1169. If (BufLen>0) and (BufLen < Len) then
  1170. Len := BufLen;
  1171. widestringmanager.Ansi2WideMoveProc(Buf,S,Len);
  1172. //PWideChar(Pointer(S)+Len*sizeof(WideChar))^:=#0;
  1173. end;
  1174. end;
  1175. {$ifndef FPUNONE}
  1176. Function fpc_Val_Real_WideStr(Const S : WideString; out Code : ValSInt): ValReal; [public, alias:'FPC_VAL_REAL_WIDESTR']; compilerproc;
  1177. Var
  1178. SS : String;
  1179. begin
  1180. fpc_Val_Real_WideStr := 0;
  1181. if length(S) > 255 then
  1182. code := 256
  1183. else
  1184. begin
  1185. SS := S;
  1186. Val(SS,fpc_Val_Real_WideStr,code);
  1187. end;
  1188. end;
  1189. {$endif}
  1190. function fpc_val_enum_widestr(str2ordindex:pointer;const s:widestring;out code:valsint):longint;compilerproc;
  1191. var ss:shortstring;
  1192. begin
  1193. if length(s)>255 then
  1194. code:=256
  1195. else
  1196. begin
  1197. ss:=s;
  1198. val(ss,fpc_val_enum_widestr,code);
  1199. end;
  1200. end;
  1201. Function fpc_Val_Currency_WideStr(Const S : WideString; out Code : ValSInt): Currency; [public, alias:'FPC_VAL_CURRENCY_WIDESTR']; compilerproc;
  1202. Var
  1203. SS : String;
  1204. begin
  1205. if length(S) > 255 then
  1206. begin
  1207. fpc_Val_Currency_WideStr:=0;
  1208. code := 256;
  1209. end
  1210. else
  1211. begin
  1212. SS := S;
  1213. Val(SS,fpc_Val_Currency_WideStr,code);
  1214. end;
  1215. end;
  1216. Function fpc_Val_UInt_WideStr (Const S : WideString; out Code : ValSInt): ValUInt; [public, alias:'FPC_VAL_UINT_WIDESTR']; compilerproc;
  1217. Var
  1218. SS : ShortString;
  1219. begin
  1220. fpc_Val_UInt_WideStr := 0;
  1221. if length(S) > 255 then
  1222. code := 256
  1223. else
  1224. begin
  1225. SS := S;
  1226. Val(SS,fpc_Val_UInt_WideStr,code);
  1227. end;
  1228. end;
  1229. Function fpc_Val_SInt_WideStr (DestSize: SizeInt; Const S : WideString; out Code : ValSInt): ValSInt; [public, alias:'FPC_VAL_SINT_WIDESTR']; compilerproc;
  1230. Var
  1231. SS : ShortString;
  1232. begin
  1233. fpc_Val_SInt_WideStr:=0;
  1234. if length(S)>255 then
  1235. code:=256
  1236. else
  1237. begin
  1238. SS := S;
  1239. fpc_Val_SInt_WideStr := int_Val_SInt_ShortStr(DestSize,SS,Code);
  1240. end;
  1241. end;
  1242. {$ifndef CPU64}
  1243. Function fpc_Val_qword_WideStr (Const S : WideString; out Code : ValSInt): qword; [public, alias:'FPC_VAL_QWORD_WIDESTR']; compilerproc;
  1244. Var
  1245. SS : ShortString;
  1246. begin
  1247. fpc_Val_qword_WideStr:=0;
  1248. if length(S)>255 then
  1249. code:=256
  1250. else
  1251. begin
  1252. SS := S;
  1253. Val(SS,fpc_Val_qword_WideStr,Code);
  1254. end;
  1255. end;
  1256. Function fpc_Val_int64_WideStr (Const S : WideString; out Code : ValSInt): Int64; [public, alias:'FPC_VAL_INT64_WIDESTR']; compilerproc;
  1257. Var
  1258. SS : ShortString;
  1259. begin
  1260. fpc_Val_int64_WideStr:=0;
  1261. if length(S)>255 then
  1262. code:=256
  1263. else
  1264. begin
  1265. SS := S;
  1266. Val(SS,fpc_Val_int64_WideStr,Code);
  1267. end;
  1268. end;
  1269. {$endif CPU64}
  1270. {$ifndef FPUNONE}
  1271. procedure fpc_WideStr_Float(d : ValReal;len,fr,rt : SizeInt;out s : WideString);compilerproc;
  1272. var
  1273. ss : shortstring;
  1274. begin
  1275. str_real(len,fr,d,treal_type(rt),ss);
  1276. s:=ss;
  1277. end;
  1278. {$endif}
  1279. procedure fpc_widestr_enum(ordinal,len:sizeint;typinfo,ord2strindex:pointer;out s:widestring);compilerproc;
  1280. var ss:shortstring;
  1281. begin
  1282. fpc_shortstr_enum(ordinal,len,typinfo,ord2strindex,ss);
  1283. s:=ss;
  1284. end;
  1285. {$ifdef FPC_HAS_STR_CURRENCY}
  1286. procedure fpc_WideStr_Currency(c : Currency;len,fr : SizeInt;out s : WideString);compilerproc;
  1287. var
  1288. ss : shortstring;
  1289. begin
  1290. str(c:len:fr,ss);
  1291. s:=ss;
  1292. end;
  1293. {$endif FPC_HAS_STR_CURRENCY}
  1294. Procedure fpc_WideStr_SInt(v : ValSint; Len : SizeInt; out S : WideString);compilerproc;
  1295. Var
  1296. SS : ShortString;
  1297. begin
  1298. Str (v:Len,SS);
  1299. S:=SS;
  1300. end;
  1301. Procedure fpc_WideStr_UInt(v : ValUInt;Len : SizeInt; out S : WideString);compilerproc;
  1302. Var
  1303. SS : ShortString;
  1304. begin
  1305. str(v:Len,SS);
  1306. S:=SS;
  1307. end;
  1308. {$ifndef CPU64}
  1309. Procedure fpc_WideStr_Int64(v : Int64; Len : SizeInt; out S : WideString);compilerproc;
  1310. Var
  1311. SS : ShortString;
  1312. begin
  1313. Str (v:Len,SS);
  1314. S:=SS;
  1315. end;
  1316. Procedure fpc_WideStr_Qword(v : Qword;Len : SizeInt; out S : WideString);compilerproc;
  1317. Var
  1318. SS : ShortString;
  1319. begin
  1320. str(v:Len,SS);
  1321. S:=SS;
  1322. end;
  1323. {$endif CPU64}
  1324. function UnicodeToUtf8(Dest: PChar; Source: PWideChar; MaxBytes: SizeInt): SizeInt;{$ifdef SYSTEMINLINE}inline;{$endif}
  1325. begin
  1326. if assigned(Source) then
  1327. Result:=UnicodeToUtf8(Dest,MaxBytes,Source,IndexWord(Source^,-1,0))
  1328. else
  1329. Result:=0;
  1330. end;
  1331. function UnicodeToUtf8(Dest: PChar; MaxDestBytes: SizeUInt; Source: PWideChar; SourceChars: SizeUInt): SizeUInt;
  1332. var
  1333. i,j : SizeUInt;
  1334. w : word;
  1335. begin
  1336. result:=0;
  1337. if source=nil then
  1338. exit;
  1339. i:=0;
  1340. j:=0;
  1341. if assigned(Dest) then
  1342. begin
  1343. while (i<SourceChars) and (j<MaxDestBytes) do
  1344. begin
  1345. w:=word(Source[i]);
  1346. case w of
  1347. 0..$7f:
  1348. begin
  1349. Dest[j]:=char(w);
  1350. inc(j);
  1351. end;
  1352. $80..$7ff:
  1353. begin
  1354. if j+1>=MaxDestBytes then
  1355. break;
  1356. Dest[j]:=char($c0 or (w shr 6));
  1357. Dest[j+1]:=char($80 or (w and $3f));
  1358. inc(j,2);
  1359. end;
  1360. else
  1361. begin
  1362. if j+2>=MaxDestBytes then
  1363. break;
  1364. Dest[j]:=char($e0 or (w shr 12));
  1365. Dest[j+1]:=char($80 or ((w shr 6)and $3f));
  1366. Dest[j+2]:=char($80 or (w and $3f));
  1367. inc(j,3);
  1368. end;
  1369. end;
  1370. inc(i);
  1371. end;
  1372. if j>SizeUInt(MaxDestBytes-1) then
  1373. j:=MaxDestBytes-1;
  1374. Dest[j]:=#0;
  1375. end
  1376. else
  1377. begin
  1378. while i<SourceChars do
  1379. begin
  1380. case word(Source[i]) of
  1381. $0..$7f:
  1382. inc(j);
  1383. $80..$7ff:
  1384. inc(j,2);
  1385. else
  1386. inc(j,3);
  1387. end;
  1388. inc(i);
  1389. end;
  1390. end;
  1391. result:=j+1;
  1392. end;
  1393. function Utf8ToUnicode(Dest: PWideChar; Source: PChar; MaxChars: SizeInt): SizeInt;{$ifdef SYSTEMINLINE}inline;{$endif}
  1394. begin
  1395. if assigned(Source) then
  1396. Result:=Utf8ToUnicode(Dest,MaxChars,Source,strlen(Source))
  1397. else
  1398. Result:=0;
  1399. end;
  1400. function Utf8ToUnicode(Dest: PWideChar; MaxDestChars: SizeUInt; Source: PChar; SourceBytes: SizeUInt): SizeUInt;
  1401. var
  1402. i,j : SizeUInt;
  1403. w: SizeUInt;
  1404. b : byte;
  1405. begin
  1406. if not assigned(Source) then
  1407. begin
  1408. result:=0;
  1409. exit;
  1410. end;
  1411. result:=SizeUInt(-1);
  1412. i:=0;
  1413. j:=0;
  1414. if assigned(Dest) then
  1415. begin
  1416. while (j<MaxDestChars) and (i<SourceBytes) do
  1417. begin
  1418. b:=byte(Source[i]);
  1419. w:=b;
  1420. inc(i);
  1421. // 2 or 3 bytes?
  1422. if b>=$80 then
  1423. begin
  1424. w:=b and $3f;
  1425. if i>=SourceBytes then
  1426. exit;
  1427. // 3 bytes?
  1428. if (b and $20)<>0 then
  1429. begin
  1430. b:=byte(Source[i]);
  1431. inc(i);
  1432. if i>=SourceBytes then
  1433. exit;
  1434. if (b and $c0)<>$80 then
  1435. exit;
  1436. w:=(w shl 6) or (b and $3f);
  1437. end;
  1438. b:=byte(Source[i]);
  1439. w:=(w shl 6) or (b and $3f);
  1440. if (b and $c0)<>$80 then
  1441. exit;
  1442. inc(i);
  1443. end;
  1444. Dest[j]:=WideChar(w);
  1445. inc(j);
  1446. end;
  1447. if j>=MaxDestChars then j:=MaxDestChars-1;
  1448. Dest[j]:=#0;
  1449. end
  1450. else
  1451. begin
  1452. while i<SourceBytes do
  1453. begin
  1454. b:=byte(Source[i]);
  1455. inc(i);
  1456. // 2 or 3 bytes?
  1457. if b>=$80 then
  1458. begin
  1459. if i>=SourceBytes then
  1460. exit;
  1461. // 3 bytes?
  1462. b := b and $3f;
  1463. if (b and $20)<>0 then
  1464. begin
  1465. b:=byte(Source[i]);
  1466. inc(i);
  1467. if i>=SourceBytes then
  1468. exit;
  1469. if (b and $c0)<>$80 then
  1470. exit;
  1471. end;
  1472. if (byte(Source[i]) and $c0)<>$80 then
  1473. exit;
  1474. inc(i);
  1475. end;
  1476. inc(j);
  1477. end;
  1478. end;
  1479. result:=j+1;
  1480. end;
  1481. function UTF8Encode(const s : WideString) : UTF8String;
  1482. var
  1483. i : SizeInt;
  1484. hs : UTF8String;
  1485. begin
  1486. result:='';
  1487. if s='' then
  1488. exit;
  1489. SetLength(hs,length(s)*3);
  1490. i:=UnicodeToUtf8(pchar(hs),length(hs)+1,PWideChar(s),length(s));
  1491. if i>0 then
  1492. begin
  1493. SetLength(hs,i-1);
  1494. result:=hs;
  1495. end;
  1496. end;
  1497. function UTF8Decode(const s : UTF8String): WideString;
  1498. var
  1499. i : SizeInt;
  1500. hs : WideString;
  1501. begin
  1502. result:='';
  1503. if s='' then
  1504. exit;
  1505. SetLength(hs,length(s));
  1506. i:=Utf8ToUnicode(PWideChar(hs),length(hs)+1,pchar(s),length(s));
  1507. if i>0 then
  1508. begin
  1509. SetLength(hs,i-1);
  1510. result:=hs;
  1511. end;
  1512. end;
  1513. function AnsiToUtf8(const s : ansistring): UTF8String;{$ifdef SYSTEMINLINE}inline;{$endif}
  1514. begin
  1515. Result:=Utf8Encode(s);
  1516. end;
  1517. function Utf8ToAnsi(const s : UTF8String) : ansistring;{$ifdef SYSTEMINLINE}inline;{$endif}
  1518. begin
  1519. Result:=Utf8Decode(s);
  1520. end;
  1521. { converts an utf-16 code point or surrogate pair to utf-32 }
  1522. function utf16toutf32(const S: WideString; const index: SizeInt; out len: longint): UCS4Char; [public, alias: 'FPC_WIDETOUTF32'];
  1523. var
  1524. w: widechar;
  1525. begin
  1526. { UTF-16 points in the range #$0-#$D7FF and #$E000-#$FFFF }
  1527. { are the same in UTF-32 }
  1528. w:=s[index];
  1529. if (w<=#$d7ff) or
  1530. (w>=#$e000) then
  1531. begin
  1532. result:=UCS4Char(w);
  1533. len:=1;
  1534. end
  1535. { valid surrogate pair? }
  1536. else if (w<=#$dbff) and
  1537. { w>=#$d7ff check not needed, checked above }
  1538. (index<length(s)) and
  1539. (s[index+1]>=#$dc00) and
  1540. (s[index+1]<=#$dfff) then
  1541. { convert the surrogate pair to UTF-32 }
  1542. begin
  1543. result:=(UCS4Char(w)-$d800) shl 10 + (UCS4Char(s[index+1])-$dc00) + $10000;
  1544. len:=2;
  1545. end
  1546. else
  1547. { invalid surrogate -> do nothing }
  1548. begin
  1549. result:=UCS4Char(w);
  1550. len:=1;
  1551. end;
  1552. end;
  1553. function WideStringToUCS4String(const s : WideString) : UCS4String;
  1554. var
  1555. i, slen,
  1556. destindex : SizeInt;
  1557. len : longint;
  1558. begin
  1559. slen:=length(s);
  1560. setlength(result,slen+1);
  1561. i:=1;
  1562. destindex:=0;
  1563. while (i<=slen) do
  1564. begin
  1565. result[destindex]:=utf16toutf32(s,i,len);
  1566. inc(destindex);
  1567. inc(i,len);
  1568. end;
  1569. { destindex <= slen (surrogate pairs may have been merged) }
  1570. { destindex+1 for terminating #0 (dynamic arrays are }
  1571. { implicitely filled with zero) }
  1572. setlength(result,destindex+1);
  1573. end;
  1574. { concatenates an utf-32 char to a widestring. S *must* be unique when entering. }
  1575. procedure ConcatUTF32ToWideStr(const nc: UCS4Char; var S: WideString; var index: SizeInt);
  1576. var
  1577. p : PWideChar;
  1578. begin
  1579. { if nc > $ffff, we need two places }
  1580. if (index+ord(nc > $ffff)>length(s)) then
  1581. if (length(s) < 10*256) then
  1582. setlength(s,length(s)+10)
  1583. else
  1584. setlength(s,length(s)+length(s) shr 8);
  1585. { we know that s is unique -> avoid uniquestring calls}
  1586. p:=@s[index];
  1587. if (nc<$ffff) then
  1588. begin
  1589. p^:=widechar(nc);
  1590. inc(index);
  1591. end
  1592. else if (dword(nc)<=$10ffff) then
  1593. begin
  1594. p^:=widechar((nc - $10000) shr 10 + $d800);
  1595. (p+1)^:=widechar((nc - $10000) and $3ff + $dc00);
  1596. inc(index,2);
  1597. end
  1598. else
  1599. { invalid code point }
  1600. begin
  1601. p^:='?';
  1602. inc(index);
  1603. end;
  1604. end;
  1605. function UCS4StringToWideString(const s : UCS4String) : WideString;
  1606. var
  1607. i : SizeInt;
  1608. resindex : SizeInt;
  1609. begin
  1610. { skip terminating #0 }
  1611. SetLength(result,length(s)-1);
  1612. resindex:=1;
  1613. for i:=0 to high(s)-1 do
  1614. ConcatUTF32ToWideStr(s[i],result,resindex);
  1615. { adjust result length (may be too big due to growing }
  1616. { for surrogate pairs) }
  1617. setlength(result,resindex-1);
  1618. end;
  1619. const
  1620. SNoWidestrings = 'This binary has no widestrings support compiled in.';
  1621. SRecompileWithWidestrings = 'Recompile the application with a widestrings-manager in the program uses clause.';
  1622. procedure unimplementedwidestring;
  1623. begin
  1624. {$ifdef FPC_HAS_FEATURE_CONSOLEIO}
  1625. If IsConsole then
  1626. begin
  1627. Writeln(StdErr,SNoWidestrings);
  1628. Writeln(StdErr,SRecompileWithWidestrings);
  1629. end;
  1630. {$endif FPC_HAS_FEATURE_CONSOLEIO}
  1631. HandleErrorFrame(233,get_frame);
  1632. end;
  1633. {$warnings off}
  1634. function GenericWideCase(const s : WideString) : WideString;
  1635. begin
  1636. unimplementedwidestring;
  1637. end;
  1638. function CompareWideString(const s1, s2 : WideString) : PtrInt;
  1639. begin
  1640. unimplementedwidestring;
  1641. end;
  1642. function CompareTextWideString(const s1, s2 : WideString): PtrInt;
  1643. begin
  1644. unimplementedwidestring;
  1645. end;
  1646. function CharLengthPChar(const Str: PChar): PtrInt;
  1647. begin
  1648. unimplementedwidestring;
  1649. end;
  1650. {$warnings on}
  1651. procedure initwidestringmanager;
  1652. begin
  1653. fillchar(widestringmanager,sizeof(widestringmanager),0);
  1654. {$ifndef HAS_WIDESTRINGMANAGER}
  1655. widestringmanager.Wide2AnsiMoveProc:=@defaultWide2AnsiMove;
  1656. widestringmanager.Ansi2WideMoveProc:=@defaultAnsi2WideMove;
  1657. widestringmanager.UpperWideStringProc:=@GenericWideCase;
  1658. widestringmanager.LowerWideStringProc:=@GenericWideCase;
  1659. {$endif HAS_WIDESTRINGMANAGER}
  1660. widestringmanager.CompareWideStringProc:=@CompareWideString;
  1661. widestringmanager.CompareTextWideStringProc:=@CompareTextWideString;
  1662. widestringmanager.CharLengthPCharProc:=@CharLengthPChar;
  1663. end;