mirror of
https://github.com/python/cpython.git
synced 2025-07-19 09:15:34 +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 */
|
||||
static object *filterstring 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 *
|
||||
builtin___import__(self, args)
|
||||
|
@ -300,14 +303,16 @@ builtin_complex(self, args)
|
|||
object *r, *i, *tmp;
|
||||
number_methods *nbr, *nbi;
|
||||
Py_complex cr, ci;
|
||||
int own_r = 0;
|
||||
|
||||
i = NULL;
|
||||
if (!newgetargs(args, "O|O:complex", &r, &i))
|
||||
return NULL;
|
||||
if ((nbr = r->ob_type->tp_as_number) == NULL ||
|
||||
nbr->nb_float == NULL || (i != NULL &&
|
||||
((nbi = i->ob_type->tp_as_number) == NULL ||
|
||||
nbi->nb_float == NULL))) {
|
||||
nbr->nb_float == NULL ||
|
||||
(i != NULL &&
|
||||
((nbi = i->ob_type->tp_as_number) == NULL ||
|
||||
nbi->nb_float == NULL))) {
|
||||
err_setstr(TypeError,
|
||||
"complex() argument can't be converted to complex");
|
||||
return NULL;
|
||||
|
@ -332,12 +337,18 @@ builtin_complex(self, args)
|
|||
DECREF(args);
|
||||
if (r == NULL)
|
||||
return NULL;
|
||||
own_r = 1;
|
||||
}
|
||||
}
|
||||
if (is_complexobject(r))
|
||||
if (is_complexobject(r)) {
|
||||
cr = ((complexobject*)r)->cval;
|
||||
if (own_r)
|
||||
DECREF(r);
|
||||
}
|
||||
else {
|
||||
tmp = (*nbr->nb_float)(r);
|
||||
if (own_r)
|
||||
DECREF(r);
|
||||
if (tmp == NULL)
|
||||
return NULL;
|
||||
cr.real = getfloatvalue(tmp);
|
||||
|
@ -351,7 +362,7 @@ builtin_complex(self, args)
|
|||
else if (is_complexobject(i))
|
||||
ci = ((complexobject*)i)->cval;
|
||||
else {
|
||||
tmp = (*nbr->nb_float)(i);
|
||||
tmp = (*nbi->nb_float)(i);
|
||||
if (tmp == NULL)
|
||||
return NULL;
|
||||
ci.real = getfloatvalue(tmp);
|
||||
|
@ -533,6 +544,8 @@ builtin_float(self, args)
|
|||
|
||||
if (!newgetargs(args, "O:float", &v))
|
||||
return NULL;
|
||||
if (is_stringobject(v))
|
||||
return float_from_string(v);
|
||||
if ((nb = v->ob_type->tp_as_number) == NULL ||
|
||||
nb->nb_float == NULL) {
|
||||
err_setstr(TypeError,
|
||||
|
@ -863,6 +876,8 @@ builtin_int(self, args)
|
|||
|
||||
if (!newgetargs(args, "O:int", &v))
|
||||
return NULL;
|
||||
if (is_stringobject(v))
|
||||
return int_from_string(v);
|
||||
if ((nb = v->ob_type->tp_as_number) == NULL ||
|
||||
nb->nb_int == NULL) {
|
||||
err_setstr(TypeError,
|
||||
|
@ -981,6 +996,8 @@ builtin_long(self, args)
|
|||
|
||||
if (!newgetargs(args, "O:long", &v))
|
||||
return NULL;
|
||||
if (is_stringobject(v))
|
||||
return long_from_string(v);
|
||||
if ((nb = v->ob_type->tp_as_number) == NULL ||
|
||||
nb->nb_long == NULL) {
|
||||
err_setstr(TypeError,
|
||||
|
@ -1618,8 +1635,8 @@ getbuiltindict()
|
|||
/* Predefined exceptions */
|
||||
|
||||
object *AccessError;
|
||||
object *PyExc_AssertionError;
|
||||
object *AttributeError;
|
||||
object *ConflictError;
|
||||
object *EOFError;
|
||||
object *FloatingPointError;
|
||||
object *IOError;
|
||||
|
@ -1652,8 +1669,8 @@ static void
|
|||
initerrors()
|
||||
{
|
||||
AccessError = newstdexception("AccessError");
|
||||
PyExc_AssertionError = newstdexception("AssertionError");
|
||||
AttributeError = newstdexception("AttributeError");
|
||||
ConflictError = newstdexception("ConflictError");
|
||||
EOFError = newstdexception("EOFError");
|
||||
FloatingPointError = newstdexception("FloatingPointError");
|
||||
IOError = newstdexception("IOError");
|
||||
|
@ -1797,3 +1814,106 @@ Fail_1:
|
|||
DECREF(result);
|
||||
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