From dca8ba6b6d637ebfc51d658a893e8dbda28b7709 Mon Sep 17 00:00:00 2001 From: Ebrahim Byagowi Date: Sun, 10 May 2020 16:57:45 +0430 Subject: [PATCH] [number] Make hb_parse_double simpler now that we don't have to mimic strtod --- src/hb-number-parser.hh | 23 ++++++++++++----------- src/hb-number-parser.rl | 15 ++++++++------- src/hb-number.cc | 25 +++++++++++++------------ src/test-number.cc | 20 -------------------- 4 files changed, 33 insertions(+), 50 deletions(-) diff --git a/src/hb-number-parser.hh b/src/hb-number-parser.hh index 02f4f7fd8..afad228f6 100644 --- a/src/hb-number-parser.hh +++ b/src/hb-number-parser.hh @@ -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.; diff --git a/src/hb-number-parser.rl b/src/hb-number-parser.rl index 28bbf9439..1de262afc 100644 --- a/src/hb-number-parser.rl +++ b/src/hb-number-parser.rl @@ -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.; diff --git a/src/hb-number.cc b/src/hb-number.cc index e68b10d9b..6e4f3f7eb 100644 --- a/src/hb-number.cc +++ b/src/hb-number.cc @@ -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 (pp, end, pv, whole_buffer, - [base] (const char *p, char **end) - { return strtoul (p, end, base); }); + return _parse_number (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 (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; } diff --git a/src/test-number.cc b/src/test-number.cc index 468de6f42..57835288c 100644 --- a/src/test-number.cc +++ b/src/test-number.cc @@ -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;