1*2d1272b8SAndroid Build Coastguard Worker
2*2d1272b8SAndroid Build Coastguard Worker #line 1 "hb-number-parser.rl"
3*2d1272b8SAndroid Build Coastguard Worker /*
4*2d1272b8SAndroid Build Coastguard Worker * Copyright © 2019 Ebrahim Byagowi
5*2d1272b8SAndroid Build Coastguard Worker *
6*2d1272b8SAndroid Build Coastguard Worker * This is part of HarfBuzz, a text shaping library.
7*2d1272b8SAndroid Build Coastguard Worker *
8*2d1272b8SAndroid Build Coastguard Worker * Permission is hereby granted, without written agreement and without
9*2d1272b8SAndroid Build Coastguard Worker * license or royalty fees, to use, copy, modify, and distribute this
10*2d1272b8SAndroid Build Coastguard Worker * software and its documentation for any purpose, provided that the
11*2d1272b8SAndroid Build Coastguard Worker * above copyright notice and the following two paragraphs appear in
12*2d1272b8SAndroid Build Coastguard Worker * all copies of this software.
13*2d1272b8SAndroid Build Coastguard Worker *
14*2d1272b8SAndroid Build Coastguard Worker * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
15*2d1272b8SAndroid Build Coastguard Worker * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
16*2d1272b8SAndroid Build Coastguard Worker * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
17*2d1272b8SAndroid Build Coastguard Worker * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
18*2d1272b8SAndroid Build Coastguard Worker * DAMAGE.
19*2d1272b8SAndroid Build Coastguard Worker *
20*2d1272b8SAndroid Build Coastguard Worker * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
21*2d1272b8SAndroid Build Coastguard Worker * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
22*2d1272b8SAndroid Build Coastguard Worker * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
23*2d1272b8SAndroid Build Coastguard Worker * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
24*2d1272b8SAndroid Build Coastguard Worker * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
25*2d1272b8SAndroid Build Coastguard Worker *
26*2d1272b8SAndroid Build Coastguard Worker */
27*2d1272b8SAndroid Build Coastguard Worker
28*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NUMBER_PARSER_HH
29*2d1272b8SAndroid Build Coastguard Worker #define HB_NUMBER_PARSER_HH
30*2d1272b8SAndroid Build Coastguard Worker
31*2d1272b8SAndroid Build Coastguard Worker #include "hb.hh"
32*2d1272b8SAndroid Build Coastguard Worker
33*2d1272b8SAndroid Build Coastguard Worker
34*2d1272b8SAndroid Build Coastguard Worker #line 35 "hb-number-parser.hh"
35*2d1272b8SAndroid Build Coastguard Worker static const unsigned char _double_parser_trans_keys[] = {
36*2d1272b8SAndroid Build Coastguard Worker 0u, 0u, 43u, 57u, 46u, 57u, 48u, 57u, 43u, 57u, 48u, 57u, 48u, 101u, 48u, 57u,
37*2d1272b8SAndroid Build Coastguard Worker 46u, 101u, 0
38*2d1272b8SAndroid Build Coastguard Worker };
39*2d1272b8SAndroid Build Coastguard Worker
40*2d1272b8SAndroid Build Coastguard Worker static const char _double_parser_key_spans[] = {
41*2d1272b8SAndroid Build Coastguard Worker 0, 15, 12, 10, 15, 10, 54, 10,
42*2d1272b8SAndroid Build Coastguard Worker 56
43*2d1272b8SAndroid Build Coastguard Worker };
44*2d1272b8SAndroid Build Coastguard Worker
45*2d1272b8SAndroid Build Coastguard Worker static const unsigned char _double_parser_index_offsets[] = {
46*2d1272b8SAndroid Build Coastguard Worker 0, 0, 16, 29, 40, 56, 67, 122,
47*2d1272b8SAndroid Build Coastguard Worker 133
48*2d1272b8SAndroid Build Coastguard Worker };
49*2d1272b8SAndroid Build Coastguard Worker
50*2d1272b8SAndroid Build Coastguard Worker static const char _double_parser_indicies[] = {
51*2d1272b8SAndroid Build Coastguard Worker 0, 1, 2, 3, 1, 4, 4,
52*2d1272b8SAndroid Build Coastguard Worker 4, 4, 4, 4, 4, 4, 4, 4,
53*2d1272b8SAndroid Build Coastguard Worker 1, 3, 1, 4, 4, 4, 4, 4,
54*2d1272b8SAndroid Build Coastguard Worker 4, 4, 4, 4, 4, 1, 5, 5,
55*2d1272b8SAndroid Build Coastguard Worker 5, 5, 5, 5, 5, 5, 5, 5,
56*2d1272b8SAndroid Build Coastguard Worker 1, 6, 1, 7, 1, 1, 8, 8,
57*2d1272b8SAndroid Build Coastguard Worker 8, 8, 8, 8, 8, 8, 8, 8,
58*2d1272b8SAndroid Build Coastguard Worker 1, 8, 8, 8, 8, 8, 8, 8,
59*2d1272b8SAndroid Build Coastguard Worker 8, 8, 8, 1, 5, 5, 5, 5,
60*2d1272b8SAndroid Build Coastguard Worker 5, 5, 5, 5, 5, 5, 1, 1,
61*2d1272b8SAndroid Build Coastguard Worker 1, 1, 1, 1, 1, 1, 1, 1,
62*2d1272b8SAndroid Build Coastguard Worker 1, 9, 1, 1, 1, 1, 1, 1,
63*2d1272b8SAndroid Build Coastguard Worker 1, 1, 1, 1, 1, 1, 1, 1,
64*2d1272b8SAndroid Build Coastguard Worker 1, 1, 1, 1, 1, 1, 1, 1,
65*2d1272b8SAndroid Build Coastguard Worker 1, 1, 1, 1, 1, 1, 1, 1,
66*2d1272b8SAndroid Build Coastguard Worker 1, 9, 1, 8, 8, 8, 8, 8,
67*2d1272b8SAndroid Build Coastguard Worker 8, 8, 8, 8, 8, 1, 3, 1,
68*2d1272b8SAndroid Build Coastguard Worker 4, 4, 4, 4, 4, 4, 4, 4,
69*2d1272b8SAndroid Build Coastguard Worker 4, 4, 1, 1, 1, 1, 1, 1,
70*2d1272b8SAndroid Build Coastguard Worker 1, 1, 1, 1, 1, 9, 1, 1,
71*2d1272b8SAndroid Build Coastguard Worker 1, 1, 1, 1, 1, 1, 1, 1,
72*2d1272b8SAndroid Build Coastguard Worker 1, 1, 1, 1, 1, 1, 1, 1,
73*2d1272b8SAndroid Build Coastguard Worker 1, 1, 1, 1, 1, 1, 1, 1,
74*2d1272b8SAndroid Build Coastguard Worker 1, 1, 1, 1, 1, 9, 1, 0
75*2d1272b8SAndroid Build Coastguard Worker };
76*2d1272b8SAndroid Build Coastguard Worker
77*2d1272b8SAndroid Build Coastguard Worker static const char _double_parser_trans_targs[] = {
78*2d1272b8SAndroid Build Coastguard Worker 2, 0, 2, 3, 8, 6, 5, 5,
79*2d1272b8SAndroid Build Coastguard Worker 7, 4
80*2d1272b8SAndroid Build Coastguard Worker };
81*2d1272b8SAndroid Build Coastguard Worker
82*2d1272b8SAndroid Build Coastguard Worker static const char _double_parser_trans_actions[] = {
83*2d1272b8SAndroid Build Coastguard Worker 0, 0, 1, 0, 2, 3, 0, 4,
84*2d1272b8SAndroid Build Coastguard Worker 5, 0
85*2d1272b8SAndroid Build Coastguard Worker };
86*2d1272b8SAndroid Build Coastguard Worker
87*2d1272b8SAndroid Build Coastguard Worker static const int double_parser_start = 1;
88*2d1272b8SAndroid Build Coastguard Worker static const int double_parser_first_final = 6;
89*2d1272b8SAndroid Build Coastguard Worker static const int double_parser_error = 0;
90*2d1272b8SAndroid Build Coastguard Worker
91*2d1272b8SAndroid Build Coastguard Worker static const int double_parser_en_main = 1;
92*2d1272b8SAndroid Build Coastguard Worker
93*2d1272b8SAndroid Build Coastguard Worker
94*2d1272b8SAndroid Build Coastguard Worker #line 68 "hb-number-parser.rl"
95*2d1272b8SAndroid Build Coastguard Worker
96*2d1272b8SAndroid Build Coastguard Worker
97*2d1272b8SAndroid Build Coastguard Worker /* Works only for n < 512 */
98*2d1272b8SAndroid Build Coastguard Worker static inline double
_pow10(unsigned exponent)99*2d1272b8SAndroid Build Coastguard Worker _pow10 (unsigned exponent)
100*2d1272b8SAndroid Build Coastguard Worker {
101*2d1272b8SAndroid Build Coastguard Worker static const double _powers_of_10[] =
102*2d1272b8SAndroid Build Coastguard Worker {
103*2d1272b8SAndroid Build Coastguard Worker 1.0e+256,
104*2d1272b8SAndroid Build Coastguard Worker 1.0e+128,
105*2d1272b8SAndroid Build Coastguard Worker 1.0e+64,
106*2d1272b8SAndroid Build Coastguard Worker 1.0e+32,
107*2d1272b8SAndroid Build Coastguard Worker 1.0e+16,
108*2d1272b8SAndroid Build Coastguard Worker 1.0e+8,
109*2d1272b8SAndroid Build Coastguard Worker 10000.,
110*2d1272b8SAndroid Build Coastguard Worker 100.,
111*2d1272b8SAndroid Build Coastguard Worker 10.
112*2d1272b8SAndroid Build Coastguard Worker };
113*2d1272b8SAndroid Build Coastguard Worker unsigned mask = 1 << (ARRAY_LENGTH (_powers_of_10) - 1);
114*2d1272b8SAndroid Build Coastguard Worker double result = 1;
115*2d1272b8SAndroid Build Coastguard Worker for (const double *power = _powers_of_10; mask; ++power, mask >>= 1)
116*2d1272b8SAndroid Build Coastguard Worker if (exponent & mask) result *= *power;
117*2d1272b8SAndroid Build Coastguard Worker return result;
118*2d1272b8SAndroid Build Coastguard Worker }
119*2d1272b8SAndroid Build Coastguard Worker
120*2d1272b8SAndroid Build Coastguard Worker /* a variant of strtod that also gets end of buffer in its second argument */
121*2d1272b8SAndroid Build Coastguard Worker static inline double
strtod_rl(const char * p,const char ** end_ptr)122*2d1272b8SAndroid Build Coastguard Worker strtod_rl (const char *p, const char **end_ptr /* IN/OUT */)
123*2d1272b8SAndroid Build Coastguard Worker {
124*2d1272b8SAndroid Build Coastguard Worker double value = 0;
125*2d1272b8SAndroid Build Coastguard Worker double frac = 0;
126*2d1272b8SAndroid Build Coastguard Worker double frac_count = 0;
127*2d1272b8SAndroid Build Coastguard Worker unsigned exp = 0;
128*2d1272b8SAndroid Build Coastguard Worker bool neg = false, exp_neg = false, exp_overflow = false;
129*2d1272b8SAndroid Build Coastguard Worker const unsigned long long MAX_FRACT = 0xFFFFFFFFFFFFFull; /* 2^52-1 */
130*2d1272b8SAndroid Build Coastguard Worker const unsigned MAX_EXP = 0x7FFu; /* 2^11-1 */
131*2d1272b8SAndroid Build Coastguard Worker
132*2d1272b8SAndroid Build Coastguard Worker const char *pe = *end_ptr;
133*2d1272b8SAndroid Build Coastguard Worker while (p < pe && ISSPACE (*p))
134*2d1272b8SAndroid Build Coastguard Worker p++;
135*2d1272b8SAndroid Build Coastguard Worker
136*2d1272b8SAndroid Build Coastguard Worker int cs;
137*2d1272b8SAndroid Build Coastguard Worker
138*2d1272b8SAndroid Build Coastguard Worker #line 139 "hb-number-parser.hh"
139*2d1272b8SAndroid Build Coastguard Worker {
140*2d1272b8SAndroid Build Coastguard Worker cs = double_parser_start;
141*2d1272b8SAndroid Build Coastguard Worker }
142*2d1272b8SAndroid Build Coastguard Worker
143*2d1272b8SAndroid Build Coastguard Worker #line 144 "hb-number-parser.hh"
144*2d1272b8SAndroid Build Coastguard Worker {
145*2d1272b8SAndroid Build Coastguard Worker int _slen;
146*2d1272b8SAndroid Build Coastguard Worker int _trans;
147*2d1272b8SAndroid Build Coastguard Worker const unsigned char *_keys;
148*2d1272b8SAndroid Build Coastguard Worker const char *_inds;
149*2d1272b8SAndroid Build Coastguard Worker if ( p == pe )
150*2d1272b8SAndroid Build Coastguard Worker goto _test_eof;
151*2d1272b8SAndroid Build Coastguard Worker if ( cs == 0 )
152*2d1272b8SAndroid Build Coastguard Worker goto _out;
153*2d1272b8SAndroid Build Coastguard Worker _resume:
154*2d1272b8SAndroid Build Coastguard Worker _keys = _double_parser_trans_keys + (cs<<1);
155*2d1272b8SAndroid Build Coastguard Worker _inds = _double_parser_indicies + _double_parser_index_offsets[cs];
156*2d1272b8SAndroid Build Coastguard Worker
157*2d1272b8SAndroid Build Coastguard Worker _slen = _double_parser_key_spans[cs];
158*2d1272b8SAndroid Build Coastguard Worker _trans = _inds[ _slen > 0 && _keys[0] <=(*p) &&
159*2d1272b8SAndroid Build Coastguard Worker (*p) <= _keys[1] ?
160*2d1272b8SAndroid Build Coastguard Worker (*p) - _keys[0] : _slen ];
161*2d1272b8SAndroid Build Coastguard Worker
162*2d1272b8SAndroid Build Coastguard Worker cs = _double_parser_trans_targs[_trans];
163*2d1272b8SAndroid Build Coastguard Worker
164*2d1272b8SAndroid Build Coastguard Worker if ( _double_parser_trans_actions[_trans] == 0 )
165*2d1272b8SAndroid Build Coastguard Worker goto _again;
166*2d1272b8SAndroid Build Coastguard Worker
167*2d1272b8SAndroid Build Coastguard Worker switch ( _double_parser_trans_actions[_trans] ) {
168*2d1272b8SAndroid Build Coastguard Worker case 1:
169*2d1272b8SAndroid Build Coastguard Worker #line 37 "hb-number-parser.rl"
170*2d1272b8SAndroid Build Coastguard Worker { neg = true; }
171*2d1272b8SAndroid Build Coastguard Worker break;
172*2d1272b8SAndroid Build Coastguard Worker case 4:
173*2d1272b8SAndroid Build Coastguard Worker #line 38 "hb-number-parser.rl"
174*2d1272b8SAndroid Build Coastguard Worker { exp_neg = true; }
175*2d1272b8SAndroid Build Coastguard Worker break;
176*2d1272b8SAndroid Build Coastguard Worker case 2:
177*2d1272b8SAndroid Build Coastguard Worker #line 40 "hb-number-parser.rl"
178*2d1272b8SAndroid Build Coastguard Worker {
179*2d1272b8SAndroid Build Coastguard Worker value = value * 10. + ((*p) - '0');
180*2d1272b8SAndroid Build Coastguard Worker }
181*2d1272b8SAndroid Build Coastguard Worker break;
182*2d1272b8SAndroid Build Coastguard Worker case 3:
183*2d1272b8SAndroid Build Coastguard Worker #line 43 "hb-number-parser.rl"
184*2d1272b8SAndroid Build Coastguard Worker {
185*2d1272b8SAndroid Build Coastguard Worker if (likely (frac <= MAX_FRACT / 10))
186*2d1272b8SAndroid Build Coastguard Worker {
187*2d1272b8SAndroid Build Coastguard Worker frac = frac * 10. + ((*p) - '0');
188*2d1272b8SAndroid Build Coastguard Worker ++frac_count;
189*2d1272b8SAndroid Build Coastguard Worker }
190*2d1272b8SAndroid Build Coastguard Worker }
191*2d1272b8SAndroid Build Coastguard Worker break;
192*2d1272b8SAndroid Build Coastguard Worker case 5:
193*2d1272b8SAndroid Build Coastguard Worker #line 50 "hb-number-parser.rl"
194*2d1272b8SAndroid Build Coastguard Worker {
195*2d1272b8SAndroid Build Coastguard Worker if (likely (exp * 10 + ((*p) - '0') <= MAX_EXP))
196*2d1272b8SAndroid Build Coastguard Worker exp = exp * 10 + ((*p) - '0');
197*2d1272b8SAndroid Build Coastguard Worker else
198*2d1272b8SAndroid Build Coastguard Worker exp_overflow = true;
199*2d1272b8SAndroid Build Coastguard Worker }
200*2d1272b8SAndroid Build Coastguard Worker break;
201*2d1272b8SAndroid Build Coastguard Worker #line 202 "hb-number-parser.hh"
202*2d1272b8SAndroid Build Coastguard Worker }
203*2d1272b8SAndroid Build Coastguard Worker
204*2d1272b8SAndroid Build Coastguard Worker _again:
205*2d1272b8SAndroid Build Coastguard Worker if ( cs == 0 )
206*2d1272b8SAndroid Build Coastguard Worker goto _out;
207*2d1272b8SAndroid Build Coastguard Worker if ( ++p != pe )
208*2d1272b8SAndroid Build Coastguard Worker goto _resume;
209*2d1272b8SAndroid Build Coastguard Worker _test_eof: {}
210*2d1272b8SAndroid Build Coastguard Worker _out: {}
211*2d1272b8SAndroid Build Coastguard Worker }
212*2d1272b8SAndroid Build Coastguard Worker
213*2d1272b8SAndroid Build Coastguard Worker #line 113 "hb-number-parser.rl"
214*2d1272b8SAndroid Build Coastguard Worker
215*2d1272b8SAndroid Build Coastguard Worker
216*2d1272b8SAndroid Build Coastguard Worker *end_ptr = p;
217*2d1272b8SAndroid Build Coastguard Worker
218*2d1272b8SAndroid Build Coastguard Worker if (frac_count) value += frac / _pow10 (frac_count);
219*2d1272b8SAndroid Build Coastguard Worker if (neg) value *= -1.;
220*2d1272b8SAndroid Build Coastguard Worker
221*2d1272b8SAndroid Build Coastguard Worker if (unlikely (exp_overflow))
222*2d1272b8SAndroid Build Coastguard Worker {
223*2d1272b8SAndroid Build Coastguard Worker if (value == 0) return value;
224*2d1272b8SAndroid Build Coastguard Worker if (exp_neg) return neg ? -DBL_MIN : DBL_MIN;
225*2d1272b8SAndroid Build Coastguard Worker else return neg ? -DBL_MAX : DBL_MAX;
226*2d1272b8SAndroid Build Coastguard Worker }
227*2d1272b8SAndroid Build Coastguard Worker
228*2d1272b8SAndroid Build Coastguard Worker if (exp)
229*2d1272b8SAndroid Build Coastguard Worker {
230*2d1272b8SAndroid Build Coastguard Worker if (exp_neg) value /= _pow10 (exp);
231*2d1272b8SAndroid Build Coastguard Worker else value *= _pow10 (exp);
232*2d1272b8SAndroid Build Coastguard Worker }
233*2d1272b8SAndroid Build Coastguard Worker
234*2d1272b8SAndroid Build Coastguard Worker return value;
235*2d1272b8SAndroid Build Coastguard Worker }
236*2d1272b8SAndroid Build Coastguard Worker
237*2d1272b8SAndroid Build Coastguard Worker #endif /* HB_NUMBER_PARSER_HH */
238