mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-27 18:33:43 +02:00
619 lines
13 KiB
PHP
619 lines
13 KiB
PHP
{
|
|
$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}
|
|
|
|
{$ifndef INTERNSETLENGTH}
|
|
procedure SetLength(var s:shortstring;len:StrLenInt);
|
|
{$else INTERNSETLENGTH}
|
|
procedure Shortstr_SetLength(var s:shortstring;len:StrLenInt);[Public,Alias : 'FPC_SHORTSTR_SETLENGTH'];
|
|
{$endif INTERNSETLENGTH}
|
|
begin
|
|
if Len>255 then
|
|
Len:=255;
|
|
s[0]:=chr(len);
|
|
end;
|
|
|
|
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 count>length(s)-index 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>length(s)-Index 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;
|
|
|
|
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;
|
|
|
|
|
|
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;
|
|
|
|
|
|
const
|
|
HexTbl : array[0..15] of char='0123456789ABCDEF';
|
|
|
|
function hexstr(val : longint;cnt : byte) : shortstring;
|
|
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;
|
|
|
|
|
|
function hexstr(val : int64;cnt : byte) : shortstring;
|
|
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 : int64;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;
|
|
|
|
|
|
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, maxValue: ValUInt;
|
|
base : byte;
|
|
negative : boolean;
|
|
begin
|
|
ValSignedInt := 0;
|
|
Temp:=0;
|
|
Code:=InitVal(s,negative,base);
|
|
if Code>length(s) then
|
|
exit;
|
|
maxValue := ValUInt(MaxUIntValue) div ValUInt(Base);
|
|
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 (u >= base) or
|
|
((base = 10) and
|
|
(MaxSIntValue-temp+ord(negative) < u)) or
|
|
((base <> 10) and
|
|
(ValUInt(MaxUIntValue-Temp) < u)) or
|
|
(prev > maxValue) 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: ValSignedInt := shortint(ValSignedInt);
|
|
2: ValSignedInt := smallint(ValSignedInt);
|
|
{ Uncomment the folling once full 64bit support is in place
|
|
4: ValSignedInt := longint(ValSignedInt);}
|
|
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;
|
|
If (u>=base) or
|
|
(ValUInt(MaxUIntValue-u) div ValUInt(Base)<prev) then
|
|
begin
|
|
ValUnsignedInt:=0;
|
|
exit;
|
|
end;
|
|
ValUnsignedInt:=ValUnsignedInt*ValUInt(base) + 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+(ord(s[code])-ord('0'));
|
|
inc(code);
|
|
end;
|
|
{ Decimal ? }
|
|
if (s[code]='.') and (length(s)>=code) then
|
|
begin
|
|
hd:=1.0;
|
|
inc(code);
|
|
while (s[code] in ['0'..'9']) and (length(s)>=code) do
|
|
begin
|
|
{ Read fractional part. }
|
|
flags:=flags or 2;
|
|
valfloat:=valfloat*10+(ord(s[code])-ord('0'));
|
|
hd:=hd*10.0;
|
|
inc(code);
|
|
end;
|
|
valfloat:=valfloat/hd;
|
|
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; }
|
|
hd:=1.0;
|
|
for i:=1 to exponent do
|
|
hd:=hd*10.0;
|
|
if esign>0 then
|
|
valfloat:=valfloat*hd
|
|
else
|
|
valfloat:=valfloat/hd;
|
|
{ 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.12 2001-06-04 11:43:51 peter
|
|
* Formal const to var fixes
|
|
* Hexstr(int64) added
|
|
|
|
Revision 1.11 2001/04/13 22:30:04 peter
|
|
* remove warnings
|
|
|
|
Revision 1.10 2001/04/13 18:06:28 peter
|
|
* removed rtllite define
|
|
|
|
Revision 1.9 2001/03/03 12:38:53 jonas
|
|
* made val for longints a bit faster
|
|
|
|
Revision 1.8 2000/12/09 20:52:41 florian
|
|
* val for dword and qword didn't handle the max values
|
|
correctly
|
|
* val for qword works again
|
|
+ val with int64/qword and ansistring implemented
|
|
|
|
Revision 1.7 2000/11/23 11:41:56 jonas
|
|
* fix for web bug 1265 by Peter (merged)
|
|
|
|
Revision 1.6 2000/11/17 17:01:23 jonas
|
|
* fixed bug for val when processing -2147483648 and low(int64) (merged)
|
|
|
|
Revision 1.5 2000/11/06 20:34:24 peter
|
|
* changed ver1_0 defines to temporary defs
|
|
|
|
Revision 1.4 2000/10/21 18:20:17 florian
|
|
* a lot of small changes:
|
|
- setlength is internal
|
|
- win32 graph unit extended
|
|
....
|
|
|
|
Revision 1.3 2000/07/28 12:29:49 jonas
|
|
* fixed web bug1069
|
|
* fixed similar (and other) problems in val() for int64 and qword
|
|
(both merged from fixes branch)
|
|
|
|
Revision 1.2 2000/07/13 11:33:45 michael
|
|
+ removed logs
|
|
|
|
}
|