@@ -46,6 +46,29 @@ static NORETURN void raise_exc(mp_obj_t exc, mp_lexer_t *lex) {
46
46
nlr_raise (exc );
47
47
}
48
48
49
+ // mp_parse_num_integer parses a small integer directly, except for the
50
+ // special case where bigint support is long long, in which case
51
+ // it parses long long and returns either a long long or a small int.
52
+ #if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_LONGLONG
53
+ typedef mp_int_t parsed_int_t ;
54
+
55
+ #define parsed_int_mul_overflow mp_small_int_mul_overflow
56
+ inline static bool parsed_int_fits (parsed_int_t int_val , mp_uint_t dig ) {
57
+ return MP_SMALL_INT_FITS (int_val + dig );
58
+ }
59
+ #else
60
+ typedef long long parsed_int_t ;
61
+
62
+ #define parsed_int_mul_overflow mp_mul_ll_overflow
63
+
64
+ inline static bool parsed_int_fits (parsed_int_t int_val , mp_uint_t dig ) {
65
+ // Unlike MP_SMALL_INT, we can't be assured that adding a digit won't
66
+ // trigger an overflow so need to explicitly check
67
+ assert (int_val >= 0 );
68
+ return int_val <= LLONG_MAX - dig ;
69
+ }
70
+ #endif
71
+
49
72
mp_obj_t mp_parse_num_integer (const char * restrict str_ , size_t len , int base , mp_lexer_t * lex ) {
50
73
const byte * restrict str = (const byte * )str_ ;
51
74
const byte * restrict top = str + len ;
@@ -76,7 +99,7 @@ mp_obj_t mp_parse_num_integer(const char *restrict str_, size_t len, int base, m
76
99
str += mp_parse_num_base ((const char * )str , top - str , & base );
77
100
78
101
// string should be an integer number
79
- mp_int_t int_val = 0 ;
102
+ parsed_int_t int_val = 0 ;
80
103
const byte * restrict str_val_start = str ;
81
104
for (; str < top ; str ++ ) {
82
105
// get next digit as a value
@@ -99,24 +122,27 @@ mp_obj_t mp_parse_num_integer(const char *restrict str_, size_t len, int base, m
99
122
}
100
123
101
124
// add next digi and check for overflow
102
- if (mp_small_int_mul_overflow (int_val , base , & int_val )) {
125
+ if (parsed_int_mul_overflow (int_val , base , & int_val )) {
103
126
goto overflow ;
104
127
}
105
- int_val += dig ;
106
- if (!MP_SMALL_INT_FITS (int_val )) {
128
+ if (!parsed_int_fits (int_val , dig )) {
107
129
goto overflow ;
108
130
}
131
+ int_val += dig ;
109
132
}
110
133
111
134
// negate value if needed
112
135
if (neg ) {
113
136
int_val = - int_val ;
114
137
}
115
138
116
- // create the small int
139
+ #if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_LONGLONG
140
+ ret_val = mp_obj_new_int_from_ll (int_val ); // Could be large or small int
141
+ #else
117
142
ret_val = MP_OBJ_NEW_SMALL_INT (int_val );
118
-
119
143
have_ret_val :
144
+ #endif
145
+
120
146
// check we parsed something
121
147
if (str == str_val_start ) {
122
148
goto value_error ;
@@ -135,13 +161,17 @@ mp_obj_t mp_parse_num_integer(const char *restrict str_, size_t len, int base, m
135
161
return ret_val ;
136
162
137
163
overflow :
164
+ #if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_LONGLONG
138
165
// reparse using long int
139
166
{
140
167
const char * s2 = (const char * )str_val_start ;
141
168
ret_val = mp_obj_new_int_from_str_len (& s2 , top - str_val_start , neg , base );
142
169
str = (const byte * )s2 ;
143
170
goto have_ret_val ;
144
171
}
172
+ #else
173
+ mp_raise_msg (& mp_type_OverflowError , MP_ERROR_TEXT ("result overflows long long storage" ));
174
+ #endif
145
175
146
176
value_error :
147
177
{
0 commit comments