jastrings.inc 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2000 by Michael Van Canneyt,
  4. member of the Free Pascal development team.
  5. This file implements AnsiStrings for 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. { This will release some functions for special shortstring support }
  13. { define EXTRAANSISHORT}
  14. constructor AnsistringClass.Create(len: longint; cp: TSystemCodePage);
  15. begin
  16. fElementSize:=1;
  17. { +1 for terminating #0 }
  18. setlength(fdata,len+1);
  19. fCodePage:=cp;
  20. end;
  21. constructor AnsistringClass.Create(const arr: array of ansichar; length: longint; cp: TSystemCodePage);
  22. begin
  23. fElementSize:=1;
  24. fCodePage:=cp;
  25. { make explicit copy so that changing the array afterwards doesn't change
  26. the string }
  27. if length=0 then
  28. begin
  29. { terminating #0 }
  30. setlength(fdata,1);
  31. exit;
  32. end;
  33. setlength(fdata,length+1);
  34. JLSystem.ArrayCopy(JLObject(@arr),0,JLObject(fdata),0,length);
  35. // last char is already #0 because of setlength
  36. end;
  37. constructor AnsistringClass.Create(const arr: array of unicodechar; cp: TSystemCodePage);
  38. var
  39. temp: RawByteString;
  40. begin
  41. fElementSize:=1;
  42. fCodePage:=cp;
  43. if high(arr)=-1 then
  44. begin
  45. { terminating #0 }
  46. setlength(fdata,1);
  47. exit;
  48. end;
  49. widestringmanager.Unicode2AnsiMoveProc(punicodechar(@arr),temp,cp,system.length(arr));
  50. fdata:=AnsistringClass(temp).fdata;
  51. // last char is already #0 because of Unicode2AnsiMoveProc()
  52. end;
  53. constructor AnsistringClass.Create(const u: unicodestring; cp: TSystemCodePage);
  54. var
  55. temp: RawByteString;
  56. begin
  57. fElementSize:=1;
  58. fCodePage:=cp;
  59. if system.length(u)=0 then
  60. begin
  61. { terminating #0 }
  62. setlength(fdata,1);
  63. exit;
  64. end;
  65. widestringmanager.Unicode2AnsiMoveProc(punicodechar(JLString(u).toCharArray),temp,cp,system.length(u));
  66. fdata:=AnsistringClass(temp).fdata;
  67. // last char is already #0 because of Unicode2AnsiMoveProc()
  68. end;
  69. constructor AnsistringClass.Create(const u: unicodestring);
  70. begin
  71. { for use in Java code }
  72. Create(u,DefaultSystemCodePage);
  73. end;
  74. constructor AnsistringClass.Create(const a: RawByteString; cp: TSystemCodePage);
  75. begin
  76. Create(AnsistringClass(a).fdata,system.length(AnsistringClass(a).fdata)-1,cp);
  77. end;
  78. constructor AnsistringClass.Create(const s: shortstring; cp: TSystemCodePage);
  79. begin
  80. Create(ShortstringClass(@s).fdata,system.length(s),cp);
  81. end;
  82. constructor AnsistringClass.Create(ch: ansichar; cp: TSystemCodePage);
  83. var
  84. arr: array[0..0] of ansichar;
  85. begin
  86. fElementSize:=1;
  87. fCodePage:=cp;
  88. setlength(fdata,2);
  89. fdata[0]:=ch;
  90. // last char is already #0 because of setlength
  91. end;
  92. constructor AnsistringClass.Create(ch: unicodechar; cp: TSystemCodePage);
  93. var
  94. temp: RawByteString;
  95. arr: array[0..0] of unicodechar;
  96. begin
  97. fElementSize:=1;
  98. fCodePage:=cp;
  99. arr[0]:=ch;
  100. widestringmanager.Unicode2AnsiMoveProc(punicodechar(@arr),temp,cp,system.length(arr));
  101. fdata:=AnsistringClass(temp).fdata;
  102. end;
  103. class function AnsistringClass.CreateFromLiteralStringBytes(const u: unicodestring; cp: TSystemCodePage): RawByteString;
  104. var
  105. res: AnsistringClass;
  106. i: longint;
  107. begin
  108. { used to construct constant ansistrings from Java string constants }
  109. res:=AnsistringClass.Create(system.length(u),cp);
  110. for i:=1 to system.length(u) do
  111. res.fdata[i-1]:=ansichar(ord(u[i]));
  112. result:=ansistring(res);
  113. end;
  114. function AnsistringClass.charAt(index: jint): ansichar;
  115. begin
  116. { index is already decreased by one, because same calling code is used for
  117. JLString.charAt() }
  118. result:=fdata[index];
  119. end;
  120. function AnsistringClass.toUnicodeString: unicodestring;
  121. begin
  122. widestringmanager.Ansi2UnicodeMoveProc(pchar(fdata),fCodePage,result,system.length(fdata)-1);
  123. end;
  124. function AnsistringClass.toShortstring(maxlen: byte): shortstring;
  125. begin
  126. ShortstringClass(@result).copyFromAnsiCharArray(fData,maxlen);
  127. end;
  128. function AnsistringClass.toString: JLString;
  129. begin
  130. result:=JLString(toUnicodeString);
  131. end;
  132. (*
  133. function AnsistringClass.concat(const a: ansistring): ansistring;
  134. var
  135. newdata: array of ansichar;
  136. addlen: sizeint;
  137. begin
  138. addlen:=length(a);
  139. thislen:=this.length;
  140. setlength(newdata,addlen+thislen);
  141. if thislen>0 then
  142. JLSystem.ArrayCopy(JLObject(fdata),0,JLObject(newdata),0,thislen);
  143. if addlen>0 then
  144. JLSystem.ArrayCopy(JLObject(AnsistringClass(a).fdata),0,JLObject(newdata),thislen,addlen);
  145. end;
  146. procedure AnsistringClass.concatmultiple(const arr: array of ansistring): ansistring;
  147. Var
  148. i : longint;
  149. size, newsize : sizeint;
  150. curlen, addlen : sizeint
  151. newdata: array of ansichar;
  152. begin
  153. { First calculate size of the result so we can allocate an array of
  154. the right size }
  155. NewSize:=0;
  156. for i:=low(arr) to high(arr) do
  157. inc(newsize,length(arr[i]));
  158. setlength(newdata,newsize);
  159. curlen
  160. for i:=low(arr) to high(arr) do
  161. begin
  162. if length(arr[i])>0 then
  163. sb.append(arr[i]);
  164. end;
  165. DestS:=sb.toString;
  166. end;
  167. *)
  168. function AnsiStringClass.length: jint;
  169. begin
  170. result:=system.length(fdata)-1;
  171. end;
  172. function AnsistringClass.codePage: TSystemCodePage;
  173. begin
  174. result:=fCodePage;
  175. end;
  176. function AnsistringClass.elementSize: Word;
  177. begin
  178. result:=fElementSize;
  179. end;
  180. class function AnsistringClass.internChars(const a: Ansistring): TAnsiCharArray;
  181. begin
  182. if a<>'' then
  183. result:=AnsistringClass(a).fdata
  184. else
  185. { empty pchar: array with one element that is #0 }
  186. setlength(result,1);
  187. end;
  188. {****************************************************************************
  189. Internal functions, not in interface.
  190. ****************************************************************************}
  191. {$ifndef FPC_HAS_PCHAR_ANSISTR_INTERN_CHARMOVE}
  192. {$define FPC_HAS_PCHAR_ANSISTR_INTERN_CHARMOVE}
  193. procedure fpc_pchar_ansistr_intern_charmove(const src: pchar; const srcindex: sizeint; var dst: ansistring; const dstindex, len: sizeint); {$ifdef FPC_HAS_CPSTRING}rtlproc;{$endif} {$ifdef SYSTEMINLINE}inline;{$endif}
  194. begin
  195. JLSystem.arraycopy(JLObject(src),srcindex,JLObject(AnsistringClass(dst).fdata),dstindex,len);
  196. end;
  197. {$endif FPC_HAS_PCHAR_ANSISTR_INTERN_CHARMOVE}
  198. {$ifndef FPC_HAS_PCHAR_PCHAR_INTERN_CHARMOVE}
  199. {$define FPC_HAS_PCHAR_PCHAR_INTERN_CHARMOVE}
  200. procedure fpc_pchar_pchar_intern_charmove(const src: pchar; const srcindex: sizeint; const dst: pchar; const dstindex, len: sizeint); {$ifdef FPC_HAS_CPSTRING}rtlproc;{$endif} {$ifdef SYSTEMINLINE}inline;{$endif}
  201. begin
  202. JLSystem.arraycopy(JLObject(src),srcindex,JLObject(dst),dstindex,len);
  203. end;
  204. {$endif FPC_HAS_PCHAR_PCHAR_INTERN_CHARMOVE}
  205. {$ifndef FPC_HAS_SHORTSTR_ANSISTR_INTERN_CHARMOVE}
  206. {$define FPC_HAS_SHORTSTR_ANSISTR_INTERN_CHARMOVE}
  207. procedure fpc_shortstr_ansistr_intern_charmove(const src: shortstring; const srcindex: sizeint; var dst: rawbytestring; const dstindex, len: sizeint); {$ifdef FPC_HAS_CPSTRING}rtlproc;{$endif} {$ifdef SYSTEMINLINE}inline;{$endif}
  208. begin
  209. JLSystem.arraycopy(JLObject(ShortStringClass(@src).fdata),srcindex-1,JLObject(AnsistringClass(dst).fdata),dstindex,len);
  210. end;
  211. {$endif FPC_HAS_SHORTSTR_ANSISTR_INTERN_CHARMOVE}
  212. {$define FPC_HAS_NEWANSISTR}
  213. Function NewAnsiString(Len : SizeInt) : Pointer;
  214. {
  215. Allocate a new AnsiString on the heap.
  216. initialize it to zero length and reference count 1.
  217. }
  218. begin
  219. result:=AnsistringClass.Create(len,DefaultSystemCodePage);
  220. end;
  221. { not required }
  222. {$define FPC_SYSTEM_HAS_ANSISTR_DECR_REF}
  223. {$define FPC_SYSTEM_HAS_ANSISTR_INCR_REF}
  224. {$define FPC_HAS_ANSISTR_ASSIGN}
  225. {$ifndef FPC_HAS_ANSISTR_CONCAT_COMPLEX}
  226. {$define FPC_HAS_ANSISTR_CONCAT_COMPLEX}
  227. { keeps implicit try..finally block out from primary control flow }
  228. procedure ansistr_concat_complex(var DestS: RawByteString; const S1,S2: RawByteString; cp: TSystemCodePage);
  229. var
  230. U: UnicodeString;
  231. begin
  232. U:=UnicodeString(S1)+UnicodeString(S2);
  233. widestringmanager.Unicode2AnsiMoveProc(PUnicodeChar(JLString(U).toCharArray),DestS,cp,Length(U));
  234. end;
  235. {$endif FPC_HAS_ANSISTR_CONCAT_COMPLEX}
  236. {$define FPC_HAS_ANSISTR_TO_ANSISTR}
  237. Function fpc_AnsiStr_To_AnsiStr (const S : RawByteString;cp : TSystemCodePage): RawByteString; compilerproc;
  238. {
  239. Converts an AnsiString to an AnsiString taking code pages into care
  240. }
  241. Var
  242. Size : SizeInt;
  243. temp : UnicodeString;
  244. orgcp: TSystemCodePage;
  245. begin
  246. result:='';
  247. Size:=Length(S);
  248. if Size>0 then
  249. begin
  250. if (cp=CP_ACP) then
  251. cp:=DefaultSystemCodePage;
  252. orgcp:=StringCodePage(S);
  253. if (orgcp=CP_ACP) then
  254. orgcp:=DefaultSystemCodePage;
  255. if (orgcp=cp) or (orgcp=CP_NONE) then
  256. begin
  257. result:=RawByteString(AnsistringClass.Create(S,cp));
  258. end
  259. else
  260. begin
  261. temp:=UnicodeString(S);
  262. Size:=Length(temp);
  263. widestringmanager.Unicode2AnsiMoveProc(PUnicodeChar(JLString(temp).toCharArray),result,cp,Size);
  264. end;
  265. end;
  266. end;
  267. Function fpc_AnsiStr_To_AnsiStr (const S : RawByteString;cp : TSystemCodePage): RawByteString; [external name 'fpc_ansistr_to_ansistr'];
  268. {$define FPC_HAS_ANSISTR_CONCAT_MULTI}
  269. procedure fpc_AnsiStr_Concat_multi (var DestS:RawByteString;const sarr:array of RawByteString{$ifdef FPC_HAS_CPSTRING};cp : TSystemCodePage{$endif FPC_HAS_CPSTRING}); compilerproc;
  270. Var
  271. lowstart,i : Longint;
  272. p : pointer;
  273. Size,NewLen,
  274. OldDestLen : SizeInt;
  275. destcopy : RawByteString;
  276. DestCP : TSystemCodePage;
  277. U : UnicodeString;
  278. sameCP : Boolean;
  279. tmpStr : RawByteString;
  280. tmpCP : TSystemCodePage;
  281. begin
  282. if high(sarr)=0 then
  283. begin
  284. DestS:='';
  285. exit;
  286. end;
  287. {$ifdef FPC_HAS_CPSTRING}
  288. if (Pointer(DestS)=nil) then
  289. DestCP:=cp
  290. else
  291. DestCP:=StringCodePage(DestS);
  292. {$else FPC_HAS_CPSTRING}
  293. DestCP:=StringCodePage(DestS);
  294. {$endif FPC_HAS_CPSTRING}
  295. if (DestCP=CP_ACP) then
  296. DestCP:=DefaultSystemCodePage;
  297. sameCP:=true;
  298. lowstart:=low(sarr);
  299. for i:=lowstart to high(sarr) do
  300. begin
  301. tmpCP:=StringCodePage(sarr[i]);
  302. if tmpCP=CP_ACP then
  303. tmpCP:=DefaultSystemCodePage;
  304. if (DestCP<>tmpCp) then
  305. begin
  306. sameCP:=false;
  307. break;
  308. end;
  309. end;
  310. if not sameCP then
  311. begin
  312. U:='';
  313. for i:=lowstart to high(sarr) do begin
  314. tmpCP:=StringCodePage(sarr[i]);
  315. if (tmpCP=CP_ACP) then
  316. begin
  317. tmpStr:=sarr[i];
  318. SetCodePage(tmpStr,DefaultSystemCodePage,False);
  319. U:=U+UnicodeString(tmpStr);
  320. end
  321. else
  322. U:=U+UnicodeString(sarr[i]);
  323. end;
  324. DestS:='';
  325. widestringmanager.Unicode2AnsiMoveProc(PUnicodeChar(JLString(U).toCharArray),DestS,DestCP,Length(U));
  326. exit;
  327. end;
  328. lowstart:=low(sarr);
  329. if Pointer(DestS)=Pointer(sarr[lowstart]) then
  330. inc(lowstart);
  331. { Check for another reuse, then we can't use
  332. the append optimization }
  333. for i:=lowstart to high(sarr) do
  334. begin
  335. if Pointer(DestS)=Pointer(sarr[i]) then
  336. begin
  337. { if DestS is used somewhere in the middle of the expression,
  338. we need to make sure the original string still exists after
  339. we empty/modify DestS -- not necessary on JVM platform, ansistrings
  340. are not explicitly refrence counted there }
  341. lowstart:=low(sarr);
  342. break;
  343. end;
  344. end;
  345. { Start with empty DestS if we start with concatting
  346. the first array element }
  347. if lowstart=low(sarr) then
  348. DestS:='';
  349. OldDestLen:=length(DestS);
  350. { Calculate size of the result so we can do
  351. a single call to SetLength() }
  352. NewLen:=0;
  353. for i:=low(sarr) to high(sarr) do
  354. inc(NewLen,length(sarr[i]));
  355. SetLength(DestS,NewLen);
  356. if (StringCodePage(DestS) <> DestCP) then
  357. SetCodePage(DestS,DestCP,False);
  358. { Concat all strings, except the string we already
  359. copied in DestS }
  360. NewLen:=OldDestLen;
  361. for i:=lowstart to high(sarr) do
  362. begin
  363. p:=pointer(sarr[i]);
  364. if assigned(p) then
  365. begin
  366. Size:=length(ansistring(p));
  367. fpc_pchar_pchar_intern_charmove(pchar(ansistring(p)),0,pchar(DestS),NewLen,Size+1);
  368. inc(NewLen,size);
  369. end;
  370. end;
  371. end;
  372. {$define FPC_HAS_ANSISTR_TO_SHORTSTR}
  373. procedure fpc_AnsiStr_To_ShortStr (out res: shortstring; const S2 : RawByteString);[Public, alias: 'FPC_ANSISTR_TO_SHORTSTR']; compilerproc;
  374. {
  375. Converts a AnsiString to a ShortString;
  376. }
  377. Var
  378. Size : SizeInt;
  379. begin
  380. if S2='' then
  381. res:=''
  382. else
  383. begin
  384. Size:=Length(S2);
  385. If Size>high(res) then
  386. Size:=high(res);
  387. if Size>0 then
  388. JLSystem.ArrayCopy(JLObject(AnsistringClass(S2).fdata),0,JLObject(ShortstringClass(@res).fdata),0,Size);
  389. setlength(res,size);
  390. end;
  391. end;
  392. {$define FPC_HAS_PCHAR_TO_ANSISTR}
  393. Function fpc_PChar_To_AnsiStr(const p : PAnsiChar{$ifdef FPC_HAS_CPSTRING};cp : TSystemCodePage{$endif FPC_HAS_CPSTRING}): RawByteString; compilerproc;
  394. Var
  395. L : SizeInt;
  396. {$ifndef FPC_HAS_CPSTRING}
  397. cp : TSystemCodePage;
  398. {$endif FPC_HAS_CPSTRING}
  399. begin
  400. if (not assigned(p)) or (p[0]=#0) Then
  401. L := 0
  402. else
  403. L:=IndexChar(Arr1jbyte(p),-1,#0);
  404. SetLength(fpc_PChar_To_AnsiStr,L);
  405. if L > 0 then
  406. begin
  407. {$ifdef FPC_HAS_CPSTRING}
  408. if (cp=CP_ACP) then
  409. cp:=DefaultSystemCodePage;
  410. {$else FPC_HAS_CPSTRING}
  411. cp:=DefaultSystemCodePage;
  412. {$endif FPC_HAS_CPSTRING}
  413. fpc_pchar_ansistr_intern_charmove(p,0,fpc_PChar_To_AnsiStr,0,L);
  414. SetCodePage(fpc_PChar_To_AnsiStr,cp,False);
  415. end;
  416. end;
  417. {$define FPC_HAS_ANSISTR_TO_CHARARRAY}
  418. procedure fpc_ansistr_to_chararray(out res: array of AnsiChar; const src: RawByteString); compilerproc;
  419. var
  420. len: longint;
  421. begin
  422. len:=length(src);
  423. if len>length(res) then
  424. len:=length(res);
  425. { make sure we don't try to access element 1 of the ansistring if it's nil }
  426. if len>0 then
  427. JLSystem.ArrayCopy(JLObject(AnsistringClass(src).fdata),0,JLObject(@res),0,len);
  428. if len<=high(res) then
  429. JUArrays.fill(TJByteArray(@res),len,high(res),0);
  430. end;
  431. function fpc_ansistr_setchar(const s: RawByteString; const index: longint; const ch: ansichar): RawByteString; compilerproc;
  432. var
  433. res: AnsistringClass;
  434. begin
  435. res:=AnsistringClass.Create(s,AnsistringClass(s).fCodePage);
  436. res.fdata[index-1]:=ch;
  437. result:=Ansistring(res);
  438. end;
  439. {$define FPC_HAS_ANSISTR_COMPARE}
  440. Function fpc_AnsiStr_Compare(const S1,S2 : RawByteString): SizeInt;[Public,Alias : 'FPC_ANSISTR_COMPARE']; compilerproc;
  441. {
  442. Compares 2 AnsiStrings;
  443. The result is
  444. <0 if S1<S2
  445. 0 if S1=S2
  446. >0 if S1>S2
  447. }
  448. Var
  449. MaxI,Temp, i : SizeInt;
  450. cp1,cp2 : TSystemCodePage;
  451. r1,r2 : RawByteString;
  452. begin
  453. if JLObject(S1)=JLObject(S2) then
  454. begin
  455. result:=0;
  456. exit;
  457. end;
  458. if (pointer(S1)=nil) then
  459. begin
  460. result:=-Length(S2);
  461. exit;
  462. end;
  463. if (pointer(S2)=nil) then
  464. begin
  465. result:=Length(S1);
  466. exit;
  467. end;
  468. cp1:=StringCodePage(S1);
  469. cp2:=StringCodePage(S2);
  470. if cp1=cp2 then
  471. begin
  472. Maxi:=Length(S1);
  473. temp:=Length(S2);
  474. If MaxI>Temp then
  475. MaxI:=Temp;
  476. for i:=0 to MaxI-1 do
  477. begin
  478. result:=ord(AnsistringClass(S1).fdata[i])-ord(AnsistringClass(S2).fdata[i]);
  479. if result<>0 then
  480. exit;
  481. end;
  482. result:=Length(S1)-Length(S2);
  483. end
  484. else
  485. begin
  486. r1:=S1;
  487. if (cp1=CP_ACP) then
  488. SetCodePage(r1,DefaultSystemCodePage,false);
  489. r2:=S2;
  490. if (cp2=CP_ACP) then
  491. SetCodePage(r2,DefaultSystemCodePage,false);
  492. //convert them to utf8 then compare
  493. SetCodePage(r1,65001);
  494. SetCodePage(r2,65001);
  495. Result := fpc_AnsiStr_Compare(r1,r2);
  496. end;
  497. end;
  498. {$define FPC_HAS_ANSISTR_COMPARE_EQUAL}
  499. Function fpc_AnsiStr_Compare_equal(const S1,S2 : RawByteString): SizeInt; compilerproc;
  500. {
  501. Compares 2 AnsiStrings for equality/inequality only;
  502. The result is
  503. 0 if S1=S2
  504. <>0 if S1<>S2
  505. }
  506. Var
  507. MaxI,Temp : SizeInt;
  508. cp1,cp2 : TSystemCodePage;
  509. r1,r2 : RawByteString;
  510. begin
  511. if JLObject(S1)=JLObject(S2) then
  512. begin
  513. result:=0;
  514. exit;
  515. end;
  516. { don't compare strings if one of them is empty }
  517. if (pointer(S1)=nil) then
  518. begin
  519. result:=-Length(S2);
  520. exit;
  521. end;
  522. if (pointer(S2)=nil) then
  523. begin
  524. result:=Length(S1);
  525. exit;
  526. end;
  527. cp1:=StringCodePage(S1);
  528. cp2:=StringCodePage(S2);
  529. if cp1<>cp2 then
  530. begin
  531. r1:=S1;
  532. if (cp1=CP_ACP) then
  533. SetCodePage(r1,DefaultSystemCodePage,false);
  534. r2:=S2;
  535. if (cp2=CP_ACP) then
  536. SetCodePage(r2,DefaultSystemCodePage,false);
  537. //convert them to utf8 then compare
  538. SetCodePage(r1,65001);
  539. SetCodePage(r2,65001);
  540. end
  541. else
  542. begin
  543. r1:=s1;
  544. r2:=s2;
  545. end;
  546. result:=ord(not JUArrays.equals(TJByteArray(AnsistringClass(r1).fdata),TJByteArray(AnsistringClass(r2).fdata)))
  547. end;
  548. { not required, the JVM does the range checking for us }
  549. {$define FPC_HAS_ANSISTR_CHECKRANGE}
  550. {$define FPC_HAS_ANSISTR_SETLENGTH}
  551. Procedure fpc_AnsiStr_SetLength (Var S : RawByteString; l : SizeInt{$ifdef FPC_HAS_CPSTRING};cp : TSystemCodePage{$endif FPC_HAS_CPSTRING});[Public,Alias : 'FPC_ANSISTR_SETLENGTH']; compilerproc;
  552. {
  553. Sets The length of string S to L.
  554. Makes sure S is unique, and contains enough room.
  555. }
  556. var
  557. oldlen: longint;
  558. result: RawByteString;
  559. begin
  560. if (cp=CP_ACP) then
  561. cp:=DefaultSystemCodePage;
  562. { no explicit reference counting possible -> can't reuse S because we don't
  563. know how many references exist to it }
  564. result:=RawByteString(AnsistringClass.Create(l,cp));
  565. oldlen:=length(s);
  566. if l>oldlen then
  567. l:=oldlen;
  568. if l>0 then
  569. JLSystem.ArrayCopy(JLObject(AnsistringClass(S).fdata),0,JLObject(AnsistringClass(result).fdata),0,l);
  570. S:=result;
  571. end;
  572. {*****************************************************************************
  573. Public functions, In interface.
  574. *****************************************************************************}
  575. { lie, not needed }
  576. {$define FPC_SYSTEM_HAS_TRUELY_ANSISTR_UNIQUE}
  577. { can't implement reference counting since no control over what javacc-compiled
  578. code does with ansistrings -> always create a copy }
  579. {$define FPC_SYSTEM_HAS_ANSISTR_UNIQUE}
  580. procedure FPC_ANSISTR_UNIQUE(var s: AnsiString); inline;
  581. begin
  582. s:=ansistring(AnsistringClass.Create(s,AnsiStringClass(s).fCodePage));
  583. end;
  584. {$define FPC_HAS_ANSISTR_COPY}
  585. Function Fpc_Ansistr_Copy(Const S : RawByteString; Index,Size : SizeInt): RawByteString;compilerproc;
  586. var
  587. res: AnsistringClass;
  588. begin
  589. dec(index);
  590. if Index < 0 then
  591. Index := 0;
  592. { Check Size. Accounts for Zero-length S, the double check is needed because
  593. Size can be maxint and will get <0 when adding index }
  594. if (Size>Length(S)) or
  595. (Index+Size>Length(S)) then
  596. Size:=Length(S)-Index;
  597. If Size>0 then
  598. begin
  599. res:=AnsistringClass.Create;
  600. AnsistringClass(res).fcodepage:=AnsistringClass(S).fcodepage;
  601. { +1 for terminating #0 }
  602. setlength(res.fdata,size+1);
  603. JLSystem.ArrayCopy(JLObject(AnsistringClass(S).fdata),index,JLObject(res.fdata),0,size);
  604. result:=ansistring(res);
  605. end;
  606. { default function result is empty string }
  607. end;
  608. {$define FPC_HAS_POS_SHORTSTR_ANSISTR}
  609. Function Pos(Const Substr : ShortString; Const Source : RawByteString) : SizeInt;
  610. var
  611. i,j,k,MaxLen, SubstrLen : SizeInt;
  612. begin
  613. Pos:=0;
  614. SubstrLen:=Length(SubStr);
  615. if SubstrLen>0 then
  616. begin
  617. MaxLen:=Length(source)-Length(SubStr);
  618. i:=0;
  619. while (i<=MaxLen) do
  620. begin
  621. inc(i);
  622. j:=0;
  623. k:=i-1;
  624. while (j<SubstrLen) and
  625. (ShortStringClass(@SubStr).fdata[j]=AnsistringClass(Source).fdata[k]) do
  626. begin
  627. inc(j);
  628. inc(k);
  629. end;
  630. if (j=SubstrLen) then
  631. begin
  632. Pos:=i;
  633. exit;
  634. end;
  635. end;
  636. end;
  637. end;
  638. {$define FPC_HAS_POS_ANSISTR_ANSISTR}
  639. Function Pos(Const Substr : RawByteString; Const Source : RawByteString) : SizeInt;
  640. var
  641. i,j,k,MaxLen, SubstrLen : SizeInt;
  642. begin
  643. Pos:=0;
  644. SubstrLen:=Length(SubStr);
  645. if SubstrLen>0 then
  646. begin
  647. MaxLen:=Length(source)-Length(SubStr);
  648. i:=0;
  649. while (i<=MaxLen) do
  650. begin
  651. inc(i);
  652. j:=0;
  653. k:=i-1;
  654. while (j<SubstrLen) and
  655. (AnsistringClass(SubStr).fdata[j]=AnsistringClass(Source).fdata[k]) do
  656. begin
  657. inc(j);
  658. inc(k);
  659. end;
  660. if (j=SubstrLen) then
  661. begin
  662. Pos:=i;
  663. exit;
  664. end;
  665. end;
  666. end;
  667. end;
  668. {$define FPC_HAS_POS_ANSICHAR_ANSISTR}
  669. { Faster version for a char alone. Must be implemented because }
  670. { pos(c: char; const s: shortstring) also exists, so otherwise }
  671. { using pos(char,pchar) will always call the shortstring version }
  672. { (exact match for first argument), also with $h+ (JM) }
  673. Function Pos (c : AnsiChar; Const s : RawByteString) : SizeInt;
  674. var
  675. i: SizeInt;
  676. begin
  677. for i:=1 to length(s) do
  678. begin
  679. if AnsistringClass(s).fdata[i-1]=c then
  680. begin
  681. pos:=i;
  682. exit;
  683. end;
  684. end;
  685. pos:=0;
  686. end;
  687. {$define FPC_HAS_ANSISTR_OF_CHAR}
  688. Function StringOfChar(c : char;l : SizeInt) : AnsiString;
  689. begin
  690. SetLength(StringOfChar,l);
  691. FillChar(AnsistringClass(result).fdata,l,c);
  692. end;
  693. {$define FPC_HAS_UPCASE_ANSISTR}
  694. function upcase(const s : ansistring) : ansistring;
  695. var
  696. u : unicodestring;
  697. begin
  698. u:=s;
  699. result:=upcase(u);
  700. end;
  701. {$define FPC_HAS_LOWERCASE_ANSISTR}
  702. function lowercase(const s : ansistring) : ansistring;
  703. var
  704. u : unicodestring;
  705. begin
  706. u:=s;
  707. result:=lowercase(u);
  708. end;
  709. {$define FPC_HAS_ANSISTR_STRINGCODEPAGE}
  710. function StringCodePage(const S: RawByteString): TSystemCodePage; overload;
  711. begin
  712. if assigned(pointer(S)) then
  713. Result:=AnsistringClass(S).fCodePage
  714. else
  715. Result:=DefaultSystemCodePage;
  716. end;
  717. {$define FPC_HAS_ANSISTR_STRINGELEMENTSIZE}
  718. function StringElementSize(const S: RawByteString): Word; overload;
  719. begin
  720. if assigned(Pointer(S)) then
  721. Result:=AnsistringClass(S).fElementSize
  722. else
  723. Result:=SizeOf(AnsiChar);
  724. end;
  725. {$define FPC_HAS_ANSISTR_STRINGREFCOUNT}
  726. function StringRefCount(const S: RawByteString): SizeInt; overload;
  727. begin
  728. if assigned(Pointer(S)) then
  729. Result:=1
  730. else
  731. Result:=0;
  732. end;
  733. {$define FPC_HAS_ANSISTR_SETCODEPAGE}
  734. procedure SetCodePage(var s : RawByteString; CodePage : TSystemCodePage; Convert : Boolean = True);
  735. begin
  736. if not assigned(Pointer(S)) or (StringCodePage(S)=CodePage) then
  737. exit
  738. else if (AnsistringClass(S).length<>0) and
  739. Convert then
  740. begin
  741. s:=fpc_AnsiStr_To_AnsiStr(s,CodePage);
  742. end
  743. else
  744. begin
  745. AnsistringClass(S).fCodePage:=CodePage;
  746. end;
  747. end;