Commit 929e811e authored by Barry Warsaw's avatar Barry Warsaw

Mainlining the string_methods branch. See branch revision log

messages for specific changes.
parent 20813406
......@@ -50,6 +50,7 @@ extern DL_IMPORT(PyTypeObject) PyFloat_Type;
#define PyFloat_Check(op) ((op)->ob_type == &PyFloat_Type)
extern DL_IMPORT(PyObject *) PyFloat_FromString Py_PROTO((PyObject*, char**));
extern DL_IMPORT(PyObject *) PyFloat_FromDouble Py_PROTO((double));
extern DL_IMPORT(double) PyFloat_AsDouble Py_PROTO((PyObject *));
......
......@@ -61,6 +61,7 @@ extern DL_IMPORT(PyTypeObject) PyInt_Type;
#define PyInt_Check(op) ((op)->ob_type == &PyInt_Type)
extern DL_IMPORT(PyObject *) PyInt_FromString Py_PROTO((char*, char**, int));
extern DL_IMPORT(PyObject *) PyInt_FromLong Py_PROTO((long));
extern DL_IMPORT(long) PyInt_AsLong Py_PROTO((PyObject *));
extern DL_IMPORT(long) PyInt_GetMax Py_PROTO((void));
......
This diff is collapsed.
This diff is collapsed.
......@@ -53,123 +53,6 @@ null_error()
return NULL;
}
/* Copied with modifications from stropmodule.c: atoi, atof, atol */
static PyObject *
int_from_string(v)
PyObject *v;
{
char *s, *end;
long x;
char buffer[256]; /* For errors */
s = PyString_AS_STRING(v);
while (*s && isspace(Py_CHARMASK(*s)))
s++;
errno = 0;
x = PyOS_strtol(s, &end, 10);
if (end == s || !isdigit(end[-1]))
goto bad;
while (*end && isspace(Py_CHARMASK(*end)))
end++;
if (*end != '\0') {
bad:
sprintf(buffer, "invalid literal for int(): %.200s", s);
PyErr_SetString(PyExc_ValueError, buffer);
return NULL;
}
else if (end != PyString_AS_STRING(v) + PyString_GET_SIZE(v)) {
PyErr_SetString(PyExc_ValueError,
"null byte in argument for int()");
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 */
s = PyString_AS_STRING(v);
while (*s && isspace(Py_CHARMASK(*s)))
s++;
x = PyLong_FromString(s, &end, 10);
if (x == NULL) {
if (PyErr_ExceptionMatches(PyExc_ValueError))
goto bad;
return NULL;
}
while (*end && isspace(Py_CHARMASK(*end)))
end++;
if (*end != '\0') {
bad:
sprintf(buffer, "invalid literal for long(): %.200s", s);
PyErr_SetString(PyExc_ValueError, buffer);
Py_XDECREF(x);
return NULL;
}
else if (end != PyString_AS_STRING(v) + PyString_GET_SIZE(v)) {
PyErr_SetString(PyExc_ValueError,
"null byte in argument for long()");
return NULL;
}
return x;
}
static PyObject *
float_from_string(v)
PyObject *v;
{
extern double strtod Py_PROTO((const char *, char **));
char *s, *last, *end;
double x;
char buffer[256]; /* For errors */
s = PyString_AS_STRING(v);
last = s + PyString_GET_SIZE(v);
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)
/* Believe it or not, Solaris 2.6 can move end *beyond* the null
byte at the end of the string, when the input is inf(inity) */
if (end > last)
end = last;
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 (end != PyString_AS_STRING(v) + PyString_GET_SIZE(v)) {
PyErr_SetString(PyExc_ValueError,
"null byte in argument for float()");
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);
}
/* Operations on any object */
int
......@@ -713,7 +596,7 @@ PyNumber_Int(o)
if (o == NULL)
return null_error();
if (PyString_Check(o))
return int_from_string(o);
return PyInt_FromString(PyString_AS_STRING(o), NULL, 10);
m = o->ob_type->tp_as_number;
if (m && m->nb_int)
return m->nb_int(o);
......@@ -721,6 +604,61 @@ PyNumber_Int(o)
return type_error("object can't be converted to int");
}
/* There are two C API functions for converting a string to a long,
* PyNumber_Long() and PyLong_FromString(). Both are used in builtin_long,
* reachable from Python with the built-in function long().
*
* The difference is this: PyNumber_Long will raise an exception when the
* string cannot be converted to a long. The most common situation is
* where a float string is passed in; this raises a ValueError.
* PyLong_FromString does not raise an exception; it silently truncates the
* float to an integer.
*
* You can see the different behavior from Python with the following:
*
* long('9.5')
* => ValueError: invalid literal for long(): 9.5
*
* long('9.5', 10)
* => 9L
*
* The first example ends up calling PyNumber_Long(), while the second one
* calls PyLong_FromString().
*/
static PyObject *
long_from_string(v)
PyObject *v;
{
char *s, *end;
PyObject *x;
char buffer[256]; /* For errors */
s = PyString_AS_STRING(v);
while (*s && isspace(Py_CHARMASK(*s)))
s++;
x = PyLong_FromString(s, &end, 10);
if (x == NULL) {
if (PyErr_ExceptionMatches(PyExc_ValueError))
goto bad;
return NULL;
}
while (*end && isspace(Py_CHARMASK(*end)))
end++;
if (*end != '\0') {
bad:
sprintf(buffer, "invalid literal for long(): %.200s", s);
PyErr_SetString(PyExc_ValueError, buffer);
Py_XDECREF(x);
return NULL;
}
else if (end != PyString_AS_STRING(v) + PyString_GET_SIZE(v)) {
PyErr_SetString(PyExc_ValueError,
"null byte in argument for long()");
return NULL;
}
return x;
}
PyObject *
PyNumber_Long(o)
PyObject *o;
......@@ -730,6 +668,10 @@ PyNumber_Long(o)
if (o == NULL)
return null_error();
if (PyString_Check(o))
/* need to do extra error checking that PyLong_FromString()
* doesn't do. In particular long('9.5') must raise an
* exception, not truncate the float.
*/
return long_from_string(o);
m = o->ob_type->tp_as_number;
if (m && m->nb_long)
......@@ -747,7 +689,7 @@ PyNumber_Float(o)
if (o == NULL)
return null_error();
if (PyString_Check(o))
return float_from_string(o);
return PyFloat_FromString(o, NULL);
m = o->ob_type->tp_as_number;
if (m && m->nb_float)
return m->nb_float(o);
......
......@@ -149,6 +149,57 @@ PyFloat_FromDouble(fval)
return (PyObject *) op;
}
PyObject *
PyFloat_FromString(v, pend)
PyObject *v;
char **pend;
{
extern double strtod Py_PROTO((const char *, char **));
char *s, *last, *end;
double x;
char buffer[256]; /* For errors */
if (!PyString_Check(v))
return NULL;
s = PyString_AS_STRING(v);
last = s + PyString_GET_SIZE(v);
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("PyFloat_FromString", return 0)
x = strtod(s, &end);
PyFPE_END_PROTECT(x)
/* Believe it or not, Solaris 2.6 can move end *beyond* the null
byte at the end of the string, when the input is inf(inity) */
if (end > last)
end = last;
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 (end != PyString_AS_STRING(v) + PyString_GET_SIZE(v)) {
PyErr_SetString(PyExc_ValueError,
"null byte in argument for float()");
return NULL;
}
else if (errno != 0) {
sprintf(buffer, "float() literal too large: %.200s", s);
PyErr_SetString(PyExc_ValueError, buffer);
return NULL;
}
if (pend)
*pend = end;
return PyFloat_FromDouble(x);
}
static void
float_dealloc(op)
PyFloatObject *op;
......
......@@ -32,6 +32,7 @@ PERFORMANCE OF THIS SOFTWARE.
/* Integer object implementation */
#include "Python.h"
#include <ctype.h>
#ifdef HAVE_LIMITS_H
#include <limits.h>
......@@ -218,6 +219,48 @@ PyInt_AsLong(op)
return val;
}
PyObject *
PyInt_FromString(s, pend, base)
char *s;
char **pend;
int base;
{
char *end;
long x;
char buffer[256]; /* For errors */
if ((base != 0 && base < 2) || base > 36) {
PyErr_SetString(PyExc_ValueError, "invalid base for int()");
return NULL;
}
while (*s && isspace(Py_CHARMASK(*s)))
s++;
errno = 0;
if (base == 0 && s[0] == '0')
x = (long) PyOS_strtoul(s, &end, base);
else
x = PyOS_strtol(s, &end, base);
if (end == s || !isalnum(end[-1]))
goto bad;
while (*end && isspace(Py_CHARMASK(*end)))
end++;
if (*end != '\0') {
bad:
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;
}
if (pend)
*pend = end;
return PyInt_FromLong(x);
}
/* Methods */
/* ARGSUSED */
......
This diff is collapsed.
......@@ -811,24 +811,6 @@ The globals and locals are dictionaries, defaulting to the current\n\
globals and locals. If only globals is given, locals defaults to it.";
static PyObject *
builtin_float(self, args)
PyObject *self;
PyObject *args;
{
PyObject *v;
if (!PyArg_ParseTuple(args, "O:float", &v))
return NULL;
return PyNumber_Float(v);
}
static char float_doc[] =
"float(x) -> floating point number\n\
\n\
Convert a string or number to a floating point number, if possible.";
static PyObject *
builtin_getattr(self, args)
PyObject *self;
......@@ -1251,17 +1233,79 @@ builtin_int(self, args)
PyObject *args;
{
PyObject *v;
int base = -909; /* unlikely! */
if (!PyArg_ParseTuple(args, "O:int", &v))
if (!PyArg_ParseTuple(args, "O|i:int", &v, &base))
return NULL;
return PyNumber_Int(v);
if (base == -909)
return PyNumber_Int(v);
else if (!PyString_Check(v)) {
PyErr_SetString(PyExc_TypeError,
"can't convert non-string with explicit base");
return NULL;
}
return PyInt_FromString(PyString_AS_STRING(v), NULL, base);
}
static char int_doc[] =
"int(x) -> integer\n\
"int(x[, base]) -> integer\n\
\n\
Convert a string or number to an integer, if possible. A floating point\n\
argument will be truncated towards zero (this does not include a string\n\
representation of a floating point number!) When converting a string, use\n\
the optional base. It is an error to supply a base when converting a\n\
non-string.";
static PyObject *
builtin_long(self, args)
PyObject *self;
PyObject *args;
{
PyObject *v;
int base = -909; /* unlikely! */
if (!PyArg_ParseTuple(args, "O|i:long", &v, &base))
return NULL;
if (base == -909)
return PyNumber_Long(v);
else if (!PyString_Check(v)) {
PyErr_SetString(PyExc_TypeError,
"can't convert non-string with explicit base");
return NULL;
}
return PyLong_FromString(PyString_AS_STRING(v), NULL, base);
}
static char long_doc[] =
"long(x) -> long integer\n\
long(x, base) -> long integer\n\
\n\
Convert a string or number to a long integer, if possible. A floating\n\
point argument will be truncated towards zero (this does not include a\n\
string representation of a floating point number!) When converting a\n\
string, use the given base. It is an error to supply a base when\n\
converting a non-string.";
static PyObject *
builtin_float(self, args)
PyObject *self;
PyObject *args;
{
PyObject *v;
if (!PyArg_ParseTuple(args, "O:float", &v))
return NULL;
if (PyString_Check(v))
return PyFloat_FromString(v, NULL);
return PyNumber_Float(v);
}
static char float_doc[] =
"float(x) -> floating point number\n\
\n\
Convert a string or number to an integer, if possible.\n\
A floating point argument will be truncated towards zero.";
Convert a string or number to a floating point number, if possible.";
static PyObject *
......@@ -1351,25 +1395,6 @@ static char locals_doc[] =
Return the dictionary containing the current scope's local variables.";
static PyObject *
builtin_long(self, args)
PyObject *self;
PyObject *args;
{
PyObject *v;
if (!PyArg_ParseTuple(args, "O:long", &v))
return NULL;
return PyNumber_Long(v);
}
static char long_doc[] =
"long(x) -> long integer\n\
\n\
Convert a string or number to a long integer, if possible.\n\
A floating point argument will be truncated towards zero.";
static PyObject *
min_max(args, sign)
PyObject *args;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment