Changeset 388 for python/vendor/current/Python/pystrtod.c
- Timestamp:
- Mar 19, 2014, 11:11:30 AM (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
python/vendor/current/Python/pystrtod.c
r2 r388 4 4 #include <locale.h> 5 5 6 /* ascii character tests (as opposed to locale tests) */ 7 #define ISSPACE(c) ((c) == ' ' || (c) == '\f' || (c) == '\n' || \ 8 (c) == '\r' || (c) == '\t' || (c) == '\v') 9 #define ISDIGIT(c) ((c) >= '0' && (c) <= '9') 10 6 /* Case-insensitive string match used for nan and inf detection; t should be 7 lower-case. Returns 1 for a successful match, 0 otherwise. */ 8 9 static int 10 case_insensitive_match(const char *s, const char *t) 11 { 12 while(*t && Py_TOLOWER(*s) == *t) { 13 s++; 14 t++; 15 } 16 return *t ? 0 : 1; 17 } 18 19 /* _Py_parse_inf_or_nan: Attempt to parse a string of the form "nan", "inf" or 20 "infinity", with an optional leading sign of "+" or "-". On success, 21 return the NaN or Infinity as a double and set *endptr to point just beyond 22 the successfully parsed portion of the string. On failure, return -1.0 and 23 set *endptr to point to the start of the string. */ 24 25 double 26 _Py_parse_inf_or_nan(const char *p, char **endptr) 27 { 28 double retval; 29 const char *s; 30 int negate = 0; 31 32 s = p; 33 if (*s == '-') { 34 negate = 1; 35 s++; 36 } 37 else if (*s == '+') { 38 s++; 39 } 40 if (case_insensitive_match(s, "inf")) { 41 s += 3; 42 if (case_insensitive_match(s, "inity")) 43 s += 5; 44 retval = negate ? -Py_HUGE_VAL : Py_HUGE_VAL; 45 } 46 #ifdef Py_NAN 47 else if (case_insensitive_match(s, "nan")) { 48 s += 3; 49 retval = negate ? -Py_NAN : Py_NAN; 50 } 51 #endif 52 else { 53 s = p; 54 retval = -1.0; 55 } 56 *endptr = (char *)s; 57 return retval; 58 } 11 59 12 60 /** … … 15 63 * @endptr: if non-%NULL, it returns the character after 16 64 * the last character used in the conversion. 17 * 65 * 18 66 * Converts a string to a #gdouble value. 19 67 * This function behaves like the standard strtod() function … … 32 80 * zero is returned and %ERANGE is stored in %errno. 33 81 * If memory allocation fails, %ENOMEM is stored in %errno. 34 * 82 * 35 83 * This function resets %errno before calling strtod() so that 36 84 * you can reliably detect overflow and underflow. … … 38 86 * Return value: the #gdouble value. 39 87 **/ 88 89 #ifndef PY_NO_SHORT_FLOAT_REPR 90 91 double 92 _PyOS_ascii_strtod(const char *nptr, char **endptr) 93 { 94 double result; 95 _Py_SET_53BIT_PRECISION_HEADER; 96 97 assert(nptr != NULL); 98 /* Set errno to zero, so that we can distinguish zero results 99 and underflows */ 100 errno = 0; 101 102 _Py_SET_53BIT_PRECISION_START; 103 result = _Py_dg_strtod(nptr, endptr); 104 _Py_SET_53BIT_PRECISION_END; 105 106 if (*endptr == nptr) 107 /* string might represent an inf or nan */ 108 result = _Py_parse_inf_or_nan(nptr, endptr); 109 110 return result; 111 112 } 113 114 #else 115 116 /* 117 Use system strtod; since strtod is locale aware, we may 118 have to first fix the decimal separator. 119 120 Note that unlike _Py_dg_strtod, the system strtod may not always give 121 correctly rounded results. 122 */ 123 124 double 125 _PyOS_ascii_strtod(const char *nptr, char **endptr) 126 { 127 char *fail_pos; 128 double val = -1.0; 129 struct lconv *locale_data; 130 const char *decimal_point; 131 size_t decimal_point_len; 132 const char *p, *decimal_point_pos; 133 const char *end = NULL; /* Silence gcc */ 134 const char *digits_pos = NULL; 135 int negate = 0; 136 137 assert(nptr != NULL); 138 139 fail_pos = NULL; 140 141 locale_data = localeconv(); 142 decimal_point = locale_data->decimal_point; 143 decimal_point_len = strlen(decimal_point); 144 145 assert(decimal_point_len != 0); 146 147 decimal_point_pos = NULL; 148 149 /* Parse infinities and nans */ 150 val = _Py_parse_inf_or_nan(nptr, endptr); 151 if (*endptr != nptr) 152 return val; 153 154 /* Set errno to zero, so that we can distinguish zero results 155 and underflows */ 156 errno = 0; 157 158 /* We process the optional sign manually, then pass the remainder to 159 the system strtod. This ensures that the result of an underflow 160 has the correct sign. (bug #1725) */ 161 p = nptr; 162 /* Process leading sign, if present */ 163 if (*p == '-') { 164 negate = 1; 165 p++; 166 } 167 else if (*p == '+') { 168 p++; 169 } 170 171 /* Some platform strtods accept hex floats; Python shouldn't (at the 172 moment), so we check explicitly for strings starting with '0x'. */ 173 if (*p == '0' && (*(p+1) == 'x' || *(p+1) == 'X')) 174 goto invalid_string; 175 176 /* Check that what's left begins with a digit or decimal point */ 177 if (!Py_ISDIGIT(*p) && *p != '.') 178 goto invalid_string; 179 180 digits_pos = p; 181 if (decimal_point[0] != '.' || 182 decimal_point[1] != 0) 183 { 184 /* Look for a '.' in the input; if present, it'll need to be 185 swapped for the current locale's decimal point before we 186 call strtod. On the other hand, if we find the current 187 locale's decimal point then the input is invalid. */ 188 while (Py_ISDIGIT(*p)) 189 p++; 190 191 if (*p == '.') 192 { 193 decimal_point_pos = p++; 194 195 /* locate end of number */ 196 while (Py_ISDIGIT(*p)) 197 p++; 198 199 if (*p == 'e' || *p == 'E') 200 p++; 201 if (*p == '+' || *p == '-') 202 p++; 203 while (Py_ISDIGIT(*p)) 204 p++; 205 end = p; 206 } 207 else if (strncmp(p, decimal_point, decimal_point_len) == 0) 208 /* Python bug #1417699 */ 209 goto invalid_string; 210 /* For the other cases, we need not convert the decimal 211 point */ 212 } 213 214 if (decimal_point_pos) { 215 char *copy, *c; 216 /* Create a copy of the input, with the '.' converted to the 217 locale-specific decimal point */ 218 copy = (char *)PyMem_MALLOC(end - digits_pos + 219 1 + decimal_point_len); 220 if (copy == NULL) { 221 *endptr = (char *)nptr; 222 errno = ENOMEM; 223 return val; 224 } 225 226 c = copy; 227 memcpy(c, digits_pos, decimal_point_pos - digits_pos); 228 c += decimal_point_pos - digits_pos; 229 memcpy(c, decimal_point, decimal_point_len); 230 c += decimal_point_len; 231 memcpy(c, decimal_point_pos + 1, 232 end - (decimal_point_pos + 1)); 233 c += end - (decimal_point_pos + 1); 234 *c = 0; 235 236 val = strtod(copy, &fail_pos); 237 238 if (fail_pos) 239 { 240 if (fail_pos > decimal_point_pos) 241 fail_pos = (char *)digits_pos + 242 (fail_pos - copy) - 243 (decimal_point_len - 1); 244 else 245 fail_pos = (char *)digits_pos + 246 (fail_pos - copy); 247 } 248 249 PyMem_FREE(copy); 250 251 } 252 else { 253 val = strtod(digits_pos, &fail_pos); 254 } 255 256 if (fail_pos == digits_pos) 257 goto invalid_string; 258 259 if (negate && fail_pos != nptr) 260 val = -val; 261 *endptr = fail_pos; 262 263 return val; 264 265 invalid_string: 266 *endptr = (char*)nptr; 267 errno = EINVAL; 268 return -1.0; 269 } 270 271 #endif 272 273 /* PyOS_ascii_strtod is DEPRECATED in Python 2.7 and 3.1 */ 274 40 275 double 41 276 PyOS_ascii_strtod(const char *nptr, char **endptr) 42 277 { 43 char *fail_pos; 44 double val = -1.0; 45 struct lconv *locale_data; 46 const char *decimal_point; 47 size_t decimal_point_len; 48 const char *p, *decimal_point_pos; 49 const char *end = NULL; /* Silence gcc */ 50 const char *digits_pos = NULL; 51 int negate = 0; 52 53 assert(nptr != NULL); 54 55 fail_pos = NULL; 56 57 locale_data = localeconv(); 58 decimal_point = locale_data->decimal_point; 59 decimal_point_len = strlen(decimal_point); 60 61 assert(decimal_point_len != 0); 62 63 decimal_point_pos = NULL; 64 65 /* We process any leading whitespace and the optional sign manually, 66 then pass the remainder to the system strtod. This ensures that 67 the result of an underflow has the correct sign. (bug #1725) */ 68 69 p = nptr; 70 /* Skip leading space */ 71 while (ISSPACE(*p)) 72 p++; 73 74 /* Process leading sign, if present */ 75 if (*p == '-') { 76 negate = 1; 77 p++; 78 } else if (*p == '+') { 79 p++; 80 } 81 82 /* What's left should begin with a digit, a decimal point, or one of 83 the letters i, I, n, N. It should not begin with 0x or 0X */ 84 if ((!ISDIGIT(*p) && 85 *p != '.' && *p != 'i' && *p != 'I' && *p != 'n' && *p != 'N') 86 || 87 (*p == '0' && (p[1] == 'x' || p[1] == 'X'))) 88 { 89 if (endptr) 90 *endptr = (char*)nptr; 91 errno = EINVAL; 92 return val; 93 } 94 digits_pos = p; 95 96 if (decimal_point[0] != '.' || 97 decimal_point[1] != 0) 98 { 99 while (ISDIGIT(*p)) 100 p++; 101 102 if (*p == '.') 103 { 104 decimal_point_pos = p++; 105 106 while (ISDIGIT(*p)) 107 p++; 108 109 if (*p == 'e' || *p == 'E') 110 p++; 111 if (*p == '+' || *p == '-') 112 p++; 113 while (ISDIGIT(*p)) 114 p++; 115 end = p; 116 } 117 else if (strncmp(p, decimal_point, decimal_point_len) == 0) 118 { 119 /* Python bug #1417699 */ 120 if (endptr) 121 *endptr = (char*)nptr; 122 errno = EINVAL; 123 return val; 124 } 125 /* For the other cases, we need not convert the decimal 126 point */ 127 } 128 129 /* Set errno to zero, so that we can distinguish zero results 130 and underflows */ 131 errno = 0; 132 133 if (decimal_point_pos) 134 { 135 char *copy, *c; 136 137 /* We need to convert the '.' to the locale specific decimal 138 point */ 139 copy = (char *)PyMem_MALLOC(end - digits_pos + 140 1 + decimal_point_len); 141 if (copy == NULL) { 142 if (endptr) 143 *endptr = (char *)nptr; 144 errno = ENOMEM; 145 return val; 146 } 147 148 c = copy; 149 memcpy(c, digits_pos, decimal_point_pos - digits_pos); 150 c += decimal_point_pos - digits_pos; 151 memcpy(c, decimal_point, decimal_point_len); 152 c += decimal_point_len; 153 memcpy(c, decimal_point_pos + 1, 154 end - (decimal_point_pos + 1)); 155 c += end - (decimal_point_pos + 1); 156 *c = 0; 157 158 val = strtod(copy, &fail_pos); 159 160 if (fail_pos) 161 { 162 if (fail_pos > decimal_point_pos) 163 fail_pos = (char *)digits_pos + 164 (fail_pos - copy) - 165 (decimal_point_len - 1); 166 else 167 fail_pos = (char *)digits_pos + 168 (fail_pos - copy); 169 } 170 171 PyMem_FREE(copy); 172 173 } 174 else { 175 val = strtod(digits_pos, &fail_pos); 176 } 177 178 if (fail_pos == digits_pos) 179 fail_pos = (char *)nptr; 180 181 if (negate && fail_pos != nptr) 182 val = -val; 183 184 if (endptr) 185 *endptr = fail_pos; 186 187 return val; 278 char *fail_pos; 279 const char *p; 280 double x; 281 282 if (PyErr_WarnEx(PyExc_DeprecationWarning, 283 "PyOS_ascii_strtod and PyOS_ascii_atof are " 284 "deprecated. Use PyOS_string_to_double " 285 "instead.", 1) < 0) 286 return -1.0; 287 288 /* _PyOS_ascii_strtod already does everything that we want, 289 except that it doesn't parse leading whitespace */ 290 p = nptr; 291 while (Py_ISSPACE(*p)) 292 p++; 293 x = _PyOS_ascii_strtod(p, &fail_pos); 294 if (fail_pos == p) 295 fail_pos = (char *)nptr; 296 if (endptr) 297 *endptr = (char *)fail_pos; 298 return x; 299 } 300 301 /* PyOS_ascii_strtod is DEPRECATED in Python 2.7 and 3.1 */ 302 303 double 304 PyOS_ascii_atof(const char *nptr) 305 { 306 return PyOS_ascii_strtod(nptr, NULL); 307 } 308 309 /* PyOS_string_to_double is the recommended replacement for the deprecated 310 PyOS_ascii_strtod and PyOS_ascii_atof functions. It converts a 311 null-terminated byte string s (interpreted as a string of ASCII characters) 312 to a float. The string should not have leading or trailing whitespace (in 313 contrast, PyOS_ascii_strtod allows leading whitespace but not trailing 314 whitespace). The conversion is independent of the current locale. 315 316 If endptr is NULL, try to convert the whole string. Raise ValueError and 317 return -1.0 if the string is not a valid representation of a floating-point 318 number. 319 320 If endptr is non-NULL, try to convert as much of the string as possible. 321 If no initial segment of the string is the valid representation of a 322 floating-point number then *endptr is set to point to the beginning of the 323 string, -1.0 is returned and again ValueError is raised. 324 325 On overflow (e.g., when trying to convert '1e500' on an IEEE 754 machine), 326 if overflow_exception is NULL then +-Py_HUGE_VAL is returned, and no Python 327 exception is raised. Otherwise, overflow_exception should point to a 328 a Python exception, this exception will be raised, -1.0 will be returned, 329 and *endptr will point just past the end of the converted value. 330 331 If any other failure occurs (for example lack of memory), -1.0 is returned 332 and the appropriate Python exception will have been set. 333 */ 334 335 double 336 PyOS_string_to_double(const char *s, 337 char **endptr, 338 PyObject *overflow_exception) 339 { 340 double x, result=-1.0; 341 char *fail_pos; 342 343 errno = 0; 344 PyFPE_START_PROTECT("PyOS_string_to_double", return -1.0) 345 x = _PyOS_ascii_strtod(s, &fail_pos); 346 PyFPE_END_PROTECT(x) 347 348 if (errno == ENOMEM) { 349 PyErr_NoMemory(); 350 fail_pos = (char *)s; 351 } 352 else if (!endptr && (fail_pos == s || *fail_pos != '\0')) 353 PyErr_Format(PyExc_ValueError, 354 "could not convert string to float: " 355 "%.200s", s); 356 else if (fail_pos == s) 357 PyErr_Format(PyExc_ValueError, 358 "could not convert string to float: " 359 "%.200s", s); 360 else if (errno == ERANGE && fabs(x) >= 1.0 && overflow_exception) 361 PyErr_Format(overflow_exception, 362 "value too large to convert to float: " 363 "%.200s", s); 364 else 365 result = x; 366 367 if (endptr != NULL) 368 *endptr = fail_pos; 369 return result; 188 370 } 189 371 … … 194 376 change_decimal_from_locale_to_dot(char* buffer) 195 377 { 196 197 198 199 200 201 202 203 204 while (isdigit(Py_CHARMASK(*buffer)))205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 378 struct lconv *locale_data = localeconv(); 379 const char *decimal_point = locale_data->decimal_point; 380 381 if (decimal_point[0] != '.' || decimal_point[1] != 0) { 382 size_t decimal_point_len = strlen(decimal_point); 383 384 if (*buffer == '+' || *buffer == '-') 385 buffer++; 386 while (Py_ISDIGIT(*buffer)) 387 buffer++; 388 if (strncmp(buffer, decimal_point, decimal_point_len) == 0) { 389 *buffer = '.'; 390 buffer++; 391 if (decimal_point_len > 1) { 392 /* buffer needs to get smaller */ 393 size_t rest_len = strlen(buffer + 394 (decimal_point_len - 1)); 395 memmove(buffer, 396 buffer + (decimal_point_len - 1), 397 rest_len); 398 buffer[rest_len] = 0; 399 } 400 } 401 } 220 402 } 221 403 … … 232 414 ensure_minimum_exponent_length(char* buffer, size_t buf_size) 233 415 { 234 char *p = strpbrk(buffer, "eE"); 235 if (p && (*(p + 1) == '-' || *(p + 1) == '+')) { 236 char *start = p + 2; 237 int exponent_digit_cnt = 0; 238 int leading_zero_cnt = 0; 239 int in_leading_zeros = 1; 240 int significant_digit_cnt; 241 242 /* Skip over the exponent and the sign. */ 243 p += 2; 244 245 /* Find the end of the exponent, keeping track of leading 246 zeros. */ 247 while (*p && isdigit(Py_CHARMASK(*p))) { 248 if (in_leading_zeros && *p == '0') 249 ++leading_zero_cnt; 250 if (*p != '0') 251 in_leading_zeros = 0; 252 ++p; 253 ++exponent_digit_cnt; 254 } 255 256 significant_digit_cnt = exponent_digit_cnt - leading_zero_cnt; 257 if (exponent_digit_cnt == MIN_EXPONENT_DIGITS) { 258 /* If there are 2 exactly digits, we're done, 259 regardless of what they contain */ 260 } 261 else if (exponent_digit_cnt > MIN_EXPONENT_DIGITS) { 262 int extra_zeros_cnt; 263 264 /* There are more than 2 digits in the exponent. See 265 if we can delete some of the leading zeros */ 266 if (significant_digit_cnt < MIN_EXPONENT_DIGITS) 267 significant_digit_cnt = MIN_EXPONENT_DIGITS; 268 extra_zeros_cnt = exponent_digit_cnt - 269 significant_digit_cnt; 270 271 /* Delete extra_zeros_cnt worth of characters from the 272 front of the exponent */ 273 assert(extra_zeros_cnt >= 0); 274 275 /* Add one to significant_digit_cnt to copy the 276 trailing 0 byte, thus setting the length */ 277 memmove(start, 278 start + extra_zeros_cnt, 279 significant_digit_cnt + 1); 280 } 281 else { 282 /* If there are fewer than 2 digits, add zeros 283 until there are 2, if there's enough room */ 284 int zeros = MIN_EXPONENT_DIGITS - exponent_digit_cnt; 285 if (start + zeros + exponent_digit_cnt + 1 286 < buffer + buf_size) { 287 memmove(start + zeros, start, 288 exponent_digit_cnt + 1); 289 memset(start, '0', zeros); 290 } 291 } 292 } 293 } 294 295 /* Ensure that buffer has a decimal point in it. The decimal point 296 will not be in the current locale, it will always be '.' */ 416 char *p = strpbrk(buffer, "eE"); 417 if (p && (*(p + 1) == '-' || *(p + 1) == '+')) { 418 char *start = p + 2; 419 int exponent_digit_cnt = 0; 420 int leading_zero_cnt = 0; 421 int in_leading_zeros = 1; 422 int significant_digit_cnt; 423 424 /* Skip over the exponent and the sign. */ 425 p += 2; 426 427 /* Find the end of the exponent, keeping track of leading 428 zeros. */ 429 while (*p && Py_ISDIGIT(*p)) { 430 if (in_leading_zeros && *p == '0') 431 ++leading_zero_cnt; 432 if (*p != '0') 433 in_leading_zeros = 0; 434 ++p; 435 ++exponent_digit_cnt; 436 } 437 438 significant_digit_cnt = exponent_digit_cnt - leading_zero_cnt; 439 if (exponent_digit_cnt == MIN_EXPONENT_DIGITS) { 440 /* If there are 2 exactly digits, we're done, 441 regardless of what they contain */ 442 } 443 else if (exponent_digit_cnt > MIN_EXPONENT_DIGITS) { 444 int extra_zeros_cnt; 445 446 /* There are more than 2 digits in the exponent. See 447 if we can delete some of the leading zeros */ 448 if (significant_digit_cnt < MIN_EXPONENT_DIGITS) 449 significant_digit_cnt = MIN_EXPONENT_DIGITS; 450 extra_zeros_cnt = exponent_digit_cnt - 451 significant_digit_cnt; 452 453 /* Delete extra_zeros_cnt worth of characters from the 454 front of the exponent */ 455 assert(extra_zeros_cnt >= 0); 456 457 /* Add one to significant_digit_cnt to copy the 458 trailing 0 byte, thus setting the length */ 459 memmove(start, 460 start + extra_zeros_cnt, 461 significant_digit_cnt + 1); 462 } 463 else { 464 /* If there are fewer than 2 digits, add zeros 465 until there are 2, if there's enough room */ 466 int zeros = MIN_EXPONENT_DIGITS - exponent_digit_cnt; 467 if (start + zeros + exponent_digit_cnt + 1 468 < buffer + buf_size) { 469 memmove(start + zeros, start, 470 exponent_digit_cnt + 1); 471 memset(start, '0', zeros); 472 } 473 } 474 } 475 } 476 477 /* Remove trailing zeros after the decimal point from a numeric string; also 478 remove the decimal point if all digits following it are zero. The numeric 479 string must end in '\0', and should not have any leading or trailing 480 whitespace. Assumes that the decimal point is '.'. */ 297 481 Py_LOCAL_INLINE(void) 298 ensure_decimal_point(char* buffer, size_t buf_size) 299 { 300 int insert_count = 0; 301 char* chars_to_insert; 302 303 /* search for the first non-digit character */ 304 char *p = buffer; 305 if (*p == '-' || *p == '+') 306 /* Skip leading sign, if present. I think this could only 307 ever be '-', but it can't hurt to check for both. */ 308 ++p; 309 while (*p && isdigit(Py_CHARMASK(*p))) 310 ++p; 311 312 if (*p == '.') { 313 if (isdigit(Py_CHARMASK(*(p+1)))) { 314 /* Nothing to do, we already have a decimal 315 point and a digit after it */ 316 } 317 else { 318 /* We have a decimal point, but no following 319 digit. Insert a zero after the decimal. */ 320 ++p; 321 chars_to_insert = "0"; 322 insert_count = 1; 323 } 324 } 325 else { 326 chars_to_insert = ".0"; 327 insert_count = 2; 328 } 329 if (insert_count) { 330 size_t buf_len = strlen(buffer); 331 if (buf_len + insert_count + 1 >= buf_size) { 332 /* If there is not enough room in the buffer 333 for the additional text, just skip it. It's 334 not worth generating an error over. */ 335 } 336 else { 337 memmove(p + insert_count, p, 338 buffer + strlen(buffer) - p + 1); 339 memcpy(p, chars_to_insert, insert_count); 340 } 341 } 342 } 343 344 /* Add the locale specific grouping characters to buffer. Note 345 that any decimal point (if it's present) in buffer is already 346 locale-specific. Return 0 on error, else 1. */ 347 Py_LOCAL_INLINE(int) 348 add_thousands_grouping(char* buffer, size_t buf_size) 349 { 350 Py_ssize_t len = strlen(buffer); 351 struct lconv *locale_data = localeconv(); 352 const char *decimal_point = locale_data->decimal_point; 353 354 /* Find the decimal point, if any. We're only concerned 355 about the characters to the left of the decimal when 356 adding grouping. */ 357 char *p = strstr(buffer, decimal_point); 358 if (!p) { 359 /* No decimal, use the entire string. */ 360 361 /* If any exponent, adjust p. */ 362 p = strpbrk(buffer, "eE"); 363 if (!p) 364 /* No exponent and no decimal. Use the entire 365 string. */ 366 p = buffer + len; 367 } 368 /* At this point, p points just past the right-most character we 369 want to format. We need to add the grouping string for the 370 characters between buffer and p. */ 371 return _PyString_InsertThousandsGrouping(buffer, len, p-buffer, 372 buf_size, NULL, 1); 482 remove_trailing_zeros(char *buffer) 483 { 484 char *old_fraction_end, *new_fraction_end, *end, *p; 485 486 p = buffer; 487 if (*p == '-' || *p == '+') 488 /* Skip leading sign, if present */ 489 ++p; 490 while (Py_ISDIGIT(*p)) 491 ++p; 492 493 /* if there's no decimal point there's nothing to do */ 494 if (*p++ != '.') 495 return; 496 497 /* scan any digits after the point */ 498 while (Py_ISDIGIT(*p)) 499 ++p; 500 old_fraction_end = p; 501 502 /* scan up to ending '\0' */ 503 while (*p != '\0') 504 p++; 505 /* +1 to make sure that we move the null byte as well */ 506 end = p+1; 507 508 /* scan back from fraction_end, looking for removable zeros */ 509 p = old_fraction_end; 510 while (*(p-1) == '0') 511 --p; 512 /* and remove point if we've got that far */ 513 if (*(p-1) == '.') 514 --p; 515 new_fraction_end = p; 516 517 memmove(new_fraction_end, old_fraction_end, end-old_fraction_end); 518 } 519 520 /* Ensure that buffer has a decimal point in it. The decimal point will not 521 be in the current locale, it will always be '.'. Don't add a decimal point 522 if an exponent is present. Also, convert to exponential notation where 523 adding a '.0' would produce too many significant digits (see issue 5864). 524 525 Returns a pointer to the fixed buffer, or NULL on failure. 526 */ 527 Py_LOCAL_INLINE(char *) 528 ensure_decimal_point(char* buffer, size_t buf_size, int precision) 529 { 530 int digit_count, insert_count = 0, convert_to_exp = 0; 531 char *chars_to_insert, *digits_start; 532 533 /* search for the first non-digit character */ 534 char *p = buffer; 535 if (*p == '-' || *p == '+') 536 /* Skip leading sign, if present. I think this could only 537 ever be '-', but it can't hurt to check for both. */ 538 ++p; 539 digits_start = p; 540 while (*p && Py_ISDIGIT(*p)) 541 ++p; 542 digit_count = Py_SAFE_DOWNCAST(p - digits_start, Py_ssize_t, int); 543 544 if (*p == '.') { 545 if (Py_ISDIGIT(*(p+1))) { 546 /* Nothing to do, we already have a decimal 547 point and a digit after it */ 548 } 549 else { 550 /* We have a decimal point, but no following 551 digit. Insert a zero after the decimal. */ 552 /* can't ever get here via PyOS_double_to_string */ 553 assert(precision == -1); 554 ++p; 555 chars_to_insert = "0"; 556 insert_count = 1; 557 } 558 } 559 else if (!(*p == 'e' || *p == 'E')) { 560 /* Don't add ".0" if we have an exponent. */ 561 if (digit_count == precision) { 562 /* issue 5864: don't add a trailing .0 in the case 563 where the '%g'-formatted result already has as many 564 significant digits as were requested. Switch to 565 exponential notation instead. */ 566 convert_to_exp = 1; 567 /* no exponent, no point, and we shouldn't land here 568 for infs and nans, so we must be at the end of the 569 string. */ 570 assert(*p == '\0'); 571 } 572 else { 573 assert(precision == -1 || digit_count < precision); 574 chars_to_insert = ".0"; 575 insert_count = 2; 576 } 577 } 578 if (insert_count) { 579 size_t buf_len = strlen(buffer); 580 if (buf_len + insert_count + 1 >= buf_size) { 581 /* If there is not enough room in the buffer 582 for the additional text, just skip it. It's 583 not worth generating an error over. */ 584 } 585 else { 586 memmove(p + insert_count, p, 587 buffer + strlen(buffer) - p + 1); 588 memcpy(p, chars_to_insert, insert_count); 589 } 590 } 591 if (convert_to_exp) { 592 int written; 593 size_t buf_avail; 594 p = digits_start; 595 /* insert decimal point */ 596 assert(digit_count >= 1); 597 memmove(p+2, p+1, digit_count); /* safe, but overwrites nul */ 598 p[1] = '.'; 599 p += digit_count+1; 600 assert(p <= buf_size+buffer); 601 buf_avail = buf_size+buffer-p; 602 if (buf_avail == 0) 603 return NULL; 604 /* Add exponent. It's okay to use lower case 'e': we only 605 arrive here as a result of using the empty format code or 606 repr/str builtins and those never want an upper case 'E' */ 607 written = PyOS_snprintf(p, buf_avail, "e%+.02d", digit_count-1); 608 if (!(0 <= written && 609 written < Py_SAFE_DOWNCAST(buf_avail, size_t, int))) 610 /* output truncated, or something else bad happened */ 611 return NULL; 612 remove_trailing_zeros(buffer); 613 } 614 return buffer; 373 615 } 374 616 … … 381 623 * @buf_size: The length of the buffer. 382 624 * @format: The printf()-style format to use for the 383 * code to use for converting. 625 * code to use for converting. 384 626 * @d: The #gdouble to convert 385 627 * … … 387 629 * decimal point. To format the number you pass in 388 630 * a printf()-style format string. Allowed conversion 389 * specifiers are 'e', 'E', 'f', 'F', 'g', 'G', and 'n'. 390 * 391 * 'n' is the same as 'g', except it uses the current locale. 631 * specifiers are 'e', 'E', 'f', 'F', 'g', 'G', and 'Z'. 632 * 392 633 * 'Z' is the same as 'g', except it always has a decimal and 393 634 * at least one digit after the decimal. 394 635 * 395 636 * Return value: The pointer to the buffer with the converted string. 637 * On failure returns NULL but does not set any Python exception. 396 638 **/ 397 639 char * 398 PyOS_ascii_formatd(char *buffer, 399 size_t buf_size, 400 const char *format, 401 double d) 402 { 403 char format_char; 404 size_t format_len = strlen(format); 405 406 /* For type 'n', we need to make a copy of the format string, because 407 we're going to modify 'n' -> 'g', and format is const char*, so we 408 can't modify it directly. FLOAT_FORMATBUFLEN should be longer than 409 we ever need this to be. There's an upcoming check to ensure it's 410 big enough. */ 411 /* Issue 2264: code 'Z' requires copying the format. 'Z' is 'g', but 412 also with at least one character past the decimal. */ 413 char tmp_format[FLOAT_FORMATBUFLEN]; 414 415 /* The last character in the format string must be the format char */ 416 format_char = format[format_len - 1]; 417 418 if (format[0] != '%') 419 return NULL; 420 421 /* I'm not sure why this test is here. It's ensuring that the format 422 string after the first character doesn't have a single quote, a 423 lowercase l, or a percent. This is the reverse of the commented-out 424 test about 10 lines ago. */ 425 if (strpbrk(format + 1, "'l%")) 426 return NULL; 427 428 /* Also curious about this function is that it accepts format strings 429 like "%xg", which are invalid for floats. In general, the 430 interface to this function is not very good, but changing it is 431 difficult because it's a public API. */ 432 433 if (!(format_char == 'e' || format_char == 'E' || 434 format_char == 'f' || format_char == 'F' || 435 format_char == 'g' || format_char == 'G' || 436 format_char == 'n' || format_char == 'Z')) 437 return NULL; 438 439 /* Map 'n' or 'Z' format_char to 'g', by copying the format string and 440 replacing the final char with a 'g' */ 441 if (format_char == 'n' || format_char == 'Z') { 442 if (format_len + 1 >= sizeof(tmp_format)) { 443 /* The format won't fit in our copy. Error out. In 444 practice, this will never happen and will be 445 detected by returning NULL */ 446 return NULL; 447 } 448 strcpy(tmp_format, format); 449 tmp_format[format_len - 1] = 'g'; 450 format = tmp_format; 451 } 452 453 454 /* Have PyOS_snprintf do the hard work */ 455 PyOS_snprintf(buffer, buf_size, format, d); 456 457 /* Do various fixups on the return string */ 458 459 /* Get the current locale, and find the decimal point string. 460 Convert that string back to a dot. Do not do this if using the 461 'n' (number) format code, since we want to keep the localized 462 decimal point in that case. */ 463 if (format_char != 'n') 464 change_decimal_from_locale_to_dot(buffer); 465 466 /* If an exponent exists, ensure that the exponent is at least 467 MIN_EXPONENT_DIGITS digits, providing the buffer is large enough 468 for the extra zeros. Also, if there are more than 469 MIN_EXPONENT_DIGITS, remove as many zeros as possible until we get 470 back to MIN_EXPONENT_DIGITS */ 471 ensure_minimum_exponent_length(buffer, buf_size); 472 473 /* If format_char is 'Z', make sure we have at least one character 474 after the decimal point (and make sure we have a decimal point). */ 475 if (format_char == 'Z') 476 ensure_decimal_point(buffer, buf_size); 477 478 /* If format_char is 'n', add the thousands grouping. */ 479 if (format_char == 'n') 480 if (!add_thousands_grouping(buffer, buf_size)) 481 return NULL; 482 483 return buffer; 484 } 485 486 double 487 PyOS_ascii_atof(const char *nptr) 488 { 489 return PyOS_ascii_strtod(nptr, NULL); 490 } 640 _PyOS_ascii_formatd(char *buffer, 641 size_t buf_size, 642 const char *format, 643 double d, 644 int precision) 645 { 646 char format_char; 647 size_t format_len = strlen(format); 648 649 /* Issue 2264: code 'Z' requires copying the format. 'Z' is 'g', but 650 also with at least one character past the decimal. */ 651 char tmp_format[FLOAT_FORMATBUFLEN]; 652 653 /* The last character in the format string must be the format char */ 654 format_char = format[format_len - 1]; 655 656 if (format[0] != '%') 657 return NULL; 658 659 /* I'm not sure why this test is here. It's ensuring that the format 660 string after the first character doesn't have a single quote, a 661 lowercase l, or a percent. This is the reverse of the commented-out 662 test about 10 lines ago. */ 663 if (strpbrk(format + 1, "'l%")) 664 return NULL; 665 666 /* Also curious about this function is that it accepts format strings 667 like "%xg", which are invalid for floats. In general, the 668 interface to this function is not very good, but changing it is 669 difficult because it's a public API. */ 670 671 if (!(format_char == 'e' || format_char == 'E' || 672 format_char == 'f' || format_char == 'F' || 673 format_char == 'g' || format_char == 'G' || 674 format_char == 'Z')) 675 return NULL; 676 677 /* Map 'Z' format_char to 'g', by copying the format string and 678 replacing the final char with a 'g' */ 679 if (format_char == 'Z') { 680 if (format_len + 1 >= sizeof(tmp_format)) { 681 /* The format won't fit in our copy. Error out. In 682 practice, this will never happen and will be 683 detected by returning NULL */ 684 return NULL; 685 } 686 strcpy(tmp_format, format); 687 tmp_format[format_len - 1] = 'g'; 688 format = tmp_format; 689 } 690 691 692 /* Have PyOS_snprintf do the hard work */ 693 PyOS_snprintf(buffer, buf_size, format, d); 694 695 /* Do various fixups on the return string */ 696 697 /* Get the current locale, and find the decimal point string. 698 Convert that string back to a dot. */ 699 change_decimal_from_locale_to_dot(buffer); 700 701 /* If an exponent exists, ensure that the exponent is at least 702 MIN_EXPONENT_DIGITS digits, providing the buffer is large enough 703 for the extra zeros. Also, if there are more than 704 MIN_EXPONENT_DIGITS, remove as many zeros as possible until we get 705 back to MIN_EXPONENT_DIGITS */ 706 ensure_minimum_exponent_length(buffer, buf_size); 707 708 /* If format_char is 'Z', make sure we have at least one character 709 after the decimal point (and make sure we have a decimal point); 710 also switch to exponential notation in some edge cases where the 711 extra character would produce more significant digits that we 712 really want. */ 713 if (format_char == 'Z') 714 buffer = ensure_decimal_point(buffer, buf_size, precision); 715 716 return buffer; 717 } 718 719 char * 720 PyOS_ascii_formatd(char *buffer, 721 size_t buf_size, 722 const char *format, 723 double d) 724 { 725 if (PyErr_WarnEx(PyExc_DeprecationWarning, 726 "PyOS_ascii_formatd is deprecated, " 727 "use PyOS_double_to_string instead", 1) < 0) 728 return NULL; 729 730 return _PyOS_ascii_formatd(buffer, buf_size, format, d, -1); 731 } 732 733 #ifdef PY_NO_SHORT_FLOAT_REPR 734 735 /* The fallback code to use if _Py_dg_dtoa is not available. */ 736 737 PyAPI_FUNC(char *) PyOS_double_to_string(double val, 738 char format_code, 739 int precision, 740 int flags, 741 int *type) 742 { 743 char format[32]; 744 Py_ssize_t bufsize; 745 char *buf; 746 int t, exp; 747 int upper = 0; 748 749 /* Validate format_code, and map upper and lower case */ 750 switch (format_code) { 751 case 'e': /* exponent */ 752 case 'f': /* fixed */ 753 case 'g': /* general */ 754 break; 755 case 'E': 756 upper = 1; 757 format_code = 'e'; 758 break; 759 case 'F': 760 upper = 1; 761 format_code = 'f'; 762 break; 763 case 'G': 764 upper = 1; 765 format_code = 'g'; 766 break; 767 case 'r': /* repr format */ 768 /* Supplied precision is unused, must be 0. */ 769 if (precision != 0) { 770 PyErr_BadInternalCall(); 771 return NULL; 772 } 773 /* The repr() precision (17 significant decimal digits) is the 774 minimal number that is guaranteed to have enough precision 775 so that if the number is read back in the exact same binary 776 value is recreated. This is true for IEEE floating point 777 by design, and also happens to work for all other modern 778 hardware. */ 779 precision = 17; 780 format_code = 'g'; 781 break; 782 default: 783 PyErr_BadInternalCall(); 784 return NULL; 785 } 786 787 /* Here's a quick-and-dirty calculation to figure out how big a buffer 788 we need. In general, for a finite float we need: 789 790 1 byte for each digit of the decimal significand, and 791 792 1 for a possible sign 793 1 for a possible decimal point 794 2 for a possible [eE][+-] 795 1 for each digit of the exponent; if we allow 19 digits 796 total then we're safe up to exponents of 2**63. 797 1 for the trailing nul byte 798 799 This gives a total of 24 + the number of digits in the significand, 800 and the number of digits in the significand is: 801 802 for 'g' format: at most precision, except possibly 803 when precision == 0, when it's 1. 804 for 'e' format: precision+1 805 for 'f' format: precision digits after the point, at least 1 806 before. To figure out how many digits appear before the point 807 we have to examine the size of the number. If fabs(val) < 1.0 808 then there will be only one digit before the point. If 809 fabs(val) >= 1.0, then there are at most 810 811 1+floor(log10(ceiling(fabs(val)))) 812 813 digits before the point (where the 'ceiling' allows for the 814 possibility that the rounding rounds the integer part of val 815 up). A safe upper bound for the above quantity is 816 1+floor(exp/3), where exp is the unique integer such that 0.5 817 <= fabs(val)/2**exp < 1.0. This exp can be obtained from 818 frexp. 819 820 So we allow room for precision+1 digits for all formats, plus an 821 extra floor(exp/3) digits for 'f' format. 822 823 */ 824 825 if (Py_IS_NAN(val) || Py_IS_INFINITY(val)) 826 /* 3 for 'inf'/'nan', 1 for sign, 1 for '\0' */ 827 bufsize = 5; 828 else { 829 bufsize = 25 + precision; 830 if (format_code == 'f' && fabs(val) >= 1.0) { 831 frexp(val, &exp); 832 bufsize += exp/3; 833 } 834 } 835 836 buf = PyMem_Malloc(bufsize); 837 if (buf == NULL) { 838 PyErr_NoMemory(); 839 return NULL; 840 } 841 842 /* Handle nan and inf. */ 843 if (Py_IS_NAN(val)) { 844 strcpy(buf, "nan"); 845 t = Py_DTST_NAN; 846 } else if (Py_IS_INFINITY(val)) { 847 if (copysign(1., val) == 1.) 848 strcpy(buf, "inf"); 849 else 850 strcpy(buf, "-inf"); 851 t = Py_DTST_INFINITE; 852 } else { 853 t = Py_DTST_FINITE; 854 if (flags & Py_DTSF_ADD_DOT_0) 855 format_code = 'Z'; 856 857 PyOS_snprintf(format, sizeof(format), "%%%s.%i%c", 858 (flags & Py_DTSF_ALT ? "#" : ""), precision, 859 format_code); 860 _PyOS_ascii_formatd(buf, bufsize, format, val, precision); 861 } 862 863 /* Add sign when requested. It's convenient (esp. when formatting 864 complex numbers) to include a sign even for inf and nan. */ 865 if (flags & Py_DTSF_SIGN && buf[0] != '-') { 866 size_t len = strlen(buf); 867 /* the bufsize calculations above should ensure that we've got 868 space to add a sign */ 869 assert((size_t)bufsize >= len+2); 870 memmove(buf+1, buf, len+1); 871 buf[0] = '+'; 872 } 873 if (upper) { 874 /* Convert to upper case. */ 875 char *p1; 876 for (p1 = buf; *p1; p1++) 877 *p1 = Py_TOUPPER(*p1); 878 } 879 880 if (type) 881 *type = t; 882 return buf; 883 } 884 885 #else 886 887 /* _Py_dg_dtoa is available. */ 888 889 /* I'm using a lookup table here so that I don't have to invent a non-locale 890 specific way to convert to uppercase */ 891 #define OFS_INF 0 892 #define OFS_NAN 1 893 #define OFS_E 2 894 895 /* The lengths of these are known to the code below, so don't change them */ 896 static char *lc_float_strings[] = { 897 "inf", 898 "nan", 899 "e", 900 }; 901 static char *uc_float_strings[] = { 902 "INF", 903 "NAN", 904 "E", 905 }; 906 907 908 /* Convert a double d to a string, and return a PyMem_Malloc'd block of 909 memory contain the resulting string. 910 911 Arguments: 912 d is the double to be converted 913 format_code is one of 'e', 'f', 'g', 'r'. 'e', 'f' and 'g' 914 correspond to '%e', '%f' and '%g'; 'r' corresponds to repr. 915 mode is one of '0', '2' or '3', and is completely determined by 916 format_code: 'e' and 'g' use mode 2; 'f' mode 3, 'r' mode 0. 917 precision is the desired precision 918 always_add_sign is nonzero if a '+' sign should be included for positive 919 numbers 920 add_dot_0_if_integer is nonzero if integers in non-exponential form 921 should have ".0" added. Only applies to format codes 'r' and 'g'. 922 use_alt_formatting is nonzero if alternative formatting should be 923 used. Only applies to format codes 'e', 'f' and 'g'. For code 'g', 924 at most one of use_alt_formatting and add_dot_0_if_integer should 925 be nonzero. 926 type, if non-NULL, will be set to one of these constants to identify 927 the type of the 'd' argument: 928 Py_DTST_FINITE 929 Py_DTST_INFINITE 930 Py_DTST_NAN 931 932 Returns a PyMem_Malloc'd block of memory containing the resulting string, 933 or NULL on error. If NULL is returned, the Python error has been set. 934 */ 935 936 static char * 937 format_float_short(double d, char format_code, 938 int mode, Py_ssize_t precision, 939 int always_add_sign, int add_dot_0_if_integer, 940 int use_alt_formatting, char **float_strings, int *type) 941 { 942 char *buf = NULL; 943 char *p = NULL; 944 Py_ssize_t bufsize = 0; 945 char *digits, *digits_end; 946 int decpt_as_int, sign, exp_len, exp = 0, use_exp = 0; 947 Py_ssize_t decpt, digits_len, vdigits_start, vdigits_end; 948 _Py_SET_53BIT_PRECISION_HEADER; 949 950 /* _Py_dg_dtoa returns a digit string (no decimal point or exponent). 951 Must be matched by a call to _Py_dg_freedtoa. */ 952 _Py_SET_53BIT_PRECISION_START; 953 digits = _Py_dg_dtoa(d, mode, precision, &decpt_as_int, &sign, 954 &digits_end); 955 _Py_SET_53BIT_PRECISION_END; 956 957 decpt = (Py_ssize_t)decpt_as_int; 958 if (digits == NULL) { 959 /* The only failure mode is no memory. */ 960 PyErr_NoMemory(); 961 goto exit; 962 } 963 assert(digits_end != NULL && digits_end >= digits); 964 digits_len = digits_end - digits; 965 966 if (digits_len && !Py_ISDIGIT(digits[0])) { 967 /* Infinities and nans here; adapt Gay's output, 968 so convert Infinity to inf and NaN to nan, and 969 ignore sign of nan. Then return. */ 970 971 /* ignore the actual sign of a nan */ 972 if (digits[0] == 'n' || digits[0] == 'N') 973 sign = 0; 974 975 /* We only need 5 bytes to hold the result "+inf\0" . */ 976 bufsize = 5; /* Used later in an assert. */ 977 buf = (char *)PyMem_Malloc(bufsize); 978 if (buf == NULL) { 979 PyErr_NoMemory(); 980 goto exit; 981 } 982 p = buf; 983 984 if (sign == 1) { 985 *p++ = '-'; 986 } 987 else if (always_add_sign) { 988 *p++ = '+'; 989 } 990 if (digits[0] == 'i' || digits[0] == 'I') { 991 strncpy(p, float_strings[OFS_INF], 3); 992 p += 3; 993 994 if (type) 995 *type = Py_DTST_INFINITE; 996 } 997 else if (digits[0] == 'n' || digits[0] == 'N') { 998 strncpy(p, float_strings[OFS_NAN], 3); 999 p += 3; 1000 1001 if (type) 1002 *type = Py_DTST_NAN; 1003 } 1004 else { 1005 /* shouldn't get here: Gay's code should always return 1006 something starting with a digit, an 'I', or 'N' */ 1007 strncpy(p, "ERR", 3); 1008 p += 3; 1009 assert(0); 1010 } 1011 goto exit; 1012 } 1013 1014 /* The result must be finite (not inf or nan). */ 1015 if (type) 1016 *type = Py_DTST_FINITE; 1017 1018 1019 /* We got digits back, format them. We may need to pad 'digits' 1020 either on the left or right (or both) with extra zeros, so in 1021 general the resulting string has the form 1022 1023 [<sign>]<zeros><digits><zeros>[<exponent>] 1024 1025 where either of the <zeros> pieces could be empty, and there's a 1026 decimal point that could appear either in <digits> or in the 1027 leading or trailing <zeros>. 1028 1029 Imagine an infinite 'virtual' string vdigits, consisting of the 1030 string 'digits' (starting at index 0) padded on both the left and 1031 right with infinite strings of zeros. We want to output a slice 1032 1033 vdigits[vdigits_start : vdigits_end] 1034 1035 of this virtual string. Thus if vdigits_start < 0 then we'll end 1036 up producing some leading zeros; if vdigits_end > digits_len there 1037 will be trailing zeros in the output. The next section of code 1038 determines whether to use an exponent or not, figures out the 1039 position 'decpt' of the decimal point, and computes 'vdigits_start' 1040 and 'vdigits_end'. */ 1041 vdigits_end = digits_len; 1042 switch (format_code) { 1043 case 'e': 1044 use_exp = 1; 1045 vdigits_end = precision; 1046 break; 1047 case 'f': 1048 vdigits_end = decpt + precision; 1049 break; 1050 case 'g': 1051 if (decpt <= -4 || decpt > 1052 (add_dot_0_if_integer ? precision-1 : precision)) 1053 use_exp = 1; 1054 if (use_alt_formatting) 1055 vdigits_end = precision; 1056 break; 1057 case 'r': 1058 /* convert to exponential format at 1e16. We used to convert 1059 at 1e17, but that gives odd-looking results for some values 1060 when a 16-digit 'shortest' repr is padded with bogus zeros. 1061 For example, repr(2e16+8) would give 20000000000000010.0; 1062 the true value is 20000000000000008.0. */ 1063 if (decpt <= -4 || decpt > 16) 1064 use_exp = 1; 1065 break; 1066 default: 1067 PyErr_BadInternalCall(); 1068 goto exit; 1069 } 1070 1071 /* if using an exponent, reset decimal point position to 1 and adjust 1072 exponent accordingly.*/ 1073 if (use_exp) { 1074 exp = decpt - 1; 1075 decpt = 1; 1076 } 1077 /* ensure vdigits_start < decpt <= vdigits_end, or vdigits_start < 1078 decpt < vdigits_end if add_dot_0_if_integer and no exponent */ 1079 vdigits_start = decpt <= 0 ? decpt-1 : 0; 1080 if (!use_exp && add_dot_0_if_integer) 1081 vdigits_end = vdigits_end > decpt ? vdigits_end : decpt + 1; 1082 else 1083 vdigits_end = vdigits_end > decpt ? vdigits_end : decpt; 1084 1085 /* double check inequalities */ 1086 assert(vdigits_start <= 0 && 1087 0 <= digits_len && 1088 digits_len <= vdigits_end); 1089 /* decimal point should be in (vdigits_start, vdigits_end] */ 1090 assert(vdigits_start < decpt && decpt <= vdigits_end); 1091 1092 /* Compute an upper bound how much memory we need. This might be a few 1093 chars too long, but no big deal. */ 1094 bufsize = 1095 /* sign, decimal point and trailing 0 byte */ 1096 3 + 1097 1098 /* total digit count (including zero padding on both sides) */ 1099 (vdigits_end - vdigits_start) + 1100 1101 /* exponent "e+100", max 3 numerical digits */ 1102 (use_exp ? 5 : 0); 1103 1104 /* Now allocate the memory and initialize p to point to the start of 1105 it. */ 1106 buf = (char *)PyMem_Malloc(bufsize); 1107 if (buf == NULL) { 1108 PyErr_NoMemory(); 1109 goto exit; 1110 } 1111 p = buf; 1112 1113 /* Add a negative sign if negative, and a plus sign if non-negative 1114 and always_add_sign is true. */ 1115 if (sign == 1) 1116 *p++ = '-'; 1117 else if (always_add_sign) 1118 *p++ = '+'; 1119 1120 /* note that exactly one of the three 'if' conditions is true, 1121 so we include exactly one decimal point */ 1122 /* Zero padding on left of digit string */ 1123 if (decpt <= 0) { 1124 memset(p, '0', decpt-vdigits_start); 1125 p += decpt - vdigits_start; 1126 *p++ = '.'; 1127 memset(p, '0', 0-decpt); 1128 p += 0-decpt; 1129 } 1130 else { 1131 memset(p, '0', 0-vdigits_start); 1132 p += 0 - vdigits_start; 1133 } 1134 1135 /* Digits, with included decimal point */ 1136 if (0 < decpt && decpt <= digits_len) { 1137 strncpy(p, digits, decpt-0); 1138 p += decpt-0; 1139 *p++ = '.'; 1140 strncpy(p, digits+decpt, digits_len-decpt); 1141 p += digits_len-decpt; 1142 } 1143 else { 1144 strncpy(p, digits, digits_len); 1145 p += digits_len; 1146 } 1147 1148 /* And zeros on the right */ 1149 if (digits_len < decpt) { 1150 memset(p, '0', decpt-digits_len); 1151 p += decpt-digits_len; 1152 *p++ = '.'; 1153 memset(p, '0', vdigits_end-decpt); 1154 p += vdigits_end-decpt; 1155 } 1156 else { 1157 memset(p, '0', vdigits_end-digits_len); 1158 p += vdigits_end-digits_len; 1159 } 1160 1161 /* Delete a trailing decimal pt unless using alternative formatting. */ 1162 if (p[-1] == '.' && !use_alt_formatting) 1163 p--; 1164 1165 /* Now that we've done zero padding, add an exponent if needed. */ 1166 if (use_exp) { 1167 *p++ = float_strings[OFS_E][0]; 1168 exp_len = sprintf(p, "%+.02d", exp); 1169 p += exp_len; 1170 } 1171 exit: 1172 if (buf) { 1173 *p = '\0'; 1174 /* It's too late if this fails, as we've already stepped on 1175 memory that isn't ours. But it's an okay debugging test. */ 1176 assert(p-buf < bufsize); 1177 } 1178 if (digits) 1179 _Py_dg_freedtoa(digits); 1180 1181 return buf; 1182 } 1183 1184 1185 PyAPI_FUNC(char *) PyOS_double_to_string(double val, 1186 char format_code, 1187 int precision, 1188 int flags, 1189 int *type) 1190 { 1191 char **float_strings = lc_float_strings; 1192 int mode; 1193 1194 /* Validate format_code, and map upper and lower case. Compute the 1195 mode and make any adjustments as needed. */ 1196 switch (format_code) { 1197 /* exponent */ 1198 case 'E': 1199 float_strings = uc_float_strings; 1200 format_code = 'e'; 1201 /* Fall through. */ 1202 case 'e': 1203 mode = 2; 1204 precision++; 1205 break; 1206 1207 /* fixed */ 1208 case 'F': 1209 float_strings = uc_float_strings; 1210 format_code = 'f'; 1211 /* Fall through. */ 1212 case 'f': 1213 mode = 3; 1214 break; 1215 1216 /* general */ 1217 case 'G': 1218 float_strings = uc_float_strings; 1219 format_code = 'g'; 1220 /* Fall through. */ 1221 case 'g': 1222 mode = 2; 1223 /* precision 0 makes no sense for 'g' format; interpret as 1 */ 1224 if (precision == 0) 1225 precision = 1; 1226 break; 1227 1228 /* repr format */ 1229 case 'r': 1230 mode = 0; 1231 /* Supplied precision is unused, must be 0. */ 1232 if (precision != 0) { 1233 PyErr_BadInternalCall(); 1234 return NULL; 1235 } 1236 break; 1237 1238 default: 1239 PyErr_BadInternalCall(); 1240 return NULL; 1241 } 1242 1243 return format_float_short(val, format_code, mode, precision, 1244 flags & Py_DTSF_SIGN, 1245 flags & Py_DTSF_ADD_DOT_0, 1246 flags & Py_DTSF_ALT, 1247 float_strings, type); 1248 } 1249 #endif /* ifdef PY_NO_SHORT_FLOAT_REPR */
Note:
See TracChangeset
for help on using the changeset viewer.