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