Skip to content

Commit 321447d

Browse files
author
Arnaud Bouchez
committed
core: rewritten GetExtended() parsing
- to be similarly efficiently on all targets, even i386 and its limited number of registers
1 parent 22ccd96 commit 321447d

File tree

2 files changed

+42
-65
lines changed

2 files changed

+42
-65
lines changed

src/core/mormot.core.base.pas

Lines changed: 41 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -6546,7 +6546,6 @@ function GetExtended(P: PUtf8Char; out err: integer): TSynExtended;
65466546
var
65476547
remdigit: integer;
65486548
frac, exp: PtrInt;
6549-
c: AnsiChar;
65506549
flags: set of (fNeg, fNegExp, fValid);
65516550
v64: Int64; // allows 64-bit resolution for the digits (match 80-bit extended)
65526551
d64: TSynExtended;
@@ -6558,106 +6557,84 @@ function GetExtended(P: PUtf8Char; out err: integer): TSynExtended;
65586557
frac := 0;
65596558
if P = nil then
65606559
goto e; // will return 0 but err=1
6561-
c := P^;
6562-
if c = ' ' then
6560+
if P^ = ' ' then
65636561
repeat
65646562
inc(P);
6565-
c := P^;
6566-
until c <> ' '; // trailing spaces
6567-
if c = '+' then
6568-
begin
6569-
inc(P);
6570-
c := P^;
6571-
end
6572-
else if c = '-' then
6563+
until P^ <> ' '; // trailing spaces
6564+
if P^ = '+' then
6565+
inc(P)
6566+
else if P^ = '-' then
65736567
begin
65746568
inc(P);
6575-
c := P^;
6576-
if (c = 'I') and
6577-
(PWord(P + 1)^ and $dfdf = ord('N') + ord('F') shl 8) then
6578-
begin
6579-
err := 0;
6580-
result := NegInfinity;
6581-
exit;
6582-
end;
65836569
include(flags, fNeg);
6584-
end
6585-
else if c > '9' then
6586-
if (c = 'N') and
6587-
(PWord(P + 1)^ and $dfdf = ord('A') + ord('N') shl 8) then
6588-
begin
6589-
err := 0;
6590-
result := NaN;
6591-
exit;
6592-
end
6593-
else if (c = 'I') and
6594-
(PWord(P + 1)^ and $dfdf = ord('N') + ord('F') shl 8) then
6595-
begin
6596-
err := 0;
6597-
result := Infinity;
6598-
exit;
6570+
end;
6571+
if P^ > '9' then
6572+
case PCardinal(P)^ and $00dfdfdf of
6573+
ord('N') + ord('A') shl 8 + ord('N') shl 16:
6574+
begin
6575+
err := 0;
6576+
result := NaN;
6577+
exit;
6578+
end;
6579+
ord('I') + ord('N') shl 8 + ord('F') shl 16:
6580+
begin
6581+
err := 0;
6582+
if fNeg in flags then
6583+
result := NegInfinity
6584+
else
6585+
result := Infinity;
6586+
exit;
6587+
end;
65996588
end;
66006589
remdigit := 18; // v64=-9,223,372,036,854,775,808..+9,223,372,036,854,775,807
66016590
repeat
6602-
inc(P);
6603-
if (c >= '0') and
6604-
(c <= '9') then
6591+
if byte(ord(P^) - ord('0')) <= 9 then
66056592
begin
6606-
if remdigit = 0 then
6607-
if v64 < 922337203685477580 then // avoid 64-bit overflow
6608-
inc(remdigit); // but allow up to 19 digits if possible
6609-
dec(remdigit);
6593+
if (remdigit <> 0) or // avoid 64-bit overflow, but allow 19 digits
6594+
(v64 > 922337203685477580) then
6595+
dec(remdigit);
66106596
if remdigit >= 0 then // over-required digits are just ignored
66116597
begin
6612-
dec(c, ord('0'));
6613-
{$ifdef CPU64}
6614-
v64 := v64 * 10;
6615-
{$else}
6616-
v64 := v64 shl 3 + v64 + v64;
6617-
{$endif CPU64}
6618-
inc(v64, byte(c));
6619-
c := P^;
6598+
v64 := v64 * 10; // FPC generates fast imul + mul on i386
6599+
inc(v64, Int64(P^) - ord('0'));
66206600
include(flags, fValid);
66216601
if frac <> 0 then
66226602
dec(frac); // digits after '.'
6603+
inc(P);
66236604
continue;
66246605
end;
66256606
if frac >= 0 then
66266607
inc(frac); // handle #############00000
6627-
c := P^;
6608+
inc(P);
66286609
continue;
66296610
end;
6630-
if c <> '.' then
6611+
if P^ <> '.' then
66316612
break;
6613+
inc(P);
66326614
if frac > 0 then
66336615
goto e; // will return partial value but err=1
66346616
dec(frac);
6635-
c := P^;
66366617
until false;
66376618
if frac < 0 then
66386619
inc(frac); // adjust digits after '.'
6639-
if (c = 'E') or
6640-
(c = 'e') then
6620+
if ord(P^) or $20 = ord('e') then
66416621
begin
66426622
exp := 0;
66436623
exclude(flags, fValid);
6644-
c := P^;
6645-
if c = '+' then
6624+
inc(P);
6625+
if P^ = '+' then
66466626
inc(P)
6647-
else if c = '-' then
6627+
else if P^ = '-' then
66486628
begin
66496629
inc(P);
66506630
include(flags, fNegExp);
66516631
end;
66526632
repeat
6653-
c := P^;
6654-
inc(P);
6655-
if (c < '0') or
6656-
(c > '9') then
6633+
if byte(ord(P^) - ord('0')) > 9 then
66576634
break;
6658-
dec(c, ord('0'));
6659-
exp := (exp * 10) + byte(c);
6635+
exp := (exp * 10) + ord(P^) - ord('0');
66606636
include(flags, fValid);
6637+
inc(P);
66616638
until false;
66626639
if fNegExp in flags then
66636640
dec(frac, exp)
@@ -6671,7 +6648,7 @@ function GetExtended(P: PUtf8Char; out err: integer): TSynExtended;
66716648
end;
66726649
end;
66736650
if (fValid in flags) and
6674-
(c = #0) then
6651+
(P^ = #0) then
66756652
err := 0
66766653
else
66776654
e: err := 1; // return the (partial) value even if not ended with #0

src/mormot.commit.inc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
'2.3.10975'
1+
'2.3.10976'

0 commit comments

Comments
 (0)