diff options
Diffstat (limited to 'Objects/stringlib/formatter.h')
| -rw-r--r-- | Objects/stringlib/formatter.h | 110 |
1 files changed, 46 insertions, 64 deletions
diff --git a/Objects/stringlib/formatter.h b/Objects/stringlib/formatter.h index 4770863..be0d897 100644 --- a/Objects/stringlib/formatter.h +++ b/Objects/stringlib/formatter.h @@ -32,7 +32,7 @@ unknown_presentation_type(STRINGLIB_CHAR presentation_type, PyErr_Format(PyExc_ValueError, "Unknown format code '%c' " "for object of type '%.200s'", - presentation_type, + (char)presentation_type, type_name); #if STRINGLIB_IS_UNICODE else @@ -44,6 +44,24 @@ unknown_presentation_type(STRINGLIB_CHAR presentation_type, #endif } +static void +invalid_comma_type(STRINGLIB_CHAR presentation_type) +{ +#if STRINGLIB_IS_UNICODE + /* See comment in unknown_presentation_type */ + if (presentation_type > 32 && presentation_type < 128) +#endif + PyErr_Format(PyExc_ValueError, + "Cannot specify ',' with '%c'.", + (char)presentation_type); +#if STRINGLIB_IS_UNICODE + else + PyErr_Format(PyExc_ValueError, + "Cannot specify ',' with '\\x%x'.", + (unsigned int)presentation_type); +#endif +} + /* get_integer consumes 0 or more decimal digit characters from an input string, updates *result with the corresponding positive @@ -55,7 +73,7 @@ static int get_integer(STRINGLIB_CHAR **ptr, STRINGLIB_CHAR *end, Py_ssize_t *result) { - Py_ssize_t accumulator, digitval, oldaccumulator; + Py_ssize_t accumulator, digitval; int numdigits; accumulator = numdigits = 0; for (;;(*ptr)++, numdigits++) { @@ -65,19 +83,17 @@ get_integer(STRINGLIB_CHAR **ptr, STRINGLIB_CHAR *end, if (digitval < 0) break; /* - This trick was copied from old Unicode format code. It's cute, - but would really suck on an old machine with a slow divide - implementation. Fortunately, in the normal case we do not - expect too many digits. + Detect possible overflow before it happens: + + accumulator * 10 + digitval > PY_SSIZE_T_MAX if and only if + accumulator > (PY_SSIZE_T_MAX - digitval) / 10. */ - oldaccumulator = accumulator; - accumulator *= 10; - if ((accumulator+10)/10 != oldaccumulator+1) { + if (accumulator > (PY_SSIZE_T_MAX - digitval) / 10) { PyErr_Format(PyExc_ValueError, "Too many decimal digits in format string"); return -1; } - accumulator += digitval; + accumulator = accumulator * 10 + digitval; } *result = accumulator; return numdigits; @@ -277,8 +293,7 @@ parse_internal_render_format_spec(STRINGLIB_CHAR *format_spec, /* These are allowed. See PEP 378.*/ break; default: - PyErr_Format(PyExc_ValueError, - "Cannot specify ',' with '%c'.", format->type); + invalid_comma_type(format->type); return 0; } } @@ -399,7 +414,7 @@ parse_number(STRINGLIB_CHAR *ptr, Py_ssize_t len, STRINGLIB_CHAR *end = ptr + len; STRINGLIB_CHAR *remainder; - while (ptr<end && isdigit(*ptr)) + while (ptr<end && Py_ISDIGIT(*ptr)) ++ptr; remainder = ptr; @@ -632,8 +647,8 @@ get_locale_info(int type, LocaleInfo *locale_info) case LT_DEFAULT_LOCALE: locale_info->decimal_point = "."; locale_info->thousands_sep = ","; - locale_info->grouping = "\3"; /* Group every 3 characters, - trailing 0 means repeat + locale_info->grouping = "\3"; /* Group every 3 characters. The + (implicit) trailing 0 means repeat infinitely. */ break; case LT_NO_LOCALE: @@ -759,14 +774,6 @@ format_int_or_long_internal(PyObject *value, const InternalFormatSpec *format, goto done; } - /* Error to specify a comma. */ - if (format->thousands_separators) { - PyErr_SetString(PyExc_ValueError, - "Thousands separators not allowed with integer" - " format specifier 'c'"); - goto done; - } - /* taken from unicodeobject.c formatchar() */ /* Integer input truncated to a character */ /* XXX: won't work for int */ @@ -932,20 +939,16 @@ format_float_internal(PyObject *value, from a hard-code pseudo-locale */ LocaleInfo locale; - /* Alternate is not allowed on floats. */ - if (format->alternate) { - PyErr_SetString(PyExc_ValueError, - "Alternate form (#) not allowed in float format " - "specifier"); - goto done; - } + if (format->alternate) + flags |= Py_DTSF_ALT; if (type == '\0') { - /* Omitted type specifier. This is like 'g' but with at least one - digit after the decimal point, and different default precision.*/ - type = 'g'; - default_precision = PyFloat_STR_PRECISION; + /* Omitted type specifier. Behaves in the same way as repr(x) + and str(x) if no precision is given, else like 'g', but with + at least one digit after the decimal point. */ flags |= Py_DTSF_ADD_DOT_0; + type = 'r'; + default_precision = 0; } if (type == 'n') @@ -953,13 +956,6 @@ format_float_internal(PyObject *value, format the result. We take care of that later. */ type = 'g'; -#if PY_VERSION_HEX < 0x0301000 - /* 'F' is the same as 'f', per the PEP */ - /* This is no longer the case in 3.x */ - if (type == 'F') - type = 'f'; -#endif - val = PyFloat_AsDouble(value); if (val == -1.0 && PyErr_Occurred()) goto done; @@ -972,12 +968,8 @@ format_float_internal(PyObject *value, if (precision < 0) precision = default_precision; - -#if PY_VERSION_HEX < 0x03010000 - /* 3.1 no longer converts large 'f' to 'g'. */ - if ((type == 'f' || type == 'F') && fabs(val) >= 1e50) + else if (type == 'r') type = 'g'; -#endif /* Cast "type", because if we're in unicode we need to pass a 8-bit char. This is safe, because we've restricted what "type" @@ -1105,15 +1097,7 @@ format_complex_internal(PyObject *value, from a hard-code pseudo-locale */ LocaleInfo locale; - /* Alternate is not allowed on complex. */ - if (format->alternate) { - PyErr_SetString(PyExc_ValueError, - "Alternate form (#) not allowed in complex format " - "specifier"); - goto done; - } - - /* Neither is zero pading. */ + /* Zero padding is not allowed. */ if (format->fill_char == '0') { PyErr_SetString(PyExc_ValueError, "Zero padding is not allowed in complex format " @@ -1136,10 +1120,13 @@ format_complex_internal(PyObject *value, if (im == -1.0 && PyErr_Occurred()) goto done; + if (format->alternate) + flags |= Py_DTSF_ALT; + if (type == '\0') { /* Omitted type specifier. Should be like str(self). */ - type = 'g'; - default_precision = PyFloat_STR_PRECISION; + type = 'r'; + default_precision = 0; if (re == 0.0 && copysign(1.0, re) == 1.0) skip_re = 1; else @@ -1151,15 +1138,10 @@ format_complex_internal(PyObject *value, format the result. We take care of that later. */ type = 'g'; -#if PY_VERSION_HEX < 0x03010000 - /* This is no longer the case in 3.x */ - /* 'F' is the same as 'f', per the PEP */ - if (type == 'F') - type = 'f'; -#endif - if (precision < 0) precision = default_precision; + else if (type == 'r') + type = 'g'; /* Cast "type", because if we're in unicode we need to pass a 8-bit char. This is safe, because we've restricted what "type" |
