[number] Make hb_parse_double simpler now that we don't have to mimic strtod

This commit is contained in:
Ebrahim Byagowi 2020-05-10 16:57:45 +04:30
parent 44fe1c8ff1
commit dca8ba6b6d
4 changed files with 33 additions and 50 deletions

View File

@ -96,7 +96,7 @@ static const int double_parser_en_main = 1;
/* Works only for n < 512 */
static inline double
_pow10 (unsigned int exponent)
_pow10 (unsigned exponent)
{
static const double _powers_of_10[] =
{
@ -110,38 +110,39 @@ _pow10 (unsigned int exponent)
100.,
10.
};
unsigned int mask = 1 << (ARRAY_LENGTH (_powers_of_10) - 1);
unsigned mask = 1 << (ARRAY_LENGTH (_powers_of_10) - 1);
double result = 1;
for (const double *power = _powers_of_10; mask; ++power, mask >>= 1)
if (exponent & mask) result *= *power;
return result;
}
/* a variant of strtod that also gets end of buffer in its second argument */
static inline double
strtod_rl (const char *buf, char **end_ptr)
strtod_rl (const char *buf, const char **end_ptr /* IN/OUT */)
{
const char *p, *pe;
double value = 0;
double frac = 0;
double frac_count = 0;
unsigned int exp = 0;
unsigned exp = 0;
bool neg = false, exp_neg = false, exp_overflow = false;
const unsigned long long MAX_FRACT = 0xFFFFFFFFFFFFFull; /* 2^52-1 */
const unsigned int MAX_EXP = 0x7FFu; /* 2^11-1 */
const unsigned MAX_EXP = 0x7FFu; /* 2^11-1 */
p = buf;
pe = p + strlen (p);
pe = *end_ptr;
while (p < pe && ISSPACE (*p))
p++;
int cs;
#line 140 "hb-number-parser.hh"
#line 141 "hb-number-parser.hh"
{
cs = double_parser_start;
}
#line 145 "hb-number-parser.hh"
#line 146 "hb-number-parser.hh"
{
int _slen;
int _trans;
@ -199,7 +200,7 @@ _resume:
exp_overflow = true;
}
break;
#line 203 "hb-number-parser.hh"
#line 204 "hb-number-parser.hh"
}
_again:
@ -211,10 +212,10 @@ _again:
_out: {}
}
#line 114 "hb-number-parser.rl"
#line 115 "hb-number-parser.rl"
*end_ptr = (char *) p;
*end_ptr = (const char *) p;
if (frac_count) value += frac / _pow10 (frac_count);
if (neg) value *= -1.;

View File

@ -69,7 +69,7 @@ main := (
/* Works only for n < 512 */
static inline double
_pow10 (unsigned int exponent)
_pow10 (unsigned exponent)
{
static const double _powers_of_10[] =
{
@ -83,26 +83,27 @@ _pow10 (unsigned int exponent)
100.,
10.
};
unsigned int mask = 1 << (ARRAY_LENGTH (_powers_of_10) - 1);
unsigned mask = 1 << (ARRAY_LENGTH (_powers_of_10) - 1);
double result = 1;
for (const double *power = _powers_of_10; mask; ++power, mask >>= 1)
if (exponent & mask) result *= *power;
return result;
}
/* a variant of strtod that also gets end of buffer in its second argument */
static inline double
strtod_rl (const char *buf, char **end_ptr)
strtod_rl (const char *buf, const char **end_ptr /* IN/OUT */)
{
const char *p, *pe;
double value = 0;
double frac = 0;
double frac_count = 0;
unsigned int exp = 0;
unsigned exp = 0;
bool neg = false, exp_neg = false, exp_overflow = false;
const unsigned long long MAX_FRACT = 0xFFFFFFFFFFFFFull; /* 2^52-1 */
const unsigned int MAX_EXP = 0x7FFu; /* 2^11-1 */
const unsigned MAX_EXP = 0x7FFu; /* 2^11-1 */
p = buf;
pe = p + strlen (p);
pe = *end_ptr;
while (p < pe && ISSPACE (*p))
p++;
@ -113,7 +114,7 @@ strtod_rl (const char *buf, char **end_ptr)
write exec;
}%%
*end_ptr = (char *) p;
*end_ptr = (const char *) p;
if (frac_count) value += frac / _pow10 (frac_count);
if (neg) value *= -1.;

View File

@ -34,8 +34,7 @@ _parse_number (const char **pp, const char *end, T *pv,
bool whole_buffer, Func f)
{
char buf[32];
unsigned int len = hb_min (ARRAY_LENGTH (buf) - 1,
(unsigned int) (end - *pp));
unsigned len = hb_min (ARRAY_LENGTH (buf) - 1, (unsigned) (end - *pp));
strncpy (buf, *pp, len);
buf[len] = '\0';
@ -46,7 +45,8 @@ _parse_number (const char **pp, const char *end, T *pv,
*pv = f (p, &pend);
if (unlikely (errno || p == pend ||
/* Check if consumed whole buffer if is requested */
(whole_buffer && pend - p != end - *pp))) return false;
(whole_buffer && pend - p != end - *pp)))
return false;
*pp += pend - p;
return true;
@ -61,19 +61,20 @@ hb_parse_int (const char **pp, const char *end, int *pv, bool whole_buffer)
}
bool
hb_parse_uint (const char **pp, const char *end, unsigned int *pv,
hb_parse_uint (const char **pp, const char *end, unsigned *pv,
bool whole_buffer, int base)
{
return _parse_number<unsigned int> (pp, end, pv, whole_buffer,
[base] (const char *p, char **end)
{ return strtoul (p, end, base); });
return _parse_number<unsigned> (pp, end, pv, whole_buffer,
[base] (const char *p, char **end)
{ return strtoul (p, end, base); });
}
bool
hb_parse_double (const char **pp, const char *end, double *pv,
bool whole_buffer)
hb_parse_double (const char **pp, const char *end, double *pv, bool whole_buffer)
{
return _parse_number<double> (pp, end, pv, whole_buffer,
[] (const char *p, char **end)
{ return strtod_rl (p, end); });
const char *pend = end;
*pv = strtod_rl (*pp, &pend);
if (unlikely (*pp == pend)) return false;
*pp = pend;
return !whole_buffer || end == pend;
}

View File

@ -25,7 +25,6 @@
#include "hb.hh"
#include "hb-number.hh"
#include "hb-number-parser.hh"
int
@ -170,10 +169,6 @@ main (int argc, char **argv)
assert ((int) roundf (pv * 1000.) == 123);
assert (pp - str == 7);
assert (end - pp == 0);
char *pend;
assert ((int) roundf (strtod_rl (str, &pend) * 1000.) == 123);
assert (pend - str == 7);
}
{
@ -186,10 +181,6 @@ main (int argc, char **argv)
assert ((int) roundf (pv * 1000.) == 123);
assert (pp - str == 6);
assert (end - pp == 0);
char *pend;
assert ((int) roundf (strtod_rl (str, &pend) * 1000.) == 123);
assert (pend - str == 6);
}
{
@ -202,10 +193,6 @@ main (int argc, char **argv)
assert ((int) roundf (pv * 1000.) == 123);
assert (pp - str == 10);
assert (end - pp == 0);
char *pend;
assert ((int) roundf (strtod_rl (str, &pend) * 1000.) == 123);
assert (pend - str == 10);
}
{
@ -219,9 +206,6 @@ main (int argc, char **argv)
assert (pp - str == 13);
assert (end - pp == 0);
char *pend;
assert ((int) roundf (strtod_rl (str, &pend) * 1000.) == -123);
assert (pend - str == 13);
}
{
@ -234,10 +218,6 @@ main (int argc, char **argv)
assert ((int) roundf (pv * 1000.) == -123);
assert (pp - str == 8);
assert (end - pp == 0);
char *pend;
assert ((int) roundf (strtod_rl (str, &pend) * 1000.) == -123);
assert (pend - str == 8);
}
return 0;