tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

hb-number-parser.rl (3216B)


      1 /*
      2 * Copyright © 2019  Ebrahim Byagowi
      3 *
      4 *  This is part of HarfBuzz, a text shaping library.
      5 *
      6 * Permission is hereby granted, without written agreement and without
      7 * license or royalty fees, to use, copy, modify, and distribute this
      8 * software and its documentation for any purpose, provided that the
      9 * above copyright notice and the following two paragraphs appear in
     10 * all copies of this software.
     11 *
     12 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
     13 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
     14 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
     15 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
     16 * DAMAGE.
     17 *
     18 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
     19 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
     20 * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
     21 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
     22 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
     23 *
     24 */
     25 
     26 #ifndef HB_NUMBER_PARSER_HH
     27 #define HB_NUMBER_PARSER_HH
     28 
     29 #include "hb.hh"
     30 
     31 %%{
     32 
     33 machine double_parser;
     34 alphtype unsigned char;
     35 write data;
     36 
     37 action see_neg { neg = true; }
     38 action see_exp_neg { exp_neg = true; }
     39 
     40 action add_int  {
     41 value = value * 10. + (fc - '0');
     42 }
     43 action add_frac {
     44 if (likely (frac <= MAX_FRACT / 10))
     45 {
     46   frac = frac * 10. + (fc - '0');
     47   ++frac_count;
     48 }
     49 }
     50 action add_exp  {
     51 if (likely (exp * 10 + (fc - '0') <= MAX_EXP))
     52   exp = exp * 10 + (fc - '0');
     53 else
     54   exp_overflow = true;
     55 }
     56 
     57 num = [0-9]+;
     58 
     59 main := (
     60 (
     61 	(('+'|'-'@see_neg)? num @add_int) ('.' num @add_frac)?
     62 	|
     63 	(('+'|'-'@see_neg)? '.' num @add_frac)
     64 )
     65 (('e'|'E') (('+'|'-'@see_exp_neg)? num @add_exp))?
     66 );
     67 
     68 }%%
     69 
     70 /* Works only for n < 512 */
     71 static inline double
     72 _pow10 (unsigned exponent)
     73 {
     74  static const double _powers_of_10[] =
     75  {
     76    1.0e+256,
     77    1.0e+128,
     78    1.0e+64,
     79    1.0e+32,
     80    1.0e+16,
     81    1.0e+8,
     82    10000.,
     83    100.,
     84    10.
     85  };
     86  unsigned mask = 1 << (ARRAY_LENGTH (_powers_of_10) - 1);
     87  double result = 1;
     88  for (const double *power = _powers_of_10; mask; ++power, mask >>= 1)
     89    if (exponent & mask) result *= *power;
     90  return result;
     91 }
     92 
     93 /* a variant of strtod that also gets end of buffer in its second argument */
     94 static inline double
     95 strtod_rl (const char *p, const char **end_ptr /* IN/OUT */)
     96 {
     97  double value = 0;
     98  double frac = 0;
     99  double frac_count = 0;
    100  unsigned exp = 0;
    101  bool neg = false, exp_neg = false, exp_overflow = false;
    102  const unsigned long long MAX_FRACT = 0xFFFFFFFFFFFFFull; /* 2^52-1 */
    103  const unsigned MAX_EXP = 0x7FFu; /* 2^11-1 */
    104 
    105  const char *pe = *end_ptr;
    106  while (p < pe && ISSPACE (*p))
    107    p++;
    108 
    109  int cs;
    110  %%{
    111    write init;
    112    write exec;
    113  }%%
    114 
    115  *end_ptr = p;
    116 
    117  if (frac_count) value += frac / _pow10 (frac_count);
    118  if (neg) value *= -1.;
    119 
    120  if (unlikely (exp_overflow))
    121  {
    122    if (value == 0) return value;
    123    if (exp_neg)    return neg ? -DBL_MIN : DBL_MIN;
    124    else            return neg ? -DBL_MAX : DBL_MAX;
    125  }
    126 
    127  if (exp)
    128  {
    129    if (exp_neg) value /= _pow10 (exp);
    130    else         value *= _pow10 (exp);
    131  }
    132 
    133  return value;
    134 }
    135 
    136 #endif /* HB_NUMBER_PARSER_HH */