LCOV - code coverage report
Current view: top level - Python - pystrtod.c (source / functions) Hit Total Coverage
Test: CPython 3.12 LCOV report [commit acb105a7c1f] Lines: 215 229 93.9 %
Date: 2022-07-20 13:12:14 Functions: 7 7 100.0 %
Branches: 146 167 87.4 %

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

Generated by: LCOV version 1.14