[number] Make hb_parse_double simpler now that we don't have to mimic strtod
This commit is contained in:
parent
44fe1c8ff1
commit
dca8ba6b6d
|
@ -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.;
|
||||
|
|
|
@ -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.;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue