From c1bdf891458d2f37aa90b27f3ea85379cbb0d967 Mon Sep 17 00:00:00 2001 From: Eric Smith Date: Mon, 26 Oct 2009 17:46:17 +0000 Subject: Finished removing _PyOS_double_to_string, as mentioned in issue 7117. --- Include/pystrtod.h | 7 --- Misc/NEWS | 4 ++ Objects/stringobject.c | 20 +++++-- Objects/unicodeobject.c | 25 ++++----- Python/pystrtod.c | 135 ------------------------------------------------ 5 files changed, 32 insertions(+), 159 deletions(-) diff --git a/Include/pystrtod.h b/Include/pystrtod.h index 106448b..97578d8 100644 --- a/Include/pystrtod.h +++ b/Include/pystrtod.h @@ -13,13 +13,6 @@ PyAPI_FUNC(double) PyOS_ascii_atof(const char *str); PyAPI_FUNC(char *) PyOS_ascii_formatd(char *buffer, size_t buf_len, const char *format, double d); -/* Use PyOS_double_to_string instead. It's the same, except it allocates - the appropriately sized buffer and returns it. This function will go - away in Python 2.8 and 3.2. */ -PyAPI_FUNC(void) _PyOS_double_to_string(char *buf, size_t buf_len, double val, - char format_code, int precision, - int flags, int* type); - /* The caller is responsible for calling PyMem_Free to free the buffer that's is returned. */ PyAPI_FUNC(char *) PyOS_double_to_string(double val, diff --git a/Misc/NEWS b/Misc/NEWS index 2810cab..368ed3e 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -12,6 +12,10 @@ What's New in Python 2.7 alpha 1 Core and Builtins ----------------- +- Removed _PyOS_double_to_string. Use PyOS_double_to_string + instead. This is in preparation for (but not strictly related to) + issue #7117, short float repr. + - Issue #1087418: Boost performance of bitwise operations for longs. - Issue #1722344: threading._shutdown() is now called in Py_Finalize(), which diff --git a/Objects/stringobject.c b/Objects/stringobject.c index 70d90d4..b5faf13 100644 --- a/Objects/stringobject.c +++ b/Objects/stringobject.c @@ -4336,7 +4336,10 @@ Py_LOCAL_INLINE(int) formatfloat(char *buf, size_t buflen, int flags, int prec, int type, PyObject *v) { + char *tmp; double x; + Py_ssize_t len; + x = PyFloat_AsDouble(v); if (x == -1.0 && PyErr_Occurred()) { PyErr_Format(PyExc_TypeError, "float argument required, " @@ -4381,9 +4384,20 @@ formatfloat(char *buf, size_t buflen, int flags, "formatted float is too long (precision too large?)"); return -1; } - _PyOS_double_to_string(buf, buflen, x, type, prec, - (flags&F_ALT)?Py_DTSF_ALT:0, NULL); - return (int)strlen(buf); + tmp = PyOS_double_to_string(x, type, prec, + (flags&F_ALT)?Py_DTSF_ALT:0, NULL); + if (!tmp) + return -1; + len = strlen(tmp); + if (len >= buflen) { + PyErr_SetString(PyExc_OverflowError, + "formatted float is too long (precision too large?)"); + PyMem_Free(tmp); + return -1; + } + strcpy(buf, tmp); + PyMem_Free(tmp); + return (int)len; } /* _PyString_FormatLong emulates the format codes d, u, o, x and X, and diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index 6eac358..65c10b1 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -8289,18 +8289,6 @@ strtounicode(Py_UNICODE *buffer, const char *charbuffer) } static int -doubletounicode(Py_UNICODE *buffer, size_t len, int format_code, - int precision, int flags, double x) -{ - Py_ssize_t result; - - _PyOS_double_to_string((char *)buffer, len, x, format_code, precision, - flags, NULL); - result = strtounicode(buffer, (char *)buffer); - return Py_SAFE_DOWNCAST(result, Py_ssize_t, int); -} - -static int longtounicode(Py_UNICODE *buffer, size_t len, const char *format, long x) { Py_ssize_t result; @@ -8323,6 +8311,8 @@ formatfloat(Py_UNICODE *buf, PyObject *v) { double x; + Py_ssize_t result; + char *tmp; x = PyFloat_AsDouble(v); if (x == -1.0 && PyErr_Occurred()) @@ -8365,8 +8355,15 @@ formatfloat(Py_UNICODE *buf, "formatted float is too long (precision too large?)"); return -1; } - return doubletounicode(buf, buflen, type, prec, - (flags&F_ALT)?Py_DTSF_ALT:0, x); + + tmp = PyOS_double_to_string(x, type, prec, + (flags&F_ALT)?Py_DTSF_ALT:0, NULL); + if (!tmp) + return -1; + + result = strtounicode(buf, tmp); + PyMem_Free(tmp); + return Py_SAFE_DOWNCAST(result, Py_ssize_t, int); } static PyObject* diff --git a/Python/pystrtod.c b/Python/pystrtod.c index 2f34b9b..64bf73d 100644 --- a/Python/pystrtod.c +++ b/Python/pystrtod.c @@ -392,25 +392,6 @@ change_decimal_from_locale_to_dot(char* buffer) } -Py_LOCAL_INLINE(void) -ensure_sign(char* buffer, size_t buf_size) -{ - size_t len; - - if (buffer[0] == '-') - /* Already have a sign. */ - return; - - /* Include the trailing 0 byte. */ - len = strlen(buffer)+1; - if (len >= buf_size+1) - /* No room for the sign, don't do anything. */ - return; - - memmove(buffer+1, buffer, len); - buffer[0] = '+'; -} - /* From the C99 standard, section 7.19.6: The exponent always contains at least two digits, and only as many more digits as necessary to represent the exponent. @@ -739,122 +720,6 @@ PyOS_ascii_formatd(char *buffer, return _PyOS_ascii_formatd(buffer, buf_size, format, d, -1); } -PyAPI_FUNC(void) -_PyOS_double_to_string(char *buf, size_t buf_len, double val, - char format_code, int precision, - int flags, int *ptype) -{ - char format[32]; - int t; - int upper = 0; - - if (buf_len < 1) { - assert(0); - /* There's no way to signal this error. Just return. */ - return; - } - buf[0] = 0; - - /* Validate format_code, and map upper and lower case */ - switch (format_code) { - case 'e': /* exponent */ - case 'f': /* fixed */ - case 'g': /* general */ - break; - case 'E': - upper = 1; - format_code = 'e'; - break; - case 'F': - upper = 1; - format_code = 'f'; - break; - case 'G': - upper = 1; - format_code = 'g'; - break; - case 'r': /* repr format */ - /* Supplied precision is unused, must be 0. */ - if (precision != 0) - return; - /* The repr() precision (17 significant decimal digits) is the - minimal number that is guaranteed to have enough precision - so that if the number is read back in the exact same binary - value is recreated. This is true for IEEE floating point - by design, and also happens to work for all other modern - hardware. */ - precision = 17; - format_code = 'g'; - break; - default: - assert(0); - return; - } - - /* Check for buf too small to fit "-inf". Other buffer too small - conditions are dealt with when converting or formatting finite - numbers. */ - if (buf_len < 5) { - assert(0); - return; - } - - /* Handle nan and inf. */ - if (Py_IS_NAN(val)) { - strcpy(buf, "nan"); - t = Py_DTST_NAN; - } else if (Py_IS_INFINITY(val)) { - if (copysign(1., val) == 1.) - strcpy(buf, "inf"); - else - strcpy(buf, "-inf"); - t = Py_DTST_INFINITE; - } else { - t = Py_DTST_FINITE; - - /* Build the format string. */ - PyOS_snprintf(format, sizeof(format), "%%%s.%i%c", - (flags & Py_DTSF_ALT ? "#" : ""), precision, - format_code); - - /* Have PyOS_snprintf do the hard work. */ - PyOS_snprintf(buf, buf_len, format, val); - - /* Do various fixups on the return string */ - - /* Get the current locale, and find the decimal point string. - Convert that string back to a dot. */ - change_decimal_from_locale_to_dot(buf); - - /* If an exponent exists, ensure that the exponent is at least - MIN_EXPONENT_DIGITS digits, providing the buffer is large - enough for the extra zeros. Also, if there are more than - MIN_EXPONENT_DIGITS, remove as many zeros as possible until - we get back to MIN_EXPONENT_DIGITS */ - ensure_minimum_exponent_length(buf, buf_len); - - /* Possibly make sure we have at least one character after the - decimal point (and make sure we have a decimal point). */ - if (flags & Py_DTSF_ADD_DOT_0) - buf = ensure_decimal_point(buf, buf_len, precision); - } - - /* Add the sign if asked and the result isn't negative. */ - if (flags & Py_DTSF_SIGN && buf[0] != '-') - ensure_sign(buf, buf_len); - - if (upper) { - /* Convert to upper case. */ - char *p; - for (p = buf; *p; p++) - *p = Py_TOUPPER(*p); - } - - if (ptype) - *ptype = t; -} - - #ifdef PY_NO_SHORT_FLOAT_REPR /* The fallback code to use if _Py_dg_dtoa is not available. */ -- cgit v0.12