1313#include <math.h>
1414#endif
1515
16- #if defined(UNIX )
17-
18- #include <ctype.h>
19- #include <errno.h>
20-
2116mp_obj_t mp_parse_num_integer (const char * restrict str , uint len , int base ) {
22- // TODO at the moment we ignore len; we should honour it!
23- // TODO detect integer overflow and return bignum
24-
25- int c , neg = 0 ;
26- const char * p = str ;
27- char * num ;
28- long found ;
17+ const char * restrict top = str + len ;
18+ bool neg = false;
2919
3020 // check radix base
3121 if ((base != 0 && base < 2 ) || base > 36 ) {
3222 nlr_jump (mp_obj_new_exception_msg (& mp_type_ValueError , "ValueError: int() arg 2 must be >=2 and <= 36" ));
3323 }
34- // skip surrounded whitespace
35- while (isspace ((c = * (p ++ ))));
36- if (c == 0 ) {
37- goto value_error ;
38- }
39- // preced sign
40- if (c == '+' || c == '-' ) {
41- neg = - (c == '-' );
42- } else {
43- p -- ;
24+
25+ // skip leading space
26+ for (; str < top && unichar_isspace (* str ); str ++ ) {
4427 }
4528
46- len -= p - str ;
47- int skip = mp_parse_num_base (p , len , & base );
48- p += skip ;
49- len -= skip ;
50-
51- errno = 0 ;
52- found = strtol (p , & num , base );
53- if (errno ) {
54- goto value_error ;
55- } else if (found && * (num ) == 0 ) {
56- goto done ;
57- } else if (found || num != p ) {
58- goto check_tail_space ;
59- } else {
60- goto value_error ;
29+ // parse optional sign
30+ if (str < top ) {
31+ if (* str == '+' ) {
32+ str ++ ;
33+ } else if (* str == '-' ) {
34+ str ++ ;
35+ neg = true;
36+ }
6137 }
6238
63- check_tail_space :
64- if (* (num ) != 0 ) {
65- while (isspace ((c = * (num ++ ))));
66- if (c != 0 ) {
67- goto value_error ;
39+ // parse optional base prefix
40+ str += mp_parse_num_base (str , top - str , & base );
41+
42+ // string should be an integer number
43+ machine_int_t int_val = 0 ;
44+ for (; str < top ; str ++ ) {
45+ machine_int_t old_val = int_val ;
46+ int dig = * str ;
47+ if (unichar_isdigit (dig ) && dig - '0' < base ) {
48+ // 0-9 digit
49+ int_val = base * int_val + dig - '0' ;
50+ } else if (base == 16 ) {
51+ dig |= 0x20 ;
52+ if ('a' <= dig && dig <= 'f' ) {
53+ // a-f hex digit
54+ int_val = base * int_val + dig - 'a' + 10 ;
55+ } else {
56+ // unknown character
57+ break ;
58+ }
59+ } else {
60+ // unknown character
61+ break ;
62+ }
63+ if (int_val < old_val ) {
64+ // If new value became less than previous, it's overflow
65+ goto overflow ;
66+ } else if ((old_val ^ int_val ) & WORD_MSBIT_HIGH ) {
67+ // If signed number changed sign - it's overflow
68+ goto overflow ;
6869 }
6970 }
7071
71- done :
72- return MP_OBJ_NEW_SMALL_INT ((found ^ neg ) - neg );
72+ // negate value if needed
73+ if (neg ) {
74+ int_val = - int_val ;
75+ }
7376
74- value_error :
75- nlr_jump ( mp_obj_new_exception_msg_varg ( & mp_type_ValueError , "invalid literal for int() with base %d: '%s'" , base , str ));
76- }
77+ // skip trailing space
78+ for (; str < top && unichar_isspace ( * str ); str ++ ) {
79+ }
7780
78- #else /* defined(UNIX) */
81+ // check we reached the end of the string
82+ if (str != top ) {
83+ nlr_jump (mp_obj_new_exception_msg (& mp_type_SyntaxError , "invalid syntax for number" ));
84+ }
7985
80- mp_obj_t mp_parse_num_integer (const char * restrict str , uint len , int base ) {
81- // TODO port strtol to stm
82- return MP_OBJ_NEW_SMALL_INT (0 );
83- }
86+ // return the object
87+ return MP_OBJ_NEW_SMALL_INT (int_val );
8488
85- #endif /* defined(UNIX) */
89+ overflow :
90+ // TODO reparse using bignum
91+ nlr_jump (mp_obj_new_exception_msg (& mp_type_ValueError , "overflow parsing integer" ));
92+ }
8693
8794#define PARSE_DEC_IN_INTG (1)
8895#define PARSE_DEC_IN_FRAC (2)
@@ -96,10 +103,10 @@ mp_obj_t mp_parse_num_decimal(const char *str, uint len, bool allow_imag, bool f
96103 bool imag = false;
97104
98105 // skip leading space
99- for (; str < top && isspace (* str ); str ++ ) {
106+ for (; str < top && unichar_isspace (* str ); str ++ ) {
100107 }
101108
102- // get optional sign
109+ // parse optional sign
103110 if (str < top ) {
104111 if (* str == '+' ) {
105112 str ++ ;
@@ -187,7 +194,7 @@ mp_obj_t mp_parse_num_decimal(const char *str, uint len, bool allow_imag, bool f
187194 }
188195
189196 // skip trailing space
190- for (; str < top && isspace (* str ); str ++ ) {
197+ for (; str < top && unichar_isspace (* str ); str ++ ) {
191198 }
192199
193200 // check we reached the end of the string
0 commit comments