123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582 |
- {
- $Id$
- This file is part of the Free Pascal run time library.
- Copyright (c) 1999-2000 by the Free Pascal development team
- See the file COPYING.FPC, included in this distribution,
- for details about the copyright.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- **********************************************************************}
- {****************************************************************************
- subroutines for string handling
- ****************************************************************************}
- {$I real2str.inc}
- function copy(const s : shortstring;index : StrLenInt;count : StrLenInt): shortstring;
- begin
- if count<0 then
- count:=0;
- if index>1 then
- dec(index)
- else
- index:=0;
- if index>length(s) then
- count:=0
- else
- if index+count>length(s) then
- count:=length(s)-index;
- Copy[0]:=chr(Count);
- Move(s[Index+1],Copy[1],Count);
- end;
- procedure delete(var s : shortstring;index : StrLenInt;count : StrLenInt);
- begin
- if index<=0 then
- begin
- inc(count,index-1);
- index:=1;
- end;
- if (Index<=Length(s)) and (Count>0) then
- begin
- if Count+Index>length(s) then
- Count:=length(s)-Index+1;
- s[0]:=Chr(length(s)-Count);
- if Index<=Length(s) then
- Move(s[Index+Count],s[Index],Length(s)-Index+1);
- end;
- end;
- procedure insert(const source : shortstring;var s : shortstring;index : StrLenInt);
- var
- cut,srclen,indexlen : longint;
- begin
- if index<1 then
- index:=1;
- if index>length(s) then
- index:=length(s)+1;
- indexlen:=Length(s)-Index+1;
- srclen:=length(Source);
- if length(source)+length(s)>=sizeof(s) then
- begin
- cut:=length(source)+length(s)-sizeof(s)+1;
- if cut>indexlen then
- begin
- dec(srclen,cut-indexlen);
- indexlen:=0;
- end
- else
- dec(indexlen,cut);
- end;
- move(s[Index],s[Index+srclen],indexlen);
- move(Source[1],s[Index],srclen);
- s[0]:=chr(index+srclen+indexlen-1);
- end;
- procedure insert(source : Char;var s : shortstring;index : StrLenInt);
- var
- indexlen : longint;
- begin
- if index<1 then
- index:=1;
- if index>length(s) then
- index:=length(s)+1;
- indexlen:=Length(s)-Index+1;
- if (length(s)+1=sizeof(s)) and (indexlen>0) then
- dec(indexlen);
- move(s[Index],s[Index+1],indexlen);
- s[Index]:=Source;
- s[0]:=chr(index+indexlen);
- end;
- function pos(const substr : shortstring;const s : shortstring):StrLenInt;
- var
- i,j : StrLenInt;
- e : boolean;
- begin
- i := 0;
- j := 0;
- e:=(length(SubStr)>0);
- while e and (i<=Length(s)-Length(SubStr)) do
- begin
- inc(i);
- if (SubStr[1]=s[i]) and (Substr=Copy(s,i,Length(SubStr))) then
- begin
- j:=i;
- e:=false;
- end;
- end;
- Pos:=j;
- end;
- {Faster when looking for a single char...}
- function pos(c:char;const s:shortstring):StrLenInt;
- var
- i : StrLenInt;
- begin
- for i:=1 to length(s) do
- if s[i]=c then
- begin
- pos:=i;
- exit;
- end;
- pos:=0;
- end;
- procedure SetLength(var s:shortstring;len:StrLenInt);
- begin
- if Len>255 then
- Len:=255;
- s[0]:=chr(len);
- end;
- function copy(c:char;index : StrLenInt;count : StrLenInt): shortstring;
- begin
- if (index=1) and (Count>0) then
- Copy:=c
- else
- Copy:='';
- end;
- function pos(const substr : shortstring;c:char): StrLenInt;
- begin
- if (length(substr)=1) and (substr[1]=c) then
- Pos:=1
- else
- Pos:=0;
- end;
- { removed must be internal to be accepted in const expr !! PM
- function length(c:char):StrLenInt;
- begin
- Length:=1;
- end;
- }
- {$ifdef IBM_CHAR_SET}
- const
- UpCaseTbl : shortstring[7]=#154#142#153#144#128#143#165;
- LoCaseTbl : shortstring[7]=#129#132#148#130#135#134#164;
- {$endif}
- function upcase(c : char) : char;
- {$IFDEF IBM_CHAR_SET}
- var
- i : longint;
- {$ENDIF}
- begin
- if (c in ['a'..'z']) then
- upcase:=char(byte(c)-32)
- else
- {$IFDEF IBM_CHAR_SET}
- begin
- i:=Pos(c,LoCaseTbl);
- if i>0 then
- upcase:=UpCaseTbl[i]
- else
- upcase:=c;
- end;
- {$ELSE}
- upcase:=c;
- {$ENDIF}
- end;
- function upcase(const s : shortstring) : shortstring;
- var
- i : longint;
- begin
- upcase[0]:=s[0];
- for i := 1 to length (s) do
- upcase[i] := upcase (s[i]);
- end;
- {$ifndef RTLLITE}
- function lowercase(c : char) : char;
- {$IFDEF IBM_CHAR_SET}
- var
- i : longint;
- {$ENDIF}
- begin
- if (c in ['A'..'Z']) then
- lowercase:=char(byte(c)+32)
- else
- {$IFDEF IBM_CHAR_SET}
- begin
- i:=Pos(c,UpCaseTbl);
- if i>0 then
- lowercase:=LoCaseTbl[i]
- else
- lowercase:=c;
- end;
- {$ELSE}
- lowercase:=c;
- {$ENDIF}
- end;
- function lowercase(const s : shortstring) : shortstring;
- var
- i : longint;
- begin
- lowercase [0]:=s[0];
- for i:=1 to length(s) do
- lowercase[i]:=lowercase (s[i]);
- end;
- function hexstr(val : longint;cnt : byte) : shortstring;
- const
- HexTbl : array[0..15] of char='0123456789ABCDEF';
- var
- i : longint;
- begin
- hexstr[0]:=char(cnt);
- for i:=cnt downto 1 do
- begin
- hexstr[i]:=hextbl[val and $f];
- val:=val shr 4;
- end;
- end;
- function binstr(val : longint;cnt : byte) : shortstring;
- var
- i : longint;
- begin
- binstr[0]:=char(cnt);
- for i:=cnt downto 1 do
- begin
- binstr[i]:=char(48+val and 1);
- val:=val shr 1;
- end;
- end;
- {$endif RTLLITE}
- function space (b : byte): shortstring;
- begin
- space[0] := chr(b);
- FillChar (Space[1],b,' ');
- end;
- {*****************************************************************************
- Str() Helpers
- *****************************************************************************}
- procedure ShortStr_Float(d : ValReal;len,fr,rt : longint;var s : shortstring);[public,alias:'FPC_SHORTSTR_FLOAT'];
- begin
- str_real(len,fr,d,treal_type(rt),s);
- end;
- procedure int_str_longint(v : longint;len : longint;var s : shortstring);[public,alias:'FPC_SHORTSTR_LONGINT'];
- begin
- int_str(v,s);
- if length(s)<len then
- s:=space(len-length(s))+s;
- end;
- procedure int_str_cardinal(v : cardinal;len : longint;var s : shortstring);[public,alias:'FPC_SHORTSTR_CARDINAL'];
- begin
- int_str(v,s);
- if length(s)<len then
- s:=space(len-length(s))+s;
- end;
- {*****************************************************************************
- Val() Functions
- *****************************************************************************}
- Function InitVal(const s:shortstring;var negativ:boolean;var base:byte):ValSInt;
- var
- Code : Longint;
- begin
- {Skip Spaces and Tab}
- code:=1;
- while (code<=length(s)) and (s[code] in [' ',#9]) do
- inc(code);
- {Sign}
- negativ:=false;
- case s[code] of
- '-' : begin
- negativ:=true;
- inc(code);
- end;
- '+' : inc(code);
- end;
- {Base}
- base:=10;
- if code<=length(s) then
- begin
- case s[code] of
- '$' : begin
- base:=16;
- repeat
- inc(code);
- until (code>=length(s)) or (s[code]<>'0');
- end;
- '%' : begin
- base:=2;
- inc(code);
- end;
- end;
- end;
- InitVal:=code;
- end;
- Function ValSignedInt(DestSize: longint; Const S: ShortString; var Code: ValSInt): ValSInt; [public, alias:'FPC_VAL_SINT_SHORTSTR'];
- var
- u, temp, prev: ValUInt;
- base : byte;
- negative : boolean;
- begin
- ValSignedInt := 0;
- Temp:=0;
- Code:=InitVal(s,negative,base);
- if Code>length(s) then
- exit;
- if negative and (s='-2147483648') then
- begin
- Code:=0;
- ValSignedInt:=$80000000;
- exit;
- end;
- while Code<=Length(s) do
- begin
- case s[Code] of
- '0'..'9' : u:=Ord(S[Code])-Ord('0');
- 'A'..'F' : u:=Ord(S[Code])-(Ord('A')-10);
- 'a'..'f' : u:=Ord(S[Code])-(Ord('a')-10);
- else
- u:=16;
- end;
- Prev := Temp;
- Temp := Temp*ValUInt(base);
- If ((base = 10) and
- (prev > MaxSIntValue div ValUInt(Base))) or
- (Temp < prev) Then
- Begin
- ValSignedInt := 0;
- Exit
- End;
- if (u>=base) or
- ((base = 10) and
- (MaxSIntValue < u+temp)) or
- ((base <> 10) and
- (ValUInt(MaxUIntValue-Temp) < u)) then
- begin
- ValSignedInt:=0;
- exit;
- end;
- Temp:=Temp+u;
- inc(code);
- end;
- code := 0;
- ValSignedInt := ValSInt(Temp);
- If Negative Then
- ValSignedInt := -ValSignedInt;
- If Not(Negative) and (base <> 10) Then
- {sign extend the result to allow proper range checking}
- Case DestSize of
- 1: If (ValSignedInt > High(ShortInt)) and (ValSignedInt <= High(Byte)) Then
- ValSignedInt := ValSignedInt or (MaxUIntValue xor High(Byte));
- 2: If (ValSignedInt > High(Integer)) and (ValSignedInt <= High(Word)) Then
- ValSignedInt := ValSignedInt or (MaxUIntValue xor High(Word));
- { Uncomment the folling once full 64bit support is in place
- 4: If (ValSignedInt > High(Longint)) and (ValSignedInt <= High(Cardinal)) Then
- ValSignedInt := ValSignedInt or (MaxUIntValue xor High(Cardinal));}
- End;
- end;
- Function ValUnsignedInt(Const S: ShortString; var Code: ValSInt): ValUInt; [public, alias:'FPC_VAL_UINT_SHORTSTR'];
- var
- u, prev: ValUInt;
- base : byte;
- negative : boolean;
- begin
- ValUnSignedInt:=0;
- Code:=InitVal(s,negative,base);
- If Negative or (Code>length(s)) Then
- Exit;
- while Code<=Length(s) do
- begin
- case s[Code] of
- '0'..'9' : u:=Ord(S[Code])-Ord('0');
- 'A'..'F' : u:=Ord(S[Code])-(Ord('A')-10);
- 'a'..'f' : u:=Ord(S[Code])-(Ord('a')-10);
- else
- u:=16;
- end;
- prev := ValUnsignedInt;
- ValUnsignedInt:=ValUnsignedInt*ValUInt(base);
- If prev > ValUnsignedInt Then
- {we've had an overflow. Can't check this with
- "If ValUnsignedInt <= (MaxUIntValue div ValUInt(Base)) Then"
- because this division always overflows! (JM)}
- Begin
- ValUnsignedInt := 0;
- Exit
- End;
- if (u>=base) or (ValUInt(MaxUIntValue-ValUnsignedInt) < u) then
- begin
- ValUnsignedInt:=0;
- exit;
- end;
- ValUnsignedInt:=ValUnsignedInt+u;
- inc(code);
- end;
- code := 0;
- end;
- Function ValFloat(const s : shortstring; var code : ValSInt): ValReal; [public, alias:'FPC_VAL_REAL_SHORTSTR'];
- var
- hd,
- esign,sign : valreal;
- exponent,i : longint;
- flags : byte;
- begin
- ValFloat:=0.0;
- code:=1;
- exponent:=0;
- esign:=1;
- flags:=0;
- sign:=1;
- while (code<=length(s)) and (s[code] in [' ',#9]) do
- inc(code);
- case s[code] of
- '+' : inc(code);
- '-' : begin
- sign:=-1;
- inc(code);
- end;
- end;
- while (Code<=Length(s)) and (s[code] in ['0'..'9']) do
- begin
- { Read integer part }
- flags:=flags or 1;
- valfloat:=valfloat*10;
- valfloat:=valfloat+(ord(s[code])-ord('0'));
- inc(code);
- end;
- { Decimal ? }
- if (s[code]='.') and (length(s)>=code) then
- begin
- hd:=0.1;
- inc(code);
- while (s[code] in ['0'..'9']) and (length(s)>=code) do
- begin
- { Read fractional part. }
- flags:=flags or 2;
- valfloat:=valfloat+hd*(ord(s[code])-ord('0'));
- hd:=hd/10.0;
- inc(code);
- end;
- end;
- { Again, read integer and fractional part}
- if flags=0 then
- begin
- valfloat:=0.0;
- exit;
- end;
- { Exponent ? }
- if (upcase(s[code])='E') and (length(s)>=code) then
- begin
- inc(code);
- if s[code]='+' then
- inc(code)
- else
- if s[code]='-' then
- begin
- esign:=-1;
- inc(code);
- end;
- if not(s[code] in ['0'..'9']) or (length(s)<code) then
- begin
- valfloat:=0.0;
- exit;
- end;
- while (s[code] in ['0'..'9']) and (length(s)>=code) do
- begin
- exponent:=exponent*10;
- exponent:=exponent+ord(s[code])-ord('0');
- inc(code);
- end;
- end;
- { Calculate Exponent }
- if esign>0 then
- for i:=1 to exponent do
- valfloat:=valfloat*10
- else
- for i:=1 to exponent do
- valfloat:=valfloat/10;
- { Not all characters are read ? }
- if length(s)>=code then
- begin
- valfloat:=0.0;
- exit;
- end;
- { evaluate sign }
- valfloat:=valfloat*sign;
- { success ! }
- code:=0;
- end;
- {$ifdef SUPPORT_FIXED}
- Function ValFixed(const s : shortstring;var code : ValSInt): Fixed; [public, alias:'FPC_VAL_FIXED_SHORTSTR'];
- begin
- ValFixed := Fixed(ValFloat(s,code));
- end;
- {$endif SUPPORT_FIXED}
- Procedure SetString (Var S : Shortstring; Buf : PChar; Len : Longint);
- begin
- Move (Buf[0],S[1],Len);
- S[0]:=chr(len);
- end;
- {
- $Log$
- Revision 1.34 2000-02-09 16:59:31 peter
- * truncated log
- Revision 1.33 2000/01/07 16:41:36 daniel
- * copyright 2000
- Revision 1.32 2000/01/07 16:32:25 daniel
- * copyright 2000 added
- Revision 1.31 1999/12/11 19:07:44 jonas
- * avoid unwanted type conversion from cardinal to longint in val for
- signed and unsigned 32bit int
- Revision 1.30 1999/11/06 14:35:39 peter
- * truncated log
- }
|