mirror of
				https://github.com/python/cpython.git
				synced 2025-10-30 21:21:22 +00:00 
			
		
		
		
	1. Add string conversions to int(), long(), float(). (Not to complex()!)
2. Fix two bugs in complex(): - Memory leak when using complex(classinstance) -- r was never DECREF'ed. - Conversion of the second argument, if not complex, was done using the type vector of the 1st.
This commit is contained in:
		
							parent
							
								
									dddf7a6fb4
								
							
						
					
					
						commit
						c6472e9ee1
					
				
					 1 changed files with 127 additions and 7 deletions
				
			
		|  | @ -49,6 +49,9 @@ PERFORMANCE OF THIS SOFTWARE. | ||||||
| /* Forward */ | /* Forward */ | ||||||
| static object *filterstring PROTO((object *, object *)); | static object *filterstring PROTO((object *, object *)); | ||||||
| static object *filtertuple  PROTO((object *, object *)); | static object *filtertuple  PROTO((object *, object *)); | ||||||
|  | static object *int_from_string PROTO((object *)); | ||||||
|  | static object *long_from_string PROTO((object *)); | ||||||
|  | static object *float_from_string PROTO((object *)); | ||||||
| 
 | 
 | ||||||
| static object * | static object * | ||||||
| builtin___import__(self, args) | builtin___import__(self, args) | ||||||
|  | @ -300,14 +303,16 @@ builtin_complex(self, args) | ||||||
| 	object *r, *i, *tmp; | 	object *r, *i, *tmp; | ||||||
| 	number_methods *nbr, *nbi; | 	number_methods *nbr, *nbi; | ||||||
| 	Py_complex cr, ci; | 	Py_complex cr, ci; | ||||||
|  | 	int own_r = 0; | ||||||
| 
 | 
 | ||||||
| 	i = NULL; | 	i = NULL; | ||||||
| 	if (!newgetargs(args, "O|O:complex", &r, &i)) | 	if (!newgetargs(args, "O|O:complex", &r, &i)) | ||||||
| 		return NULL; | 		return NULL; | ||||||
| 	if ((nbr = r->ob_type->tp_as_number) == NULL || | 	if ((nbr = r->ob_type->tp_as_number) == NULL || | ||||||
| 	     nbr->nb_float == NULL || (i != NULL && | 	    nbr->nb_float == NULL || | ||||||
| 	   ((nbi = i->ob_type->tp_as_number) == NULL || | 	    (i != NULL && | ||||||
| 	     nbi->nb_float == NULL))) { | 	     ((nbi = i->ob_type->tp_as_number) == NULL || | ||||||
|  | 	      nbi->nb_float == NULL))) { | ||||||
| 		err_setstr(TypeError, | 		err_setstr(TypeError, | ||||||
| 			   "complex() argument can't be converted to complex"); | 			   "complex() argument can't be converted to complex"); | ||||||
| 		return NULL; | 		return NULL; | ||||||
|  | @ -332,12 +337,18 @@ builtin_complex(self, args) | ||||||
| 			DECREF(args); | 			DECREF(args); | ||||||
| 			if (r == NULL) | 			if (r == NULL) | ||||||
| 				return NULL; | 				return NULL; | ||||||
|  | 			own_r = 1; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	if (is_complexobject(r)) | 	if (is_complexobject(r)) { | ||||||
| 		cr = ((complexobject*)r)->cval; | 		cr = ((complexobject*)r)->cval; | ||||||
|  | 		if (own_r) | ||||||
|  | 			DECREF(r); | ||||||
|  | 	} | ||||||
| 	else { | 	else { | ||||||
| 		tmp = (*nbr->nb_float)(r); | 		tmp = (*nbr->nb_float)(r); | ||||||
|  | 		if (own_r) | ||||||
|  | 			DECREF(r); | ||||||
| 		if (tmp == NULL) | 		if (tmp == NULL) | ||||||
| 			return NULL; | 			return NULL; | ||||||
| 		cr.real = getfloatvalue(tmp); | 		cr.real = getfloatvalue(tmp); | ||||||
|  | @ -351,7 +362,7 @@ builtin_complex(self, args) | ||||||
| 	else if (is_complexobject(i)) | 	else if (is_complexobject(i)) | ||||||
| 		ci = ((complexobject*)i)->cval; | 		ci = ((complexobject*)i)->cval; | ||||||
| 	else { | 	else { | ||||||
| 		tmp = (*nbr->nb_float)(i); | 		tmp = (*nbi->nb_float)(i); | ||||||
| 		if (tmp == NULL) | 		if (tmp == NULL) | ||||||
| 			return NULL; | 			return NULL; | ||||||
| 		ci.real = getfloatvalue(tmp); | 		ci.real = getfloatvalue(tmp); | ||||||
|  | @ -533,6 +544,8 @@ builtin_float(self, args) | ||||||
| 
 | 
 | ||||||
| 	if (!newgetargs(args, "O:float", &v)) | 	if (!newgetargs(args, "O:float", &v)) | ||||||
| 		return NULL; | 		return NULL; | ||||||
|  | 	if (is_stringobject(v)) | ||||||
|  | 		return float_from_string(v); | ||||||
| 	if ((nb = v->ob_type->tp_as_number) == NULL || | 	if ((nb = v->ob_type->tp_as_number) == NULL || | ||||||
| 	    nb->nb_float == NULL) { | 	    nb->nb_float == NULL) { | ||||||
| 		err_setstr(TypeError, | 		err_setstr(TypeError, | ||||||
|  | @ -863,6 +876,8 @@ builtin_int(self, args) | ||||||
| 
 | 
 | ||||||
| 	if (!newgetargs(args, "O:int", &v)) | 	if (!newgetargs(args, "O:int", &v)) | ||||||
| 		return NULL; | 		return NULL; | ||||||
|  | 	if (is_stringobject(v)) | ||||||
|  | 		return int_from_string(v); | ||||||
| 	if ((nb = v->ob_type->tp_as_number) == NULL || | 	if ((nb = v->ob_type->tp_as_number) == NULL || | ||||||
| 	    nb->nb_int == NULL) { | 	    nb->nb_int == NULL) { | ||||||
| 		err_setstr(TypeError, | 		err_setstr(TypeError, | ||||||
|  | @ -981,6 +996,8 @@ builtin_long(self, args) | ||||||
| 	 | 	 | ||||||
| 	if (!newgetargs(args, "O:long", &v)) | 	if (!newgetargs(args, "O:long", &v)) | ||||||
| 		return NULL; | 		return NULL; | ||||||
|  | 	if (is_stringobject(v)) | ||||||
|  | 		return long_from_string(v); | ||||||
| 	if ((nb = v->ob_type->tp_as_number) == NULL || | 	if ((nb = v->ob_type->tp_as_number) == NULL || | ||||||
| 	    nb->nb_long == NULL) { | 	    nb->nb_long == NULL) { | ||||||
| 		err_setstr(TypeError, | 		err_setstr(TypeError, | ||||||
|  | @ -1618,8 +1635,8 @@ getbuiltindict() | ||||||
| /* Predefined exceptions */ | /* Predefined exceptions */ | ||||||
| 
 | 
 | ||||||
| object *AccessError; | object *AccessError; | ||||||
|  | object *PyExc_AssertionError; | ||||||
| object *AttributeError; | object *AttributeError; | ||||||
| object *ConflictError; |  | ||||||
| object *EOFError; | object *EOFError; | ||||||
| object *FloatingPointError; | object *FloatingPointError; | ||||||
| object *IOError; | object *IOError; | ||||||
|  | @ -1652,8 +1669,8 @@ static void | ||||||
| initerrors() | initerrors() | ||||||
| { | { | ||||||
| 	AccessError = newstdexception("AccessError"); | 	AccessError = newstdexception("AccessError"); | ||||||
|  | 	PyExc_AssertionError = newstdexception("AssertionError"); | ||||||
| 	AttributeError = newstdexception("AttributeError"); | 	AttributeError = newstdexception("AttributeError"); | ||||||
| 	ConflictError = newstdexception("ConflictError"); |  | ||||||
| 	EOFError = newstdexception("EOFError"); | 	EOFError = newstdexception("EOFError"); | ||||||
| 	FloatingPointError = newstdexception("FloatingPointError"); | 	FloatingPointError = newstdexception("FloatingPointError"); | ||||||
| 	IOError = newstdexception("IOError"); | 	IOError = newstdexception("IOError"); | ||||||
|  | @ -1797,3 +1814,106 @@ filterstring(func, strobj) | ||||||
| 	DECREF(result); | 	DECREF(result); | ||||||
| 	return NULL; | 	return NULL; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | /* Copied with modifications from stropmodule.c: atoi,atof.atol */ | ||||||
|  | 
 | ||||||
|  | static PyObject * | ||||||
|  | int_from_string(v) | ||||||
|  | 	PyObject *v; | ||||||
|  | { | ||||||
|  | 	extern long PyOS_strtol Py_PROTO((const char *, char **, int)); | ||||||
|  | 	char *s, *end; | ||||||
|  | 	long x; | ||||||
|  | 	char buffer[256]; /* For errors */ | ||||||
|  | 
 | ||||||
|  | 	if (!PyArg_Parse(v, "s", &s)) | ||||||
|  | 		return NULL; | ||||||
|  | 	while (*s && isspace(Py_CHARMASK(*s))) | ||||||
|  | 		s++; | ||||||
|  | 	if (s[0] == '\0') { | ||||||
|  | 		PyErr_SetString(PyExc_ValueError, "empty string for int()"); | ||||||
|  | 		return NULL; | ||||||
|  | 	} | ||||||
|  | 	errno = 0; | ||||||
|  | 	x = PyOS_strtol(s, &end, 10); | ||||||
|  | 	while (*end && isspace(Py_CHARMASK(*end))) | ||||||
|  | 		end++; | ||||||
|  | 	if (*end != '\0') { | ||||||
|  | 		sprintf(buffer, "invalid literal for int(): %.200s", s); | ||||||
|  | 		PyErr_SetString(PyExc_ValueError, buffer); | ||||||
|  | 		return NULL; | ||||||
|  | 	} | ||||||
|  | 	else if (errno != 0) { | ||||||
|  | 		sprintf(buffer, "int() literal too large: %.200s", s); | ||||||
|  | 		PyErr_SetString(PyExc_ValueError, buffer); | ||||||
|  | 		return NULL; | ||||||
|  | 	} | ||||||
|  | 	return PyInt_FromLong(x); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static PyObject * | ||||||
|  | long_from_string(v) | ||||||
|  | 	PyObject *v; | ||||||
|  | { | ||||||
|  | 	char *s, *end; | ||||||
|  | 	PyObject *x; | ||||||
|  | 	char buffer[256]; /* For errors */ | ||||||
|  | 
 | ||||||
|  | 	if (!PyArg_Parse(v, "s", &s)) | ||||||
|  | 		return NULL; | ||||||
|  | 
 | ||||||
|  | 	while (*s && isspace(Py_CHARMASK(*s))) | ||||||
|  | 		s++; | ||||||
|  | 	if (s[0] == '\0') { | ||||||
|  | 		PyErr_SetString(PyExc_ValueError, "empty string for long()"); | ||||||
|  | 		return NULL; | ||||||
|  | 	} | ||||||
|  | 	x = PyLong_FromString(s, &end, 10); | ||||||
|  | 	if (x == NULL) | ||||||
|  | 		return NULL; | ||||||
|  | 	while (*end && isspace(Py_CHARMASK(*end))) | ||||||
|  | 		end++; | ||||||
|  | 	if (*end != '\0') { | ||||||
|  | 		sprintf(buffer, "invalid literal for long(): %.200s", s); | ||||||
|  | 		PyErr_SetString(PyExc_ValueError, buffer); | ||||||
|  | 		Py_DECREF(x); | ||||||
|  | 		return NULL; | ||||||
|  | 	} | ||||||
|  | 	return x; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static PyObject * | ||||||
|  | float_from_string(v) | ||||||
|  | 	PyObject *v; | ||||||
|  | { | ||||||
|  | 	extern double strtod Py_PROTO((const char *, char **)); | ||||||
|  | 	char *s, *end; | ||||||
|  | 	double x; | ||||||
|  | 	char buffer[256]; /* For errors */ | ||||||
|  | 
 | ||||||
|  | 	if (!PyArg_Parse(v, "s", &s)) | ||||||
|  | 		return NULL; | ||||||
|  | 	while (*s && isspace(Py_CHARMASK(*s))) | ||||||
|  | 		s++; | ||||||
|  | 	if (s[0] == '\0') { | ||||||
|  | 		PyErr_SetString(PyExc_ValueError, "empty string for float()"); | ||||||
|  | 		return NULL; | ||||||
|  | 	} | ||||||
|  | 	errno = 0; | ||||||
|  | 	PyFPE_START_PROTECT("float_from_string", return 0) | ||||||
|  | 	x = strtod(s, &end); | ||||||
|  | 	PyFPE_END_PROTECT(x) | ||||||
|  | 	while (*end && isspace(Py_CHARMASK(*end))) | ||||||
|  | 		end++; | ||||||
|  | 	if (*end != '\0') { | ||||||
|  | 		sprintf(buffer, "invalid literal for float(): %.200s", s); | ||||||
|  | 		PyErr_SetString(PyExc_ValueError, buffer); | ||||||
|  | 		return NULL; | ||||||
|  | 	} | ||||||
|  | 	else if (errno != 0) { | ||||||
|  | 		sprintf(buffer, "float() literal too large: %.200s", s); | ||||||
|  | 		PyErr_SetString(PyExc_ValueError, buffer); | ||||||
|  | 		return NULL; | ||||||
|  | 	} | ||||||
|  | 	return PyFloat_FromDouble(x); | ||||||
|  | } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Guido van Rossum
						Guido van Rossum