It seems there is no Ansi overload for StrToInt. Is this right? Or maybe I am missing something. StrToInt insists to convert my ansistrings to string.
You are correct. There is no ANSI version of StrToInt
. The place to find ANSI versions of standard function is the AnsiStrings
unit, and there's nothing there.
Either write your own function to do the job, or accept the conversion required to use StrToInt
.
It's not too hard to write your own function. It might look like this:
uses
SysConst; // for SInvalidInteger
....
{$OVERFLOWCHECKS OFF}
{$RANGECHECKS OFF}
function AnsiStrToInt(const s: AnsiString): Integer;
procedure Error;
begin
raise EConvertError.CreateResFmt(@SInvalidInteger, [s]);
end;
var
Index, Len, Digit: Integer;
Negative: Boolean;
begin
Index := 1;
Result := 0;
Negative := False;
Len := Length(s);
while (Index <= Len) and (s[Index] = ' ') do
inc(Index);
if Index > Len then
Error;
case s[Index] of
'-','+':
begin
Negative := s[Index] = '-';
inc(Index);
if Index > Len then
Error;
end;
end;
while Index <= Len do
begin
Digit := ord(s[Index]) - ord('0');
if (Digit < 0) or (Digit > 9) then
Error;
Result := Result * 10 + Digit;
if Result < 0 then
Error;
inc(Index);
end;
if Negative then
Result := -Result;
end;
This is a cut-down version of that found in StrToInt
. It does not handle hexadecimal and is a bit more stringent regarding errors. Before using this code I'd want to test whether or not this really is your bottleneck.
It is quite interesting that this code, based on that in the RTL source, is incapable of returning low(Integer)
. It's not too hard to fix that up, but it would make the code more complex.
The code is actually very simple (hex strings aren't supported but prolly you don't need them):
function AnsiStrToInt(const S: RawByteString): Integer;
var
P: PByte;
Negative: Boolean;
Digit: Integer;
begin
P:= Pointer(S);
// skip leading spaces
while (P^ = Ord(' ')) do Inc(P);
Negative:= False;
if (P^ = Ord('-')) then begin
Negative:= True;
Inc(P);
end
else if (P^ = Ord('+')) then Inc(P);
if P^ = 0 then
raise Exception.Create('No data');
Result:= 0;
repeat
if Cardinal(Result) > Cardinal(High(Result) div 10) then
raise Exception.Create('Integer overflow');
Digit:= P^ - Ord('0');
if (Digit < 0) or (Digit > 9) then
raise Exception.Create('Invalid char');
Result:= Result * 10 + Digit;
if (Result < 0) then begin
if not Negative or (Cardinal(Result) <> Cardinal(Low(Result))) then
raise Exception.Create('Integer overflow');
end;
Inc(P);
until (P^ = 0);
if Negative then Result:= -Result;
end;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With