sstrings.inc 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1999-2000 by the Free Pascal development team
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. {****************************************************************************
  12. subroutines for string handling
  13. ****************************************************************************}
  14. {$ifndef INTERNSETLENGTH}
  15. procedure SetLength(var s:shortstring;len:StrLenInt);
  16. {$else INTERNSETLENGTH}
  17. procedure fpc_Shortstr_SetLength(var s:shortstring;len:StrLenInt);[Public,Alias : 'FPC_SHORTSTR_SETLENGTH']; {$ifdef hascompilerproc} compilerproc; {$endif}
  18. {$endif INTERNSETLENGTH}
  19. begin
  20. if Len>255 then
  21. Len:=255;
  22. s[0]:=chr(len);
  23. end;
  24. function copy(const s : shortstring;index : StrLenInt;count : StrLenInt): shortstring;
  25. begin
  26. if count<0 then
  27. count:=0;
  28. if index>1 then
  29. dec(index)
  30. else
  31. index:=0;
  32. if index>length(s) then
  33. count:=0
  34. else
  35. if count>length(s)-index then
  36. count:=length(s)-index;
  37. Copy[0]:=chr(Count);
  38. Move(s[Index+1],Copy[1],Count);
  39. end;
  40. procedure delete(var s : shortstring;index : StrLenInt;count : StrLenInt);
  41. begin
  42. if index<=0 then
  43. exit;
  44. if (Index<=Length(s)) and (Count>0) then
  45. begin
  46. if Count>length(s)-Index then
  47. Count:=length(s)-Index+1;
  48. s[0]:=Chr(length(s)-Count);
  49. if Index<=Length(s) then
  50. Move(s[Index+Count],s[Index],Length(s)-Index+1);
  51. end;
  52. end;
  53. procedure insert(const source : shortstring;var s : shortstring;index : StrLenInt);
  54. var
  55. cut,srclen,indexlen : longint;
  56. begin
  57. if index<1 then
  58. index:=1;
  59. if index>length(s) then
  60. index:=length(s)+1;
  61. indexlen:=Length(s)-Index+1;
  62. srclen:=length(Source);
  63. if length(source)+length(s)>=sizeof(s) then
  64. begin
  65. cut:=length(source)+length(s)-sizeof(s)+1;
  66. if cut>indexlen then
  67. begin
  68. dec(srclen,cut-indexlen);
  69. indexlen:=0;
  70. end
  71. else
  72. dec(indexlen,cut);
  73. end;
  74. move(s[Index],s[Index+srclen],indexlen);
  75. move(Source[1],s[Index],srclen);
  76. s[0]:=chr(index+srclen+indexlen-1);
  77. end;
  78. procedure insert(source : Char;var s : shortstring;index : StrLenInt);
  79. var
  80. indexlen : longint;
  81. begin
  82. if index<1 then
  83. index:=1;
  84. if index>length(s) then
  85. index:=length(s)+1;
  86. indexlen:=Length(s)-Index+1;
  87. if (length(s)+1=sizeof(s)) and (indexlen>0) then
  88. dec(indexlen);
  89. move(s[Index],s[Index+1],indexlen);
  90. s[Index]:=Source;
  91. s[0]:=chr(index+indexlen);
  92. end;
  93. function pos(const substr : shortstring;const s : shortstring):StrLenInt;
  94. var
  95. i,MaxLen : StrLenInt;
  96. pc : pchar;
  97. begin
  98. Pos:=0;
  99. if Length(SubStr)>0 then
  100. begin
  101. MaxLen:=Length(s)-Length(SubStr);
  102. i:=0;
  103. pc:=@s[1];
  104. while (i<=MaxLen) do
  105. begin
  106. inc(i);
  107. if (SubStr[1]=pc^) and
  108. (CompareChar(Substr[1],pc^,Length(SubStr))=0) then
  109. begin
  110. Pos:=i;
  111. exit;
  112. end;
  113. inc(pc);
  114. end;
  115. end;
  116. end;
  117. {Faster when looking for a single char...}
  118. function pos(c:char;const s:shortstring):StrLenInt;
  119. var
  120. i : StrLenInt;
  121. pc : pchar;
  122. begin
  123. pc:=@s[1];
  124. for i:=1 to length(s) do
  125. begin
  126. if pc^=c then
  127. begin
  128. pos:=i;
  129. exit;
  130. end;
  131. inc(pc);
  132. end;
  133. pos:=0;
  134. end;
  135. function copy(c:char;index : StrLenInt;count : StrLenInt): shortstring;
  136. begin
  137. if (index=1) and (Count>0) then
  138. Copy:=c
  139. else
  140. Copy:='';
  141. end;
  142. function pos(const substr : shortstring;c:char): StrLenInt;
  143. begin
  144. if (length(substr)=1) and (substr[1]=c) then
  145. Pos:=1
  146. else
  147. Pos:=0;
  148. end;
  149. {$ifdef IBM_CHAR_SET}
  150. const
  151. UpCaseTbl : shortstring[7]=#154#142#153#144#128#143#165;
  152. LoCaseTbl : shortstring[7]=#129#132#148#130#135#134#164;
  153. {$endif}
  154. function upcase(c : char) : char;
  155. {$IFDEF IBM_CHAR_SET}
  156. var
  157. i : longint;
  158. {$ENDIF}
  159. begin
  160. if (c in ['a'..'z']) then
  161. upcase:=char(byte(c)-32)
  162. else
  163. {$IFDEF IBM_CHAR_SET}
  164. begin
  165. i:=Pos(c,LoCaseTbl);
  166. if i>0 then
  167. upcase:=UpCaseTbl[i]
  168. else
  169. upcase:=c;
  170. end;
  171. {$ELSE}
  172. upcase:=c;
  173. {$ENDIF}
  174. end;
  175. function upcase(const s : shortstring) : shortstring;
  176. var
  177. i : longint;
  178. begin
  179. upcase[0]:=s[0];
  180. for i := 1 to length (s) do
  181. upcase[i] := upcase (s[i]);
  182. end;
  183. function lowercase(c : char) : char;overload;
  184. {$IFDEF IBM_CHAR_SET}
  185. var
  186. i : longint;
  187. {$ENDIF}
  188. begin
  189. if (c in ['A'..'Z']) then
  190. lowercase:=char(byte(c)+32)
  191. else
  192. {$IFDEF IBM_CHAR_SET}
  193. begin
  194. i:=Pos(c,UpCaseTbl);
  195. if i>0 then
  196. lowercase:=LoCaseTbl[i]
  197. else
  198. lowercase:=c;
  199. end;
  200. {$ELSE}
  201. lowercase:=c;
  202. {$ENDIF}
  203. end;
  204. function lowercase(const s : shortstring) : shortstring; overload;
  205. var
  206. i : longint;
  207. begin
  208. lowercase [0]:=s[0];
  209. for i:=1 to length(s) do
  210. lowercase[i]:=lowercase (s[i]);
  211. end;
  212. const
  213. HexTbl : array[0..15] of char='0123456789ABCDEF';
  214. function hexstr(val : longint;cnt : byte) : shortstring;
  215. var
  216. i : longint;
  217. begin
  218. hexstr[0]:=char(cnt);
  219. for i:=cnt downto 1 do
  220. begin
  221. hexstr[i]:=hextbl[val and $f];
  222. val:=val shr 4;
  223. end;
  224. end;
  225. function octstr(val : longint;cnt : byte) : shortstring;
  226. var
  227. i : longint;
  228. begin
  229. octstr[0]:=char(cnt);
  230. for i:=cnt downto 1 do
  231. begin
  232. octstr[i]:=hextbl[val and 7];
  233. val:=val shr 3;
  234. end;
  235. end;
  236. function binstr(val : longint;cnt : byte) : shortstring;
  237. var
  238. i : longint;
  239. begin
  240. binstr[0]:=char(cnt);
  241. for i:=cnt downto 1 do
  242. begin
  243. binstr[i]:=char(48+val and 1);
  244. val:=val shr 1;
  245. end;
  246. end;
  247. function hexstr(val : int64;cnt : byte) : shortstring;
  248. var
  249. i : longint;
  250. begin
  251. hexstr[0]:=char(cnt);
  252. for i:=cnt downto 1 do
  253. begin
  254. hexstr[i]:=hextbl[val and $f];
  255. val:=val shr 4;
  256. end;
  257. end;
  258. function octstr(val : int64;cnt : byte) : shortstring;
  259. var
  260. i : longint;
  261. begin
  262. octstr[0]:=char(cnt);
  263. for i:=cnt downto 1 do
  264. begin
  265. octstr[i]:=hextbl[val and 7];
  266. val:=val shr 3;
  267. end;
  268. end;
  269. function binstr(val : int64;cnt : byte) : shortstring;
  270. var
  271. i : longint;
  272. begin
  273. binstr[0]:=char(cnt);
  274. for i:=cnt downto 1 do
  275. begin
  276. binstr[i]:=char(48+val and 1);
  277. val:=val shr 1;
  278. end;
  279. end;
  280. function space (b : byte): shortstring;
  281. begin
  282. space[0] := chr(b);
  283. FillChar (Space[1],b,' ');
  284. end;
  285. {*****************************************************************************
  286. Str() Helpers
  287. *****************************************************************************}
  288. procedure fpc_shortstr_longint(v : longint;len : longint;var s : shortstring);[public,alias:'FPC_SHORTSTR_LONGINT']; {$ifdef hascompilerproc} compilerproc; {$endif}
  289. begin
  290. int_str(v,s);
  291. if length(s)<len then
  292. s:=space(len-length(s))+s;
  293. end;
  294. {$ifdef ver1_0}
  295. procedure fpc_shortstr_cardinal(v : longword;len : longint;var s : shortstring);[public,alias:'FPC_SHORTSTR_CARDINAL']; {$ifdef hascompilerproc} compilerproc; {$endif}
  296. {$else}
  297. procedure fpc_shortstr_longword(v : longword;len : longint;var s : shortstring);[public,alias:'FPC_SHORTSTR_LONGWORD']; {$ifdef hascompilerproc} compilerproc; {$endif}
  298. {$endif}
  299. begin
  300. int_str(v,s);
  301. if length(s)<len then
  302. s:=space(len-length(s))+s;
  303. end;
  304. { fpc_shortstr_longint must appear before this file is included, because }
  305. { it's used inside real2str.inc and otherwise the searching via the }
  306. { compilerproc name will fail (JM) }
  307. {$I real2str.inc}
  308. procedure fpc_ShortStr_Float(d : ValReal;len,fr,rt : longint;var s : shortstring);[public,alias:'FPC_SHORTSTR_FLOAT']; {$ifdef hascompilerproc}compilerproc;{$endif hascompilerproc}
  309. begin
  310. str_real(len,fr,d,treal_type(rt),s);
  311. end;
  312. {
  313. Array Of Char Str() helpers
  314. }
  315. procedure fpc_chararray_longint(v : longint;len : longint;var a:array of char);{$ifdef hascompilerproc} compilerproc; {$endif}
  316. var
  317. ss : shortstring;
  318. maxlen : longint;
  319. begin
  320. int_str(v,ss);
  321. if length(ss)<len then
  322. ss:=space(len-length(ss))+ss;
  323. if length(ss)<high(a)+1 then
  324. maxlen:=length(ss)
  325. else
  326. maxlen:=high(a)+1;
  327. move(ss[1],pchar(@a)^,maxlen);
  328. end;
  329. procedure fpc_chararray_longword(v : longword;len : longint;var a : array of char);{$ifdef hascompilerproc} compilerproc; {$endif}
  330. var
  331. ss : shortstring;
  332. maxlen : longint;
  333. begin
  334. int_str(v,ss);
  335. if length(ss)<len then
  336. ss:=space(len-length(ss))+ss;
  337. if length(ss)<high(a)+1 then
  338. maxlen:=length(ss)
  339. else
  340. maxlen:=high(a)+1;
  341. move(ss[1],pchar(@a)^,maxlen);
  342. end;
  343. procedure fpc_chararray_Float(d : ValReal;len,fr,rt : longint;var a : array of char);{$ifdef hascompilerproc}compilerproc;{$endif hascompilerproc}
  344. var
  345. ss : shortstring;
  346. maxlen : longint;
  347. begin
  348. str_real(len,fr,d,treal_type(rt),ss);
  349. if length(ss)<high(a)+1 then
  350. maxlen:=length(ss)
  351. else
  352. maxlen:=high(a)+1;
  353. move(ss[1],pchar(@a)^,maxlen);
  354. end;
  355. {*****************************************************************************
  356. Val() Functions
  357. *****************************************************************************}
  358. Function InitVal(const s:shortstring;var negativ:boolean;var base:byte):ValSInt;
  359. var
  360. Code : Longint;
  361. begin
  362. {Skip Spaces and Tab}
  363. code:=1;
  364. while (code<=length(s)) and (s[code] in [' ',#9]) do
  365. inc(code);
  366. {Sign}
  367. negativ:=false;
  368. case s[code] of
  369. '-' : begin
  370. negativ:=true;
  371. inc(code);
  372. end;
  373. '+' : inc(code);
  374. end;
  375. {Base}
  376. base:=10;
  377. if code<=length(s) then
  378. begin
  379. case s[code] of
  380. '$' : begin
  381. base:=16;
  382. repeat
  383. inc(code);
  384. until (code>=length(s)) or (s[code]<>'0');
  385. end;
  386. '%' : begin
  387. base:=2;
  388. inc(code);
  389. end;
  390. '&' : begin
  391. Base:=8;
  392. repeat
  393. inc(code);
  394. until (code>=length(s)) or (s[code]<>'0');
  395. end;
  396. end;
  397. end;
  398. InitVal:=code;
  399. end;
  400. Function fpc_Val_SInt_ShortStr(DestSize: longint; Const S: ShortString; var Code: ValSInt): ValSInt; [public, alias:'FPC_VAL_SINT_SHORTSTR']; {$ifdef hascompilerproc} compilerproc; {$endif}
  401. var
  402. u, temp, prev, maxPrevValue, maxNewValue: ValUInt;
  403. base : byte;
  404. negative : boolean;
  405. begin
  406. fpc_Val_SInt_ShortStr := 0;
  407. Temp:=0;
  408. Code:=InitVal(s,negative,base);
  409. if Code>length(s) then
  410. exit;
  411. maxPrevValue := ValUInt(MaxUIntValue) div ValUInt(Base);
  412. if (base = 10) then
  413. maxNewValue := MaxSIntValue + ord(negative)
  414. else
  415. maxNewValue := MaxUIntValue;
  416. while Code<=Length(s) do
  417. begin
  418. case s[Code] of
  419. '0'..'9' : u:=Ord(S[Code])-Ord('0');
  420. 'A'..'F' : u:=Ord(S[Code])-(Ord('A')-10);
  421. 'a'..'f' : u:=Ord(S[Code])-(Ord('a')-10);
  422. else
  423. u:=16;
  424. end;
  425. Prev := Temp;
  426. Temp := Temp*ValUInt(base);
  427. If (u >= base) or
  428. (ValUInt(maxNewValue-u) < Temp) or
  429. (prev > maxPrevValue) Then
  430. Begin
  431. fpc_Val_SInt_ShortStr := 0;
  432. Exit
  433. End;
  434. Temp:=Temp+u;
  435. inc(code);
  436. end;
  437. code := 0;
  438. fpc_Val_SInt_ShortStr := ValSInt(Temp);
  439. If Negative Then
  440. fpc_Val_SInt_ShortStr := -fpc_Val_SInt_ShortStr;
  441. If Not(Negative) and (base <> 10) Then
  442. {sign extend the result to allow proper range checking}
  443. Case DestSize of
  444. 1: fpc_Val_SInt_ShortStr := shortint(fpc_Val_SInt_ShortStr);
  445. 2: fpc_Val_SInt_ShortStr := smallint(fpc_Val_SInt_ShortStr);
  446. { Uncomment the folling once full 64bit support is in place
  447. 4: fpc_Val_SInt_ShortStr := longint(fpc_Val_SInt_ShortStr);}
  448. End;
  449. end;
  450. {$ifdef hascompilerproc}
  451. { we need this for fpc_Val_SInt_Ansistr and fpc_Val_SInt_WideStr because }
  452. { we have to pass the DestSize parameter on (JM) }
  453. Function fpc_Val_SInt_ShortStr(DestSize: longint; Const S: ShortString; var Code: ValSInt): ValSInt; [external name 'FPC_VAL_SINT_SHORTSTR'];
  454. {$endif hascompilerproc}
  455. Function fpc_Val_UInt_Shortstr(Const S: ShortString; var Code: ValSInt): ValUInt; [public, alias:'FPC_VAL_UINT_SHORTSTR']; {$ifdef hascompilerproc} compilerproc; {$endif}
  456. var
  457. u, prev : ValUInt;
  458. base : byte;
  459. negative : boolean;
  460. begin
  461. fpc_Val_UInt_Shortstr:=0;
  462. Code:=InitVal(s,negative,base);
  463. If Negative or (Code>length(s)) Then
  464. Exit;
  465. while Code<=Length(s) do
  466. begin
  467. case s[Code] of
  468. '0'..'9' : u:=Ord(S[Code])-Ord('0');
  469. 'A'..'F' : u:=Ord(S[Code])-(Ord('A')-10);
  470. 'a'..'f' : u:=Ord(S[Code])-(Ord('a')-10);
  471. else
  472. u:=16;
  473. end;
  474. prev := fpc_Val_UInt_Shortstr;
  475. If (u>=base) or
  476. (ValUInt(MaxUIntValue-u) div ValUInt(Base)<prev) then
  477. begin
  478. fpc_Val_UInt_Shortstr:=0;
  479. exit;
  480. end;
  481. fpc_Val_UInt_Shortstr:=fpc_Val_UInt_Shortstr*ValUInt(base) + u;
  482. inc(code);
  483. end;
  484. code := 0;
  485. end;
  486. Function fpc_Val_Real_ShortStr(const s : shortstring; var code : ValSInt): ValReal; [public, alias:'FPC_VAL_REAL_SHORTSTR']; {$ifdef hascompilerproc} compilerproc; {$endif}
  487. var
  488. hd,
  489. esign,sign : valreal;
  490. exponent,i : longint;
  491. flags : byte;
  492. begin
  493. fpc_Val_Real_ShortStr:=0.0;
  494. code:=1;
  495. exponent:=0;
  496. esign:=1;
  497. flags:=0;
  498. sign:=1;
  499. while (code<=length(s)) and (s[code] in [' ',#9]) do
  500. inc(code);
  501. case s[code] of
  502. '+' : inc(code);
  503. '-' : begin
  504. sign:=-1;
  505. inc(code);
  506. end;
  507. end;
  508. while (Code<=Length(s)) and (s[code] in ['0'..'9']) do
  509. begin
  510. { Read integer part }
  511. flags:=flags or 1;
  512. fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr*10+(ord(s[code])-ord('0'));
  513. inc(code);
  514. end;
  515. { Decimal ? }
  516. if (s[code]='.') and (length(s)>=code) then
  517. begin
  518. hd:=1.0;
  519. inc(code);
  520. while (s[code] in ['0'..'9']) and (length(s)>=code) do
  521. begin
  522. { Read fractional part. }
  523. flags:=flags or 2;
  524. fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr*10+(ord(s[code])-ord('0'));
  525. hd:=hd*10.0;
  526. inc(code);
  527. end;
  528. fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr/hd;
  529. end;
  530. { Again, read integer and fractional part}
  531. if flags=0 then
  532. begin
  533. fpc_Val_Real_ShortStr:=0.0;
  534. exit;
  535. end;
  536. { Exponent ? }
  537. if (upcase(s[code])='E') and (length(s)>=code) then
  538. begin
  539. inc(code);
  540. if s[code]='+' then
  541. inc(code)
  542. else
  543. if s[code]='-' then
  544. begin
  545. esign:=-1;
  546. inc(code);
  547. end;
  548. if not(s[code] in ['0'..'9']) or (length(s)<code) then
  549. begin
  550. fpc_Val_Real_ShortStr:=0.0;
  551. exit;
  552. end;
  553. while (s[code] in ['0'..'9']) and (length(s)>=code) do
  554. begin
  555. exponent:=exponent*10;
  556. exponent:=exponent+ord(s[code])-ord('0');
  557. inc(code);
  558. end;
  559. end;
  560. { Calculate Exponent }
  561. {
  562. if esign>0 then
  563. for i:=1 to exponent do
  564. fpc_Val_Real_ShortStr:=Val_Real_ShortStr*10
  565. else
  566. for i:=1 to exponent do
  567. fpc_Val_Real_ShortStr:=Val_Real_ShortStr/10; }
  568. hd:=1.0;
  569. for i:=1 to exponent do
  570. hd:=hd*10.0;
  571. if esign>0 then
  572. fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr*hd
  573. else
  574. fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr/hd;
  575. { Not all characters are read ? }
  576. if length(s)>=code then
  577. begin
  578. fpc_Val_Real_ShortStr:=0.0;
  579. exit;
  580. end;
  581. { evaluate sign }
  582. fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr*sign;
  583. { success ! }
  584. code:=0;
  585. end;
  586. Procedure SetString (Var S : Shortstring; Buf : PChar; Len : Longint);
  587. begin
  588. Move (Buf[0],S[1],Len);
  589. S[0]:=chr(len);
  590. end;
  591. {
  592. $Log$
  593. Revision 1.23 2002-09-14 11:20:50 carl
  594. * Delphi compatibility fix (with string routines)
  595. Revision 1.22 2002/09/07 21:19:00 carl
  596. * cardinal -> longword
  597. Revision 1.21 2002/09/07 15:07:46 peter
  598. * old logs removed and tabs fixed
  599. Revision 1.20 2002/09/02 19:24:41 peter
  600. * array of char support for Str()
  601. Revision 1.19 2002/08/06 20:53:38 michael
  602. + Added support for octal strings (using &)
  603. Revision 1.18 2002/01/24 18:27:06 peter
  604. * lowercase() overloaded
  605. }