xref: /aosp_15_r20/external/harfbuzz_ng/src/hb-number-parser.hh (revision 2d1272b857b1f7575e6e246373e1cb218663db8a)
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