mirror of
https://github.com/python/cpython.git
synced 2025-07-24 03:35:53 +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 @@ Fail_1:
|
||||||
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