@@ -997,7 +997,6 @@ _match_number_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t start, Py_
997997 Py_ssize_t idx = start ;
998998 int is_float = 0 ;
999999 PyObject * rval ;
1000- PyObject * numstr = NULL ;
10011000 PyObject * custom_func ;
10021001
10031002 str = PyUnicode_DATA (pystr );
@@ -1064,32 +1063,62 @@ _match_number_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t start, Py_
10641063
10651064 if (custom_func ) {
10661065 /* copy the section we determined to be a number */
1067- numstr = PyUnicode_FromKindAndData (kind ,
1068- (char * )str + kind * start ,
1069- idx - start );
1066+ PyObject * numstr = PyUnicode_FromKindAndData (kind ,
1067+ (char * )str + kind * start ,
1068+ idx - start );
10701069 if (numstr == NULL )
10711070 return NULL ;
10721071 rval = PyObject_CallOneArg (custom_func , numstr );
1072+ Py_DECREF (numstr );
10731073 }
10741074 else {
10751075 Py_ssize_t i , n ;
1076- char * buf ;
1076+
1077+ /* Fast path for integers with at most 19 digits (excluding the
1078+ optional minus sign): the magnitude always fits in an unsigned
1079+ long long, so we construct the result from it directly. */
1080+ int neg = (PyUnicode_READ (kind , str , start ) == '-' );
1081+ if (!is_float && idx - start - neg <= 19 ) {
1082+ unsigned long long value = 0 ;
1083+ for (i = start + neg ; i < idx ; i ++ ) {
1084+ value = value * 10 + (PyUnicode_READ (kind , str , i ) - '0' );
1085+ }
1086+ * next_idx_ptr = idx ;
1087+ rval = PyLong_FromUnsignedLongLong (value );
1088+ if (neg && rval != NULL ) {
1089+ Py_SETREF (rval , PyNumber_Negative (rval ));
1090+ }
1091+ return rval ;
1092+ }
1093+
10771094 /* Straight conversion to ASCII, to avoid costly conversion of
10781095 decimal unicode digits (which cannot appear here) */
10791096 n = idx - start ;
1080- numstr = PyBytes_FromStringAndSize (NULL , n );
1081- if (numstr == NULL )
1082- return NULL ;
1083- buf = PyBytes_AS_STRING (numstr );
1097+ char stackbuf [64 ];
1098+ PyObject * numstr = NULL ;
1099+ char * buf ;
1100+ if (n < (Py_ssize_t )sizeof (stackbuf )) {
1101+ buf = stackbuf ;
1102+ buf [n ] = '\0' ;
1103+ }
1104+ else {
1105+ numstr = PyBytes_FromStringAndSize (NULL , n );
1106+ if (numstr == NULL )
1107+ return NULL ;
1108+ buf = PyBytes_AS_STRING (numstr );
1109+ }
10841110 for (i = 0 ; i < n ; i ++ ) {
10851111 buf [i ] = (char ) PyUnicode_READ (kind , str , i + start );
10861112 }
1087- if (is_float )
1088- rval = PyFloat_FromString (numstr );
1089- else
1113+ if (is_float ) {
1114+ double d = PyOS_string_to_double (buf , NULL , NULL );
1115+ rval = (d == -1.0 && PyErr_Occurred ()) ? NULL : PyFloat_FromDouble (d );
1116+ }
1117+ else {
10901118 rval = PyLong_FromString (buf , NULL , 10 );
1119+ }
1120+ Py_XDECREF (numstr );
10911121 }
1092- Py_DECREF (numstr );
10931122 * next_idx_ptr = idx ;
10941123 return rval ;
10951124}
0 commit comments