static FLOAT_STRING_TYPE splitFloatString()

in src/crt_abstractions.c [477:571]


static FLOAT_STRING_TYPE splitFloatString(const char* nptr, char** endptr, int *signal, double *fraction, int *exponential)
{
    FLOAT_STRING_TYPE result = FST_ERROR;

    unsigned long long ullInteger = 0;
    unsigned long long ullFraction = 0;
    int integerSize = 0;
    int fractionSize = 0;
    char* startptr;

    (*endptr) = (char*)nptr;

    /*Codes_SRS_CRT_ABSTRACTIONS_21_018: [The white-space for strtof_s must be one of the characters ' ', '\f', '\n', '\r', '\t', '\v'.]*/
    /*Codes_SRS_CRT_ABSTRACTIONS_21_028: [The white-space for strtold_s must be one of the characters ' ', '\f', '\n', '\r', '\t', '\v'.]*/
    while (IS_SPACE(**endptr))
    {
        (*endptr)++;
    }

    /*Codes_SRS_CRT_ABSTRACTIONS_21_019: [The valid sequence for strtof_s starts after the first non-white - space character, followed by an optional positive or negative sign, a number, 'INF', or 'NAN' (ignoring case).]*/
    /*Codes_SRS_CRT_ABSTRACTIONS_21_029: [The valid sequence for strtold_s starts after the first non-white - space character, followed by an optional positive or negative sign, a number, 'INF', or 'NAN' (ignoring case).]*/
    (*signal) = +1;
    if ((**endptr) == '+')
    {
        (*endptr)++;
    }
    else if ((**endptr) == '-')
    {
        (*signal) = -1;
        (*endptr)++;
    }

    /*Codes_SRS_CRT_ABSTRACTIONS_21_023: [If the string is 'INF' of 'INFINITY' (ignoring case), the strtof_s must return the INFINITY value for float.]*/
    /*Codes_SRS_CRT_ABSTRACTIONS_21_033: [If the string is 'INF' of 'INFINITY' (ignoring case), the strtold_s must return the INFINITY value for long double.]*/
    if (isInfinity((const char**)endptr))
    {
        result = FST_INFINITY;
    }
    /*Codes_SRS_CRT_ABSTRACTIONS_21_034: [If the string is 'NAN' or 'NAN(...)' (ignoring case), the strtold_s must return 0.0 and points endptr to the first character after the 'NAN' sequence.]*/
    /*Codes_SRS_CRT_ABSTRACTIONS_21_024: [If the string is 'NAN' or 'NAN(...)' (ignoring case), the strtof_s must return 0.0f and points endptr to the first character after the 'NAN' sequence.]*/
    else if (isNaN((const char**)endptr))
    {
        result = FST_NAN;
    }
    else if (IN_BASE_RANGE(DIGIT_VAL(**endptr), 10))
    {
        result = FST_NUMBER;
        startptr = *endptr;
        /* integers will go to the fraction and exponential. */
        ullInteger = strtoull_s(startptr, endptr, 10);
        integerSize = (int)((*endptr) - startptr);
        if ((ullInteger == ULLONG_MAX) && (errno != 0))
        {
            result = FST_OVERFLOW;
        }

        /* get the real fraction part, if exist. */
        if ((**endptr) == '.')
        {
            startptr = (*endptr) + 1;
            ullFraction = strtoull_s(startptr, endptr, 10);
            fractionSize = (int)((*endptr) - startptr);
            if ((ullFraction == ULLONG_MAX) && (errno != 0))
            {
                result = FST_OVERFLOW;
            }
        }

        if (((**endptr) == 'e') || ((**endptr) == 'E'))
        {
            startptr = (*endptr) + 1;
            (*exponential) = (int)strtol(startptr, endptr, 10);
            if (((*exponential) < (DBL_MAX_10_EXP * (-1))) || ((*exponential) > DBL_MAX_10_EXP))
            {
                result = FST_OVERFLOW;
            }
        }
        else
        {
            (*exponential) = 0;
        }

        if (result == FST_NUMBER)
        {
            /* Add ullInteger to ullFraction. */
            ullFraction += (ullInteger * (unsigned long long)(pow(10, (double)fractionSize)));
            (*fraction) = ((double)ullFraction / (pow(10.0f, ((double)fractionSize + (double)integerSize - 1.00))));

            /* Unify rest of integerSize and fractionSize in the exponential. */
            (*exponential) += integerSize - 1;
        }
    }

    return result;
}