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