diff --git a/Include/floatobject.h b/Include/floatobject.h index f695de8578c..c3c18afcd73 100644 --- a/Include/floatobject.h +++ b/Include/floatobject.h @@ -34,19 +34,6 @@ PyAPI_FUNC(PyObject *) PyFloat_FromDouble(double); PyAPI_FUNC(double) PyFloat_AsDouble(PyObject *); #define PyFloat_AS_DOUBLE(op) (((PyFloatObject *)(op))->ob_fval) -/* Write repr(v) into the char buffer argument, followed by null byte. The - buffer must be "big enough"; >= 100 is very safe. - PyFloat_AsReprString(buf, x) strives to print enough digits so that - PyFloat_FromString(buf) then reproduces x exactly. */ -PyAPI_FUNC(void) PyFloat_AsReprString(char*, PyFloatObject *v); - -/* Write str(v) into the char buffer argument, followed by null byte. The - buffer must be "big enough"; >= 100 is very safe. Note that it's - unusual to be able to get back the float you started with from - PyFloat_AsString's result -- use PyFloat_AsReprString() if you want to - preserve precision across conversions. */ -PyAPI_FUNC(void) PyFloat_AsString(char*, PyFloatObject *v); - /* _PyFloat_{Pack,Unpack}{4,8} * * The struct and pickle (at least) modules need an efficient platform- @@ -82,6 +69,11 @@ PyAPI_FUNC(void) PyFloat_AsString(char*, PyFloatObject *v); PyAPI_FUNC(int) _PyFloat_Pack4(double x, unsigned char *p, int le); PyAPI_FUNC(int) _PyFloat_Pack8(double x, unsigned char *p, int le); +/* Needed for the old way for marshal to store a floating point number. + Returns the string length copied into p, -1 on error. + */ +PyAPI_FUNC(int) _PyFloat_Repr(double x, char *p, size_t len); + /* The unpack routines read 4 or 8 bytes, starting at p. le is a bool * argument, true if the string is in little-endian format (exponent * last, at p+3 or p+7), false if big-endian (exponent first, at p). @@ -93,7 +85,6 @@ PyAPI_FUNC(int) _PyFloat_Pack8(double x, unsigned char *p, int le); PyAPI_FUNC(double) _PyFloat_Unpack4(const unsigned char *p, int le); PyAPI_FUNC(double) _PyFloat_Unpack8(const unsigned char *p, int le); - #ifdef __cplusplus } #endif diff --git a/Objects/floatobject.c b/Objects/floatobject.c index aab76122749..9c6dadf7406 100644 --- a/Objects/floatobject.c +++ b/Objects/floatobject.c @@ -220,19 +220,18 @@ PyFloat_AsDouble(PyObject *op) /* Methods */ static void -format_float(char *buf, size_t buflen, PyFloatObject *v, int precision) +format_double(char *buf, size_t buflen, double ob_fval, int precision) { register char *cp; char format[32]; - /* Subroutine for float_repr and float_print. + /* Subroutine for float_repr, float_str, float_print and others. We want float numbers to be recognizable as such, i.e., they should contain a decimal point or an exponent. However, %g may print the number as an integer; in such cases, we append ".0" to the string. */ - assert(PyFloat_Check(v)); PyOS_snprintf(format, 32, "%%.%ig", precision); - PyOS_ascii_formatd(buf, buflen, format, v->ob_fval); + PyOS_ascii_formatd(buf, buflen, format, ob_fval); cp = buf; if (*cp == '-') cp++; @@ -249,14 +248,11 @@ format_float(char *buf, size_t buflen, PyFloatObject *v, int precision) } } -/* XXX PyFloat_AsStringEx should not be a public API function (for one - XXX thing, its signature passes a buffer without a length; for another, - XXX it isn't useful outside this file). -*/ -void -PyFloat_AsStringEx(char *buf, PyFloatObject *v, int precision) +static void +format_float(char *buf, size_t buflen, PyFloatObject *v, int precision) { - format_float(buf, 100, v, precision); + assert(PyFloat_Check(v)); + format_double(buf, buflen, PyFloat_AS_DOUBLE(v), precision); } /* Macro and helper that convert PyObject obj to a C double and store @@ -312,21 +308,6 @@ convert_to_double(PyObject **v, double *dbl) #define PREC_REPR 17 #define PREC_STR 12 -/* XXX PyFloat_AsString and PyFloat_AsReprString should be deprecated: - XXX they pass a char buffer without passing a length. -*/ -void -PyFloat_AsString(char *buf, PyFloatObject *v) -{ - format_float(buf, 100, v, PREC_STR); -} - -void -PyFloat_AsReprString(char *buf, PyFloatObject *v) -{ - format_float(buf, 100, v, PREC_REPR); -} - /* ARGSUSED */ static int float_print(PyFloatObject *v, FILE *fp, int flags) @@ -1275,7 +1256,7 @@ PyFloat_Fini(void) if (PyFloat_CheckExact(p) && p->ob_refcnt != 0) { char buf[100]; - PyFloat_AsString(buf, p); + format_float(buf, sizeof(buf), p, PREC_STR); /* XXX(twouters) cast refcount to long until %zd is universally available @@ -1527,6 +1508,14 @@ _PyFloat_Pack8(double x, unsigned char *p, int le) } } +/* Should only be used by marshal. */ +int +_PyFloat_Repr(double x, char *p, size_t len) +{ + format_double(p, len, x, PREC_REPR); + return (int)strlen(p); +} + double _PyFloat_Unpack4(const unsigned char *p, int le) { diff --git a/Python/marshal.c b/Python/marshal.c index 4e02ac6548d..1819eacbac5 100644 --- a/Python/marshal.c +++ b/Python/marshal.c @@ -182,8 +182,8 @@ w_object(PyObject *v, WFILE *p) } else { char buf[256]; /* Plenty to format any double */ - PyFloat_AsReprString(buf, (PyFloatObject *)v); - n = strlen(buf); + n = _PyFloat_Repr(PyFloat_AS_DOUBLE(v), + buf, sizeof(buf)); w_byte(TYPE_FLOAT, p); w_byte((int)n, p); w_string(buf, (int)n, p); @@ -209,28 +209,14 @@ w_object(PyObject *v, WFILE *p) } else { char buf[256]; /* Plenty to format any double */ - PyFloatObject *temp; w_byte(TYPE_COMPLEX, p); - temp = (PyFloatObject*)PyFloat_FromDouble( - PyComplex_RealAsDouble(v)); - if (!temp) { - p->error = 1; - return; - } - PyFloat_AsReprString(buf, temp); - Py_DECREF(temp); + n = _PyFloat_Repr(PyComplex_RealAsDouble(v), + buf, sizeof(buf)); n = strlen(buf); w_byte((int)n, p); w_string(buf, (int)n, p); - temp = (PyFloatObject*)PyFloat_FromDouble( - PyComplex_ImagAsDouble(v)); - if (!temp) { - p->error = 1; - return; - } - PyFloat_AsReprString(buf, temp); - Py_DECREF(temp); - n = strlen(buf); + n = _PyFloat_Repr(PyComplex_ImagAsDouble(v), + buf, sizeof(buf)); w_byte((int)n, p); w_string(buf, (int)n, p); }