unsigned long long strtoull_s()

in src/crt_abstractions.c [307:406]


unsigned long long strtoull_s(const char* nptr, char** endptr, int base)
{
    unsigned long long result = 0ULL;
    bool validStr = true;
    char* runner = (char*)nptr;
    bool isNegative = false;
    int digitVal;

    /*Codes_SRS_CRT_ABSTRACTIONS_21_005: [The strtoull_s must convert number using base 2 to 36.]*/
    /*Codes_SRS_CRT_ABSTRACTIONS_21_012: [If the subject sequence is empty or does not have the expected form, the strtoull_s must not perform any conversion; the value of nptr is stored in the object pointed to by endptr, provided that endptr is not a NULL pointer.]*/
    /*Codes_SRS_CRT_ABSTRACTIONS_21_013: [If no conversion could be performed, the strtoull_s returns the value 0L.]*/
    /*Codes_SRS_CRT_ABSTRACTIONS_21_035: [If the nptr is NULL, the strtoull_s must **not** perform any conversion and must returns 0L; endptr must receive NULL, provided that endptr is not a NULL pointer.]*/
        if (((base >= 2) || (base == 0)) && (base <= 36) && (runner != NULL))
    {
        /*Codes_SRS_CRT_ABSTRACTIONS_21_011: [The valid sequence starts after the first non-white-space character, followed by an optional positive or negative sign, a number or a letter(depending of the base).]*/
        /*Codes_SRS_CRT_ABSTRACTIONS_21_010: [The white-space must be one of the characters ' ', '\f', '\n', '\r', '\t', '\v'.]*/
        while (IS_SPACE(*runner))
        {
            runner++;
        }
        if ((*runner) == '+')
        {
            runner++;
        }
        else if ((*runner) == '-')
        {
            /*Codes_SRS_CRT_ABSTRACTIONS_21_038: [If the subject sequence starts with a negative sign, the strtoull_s will convert it to the posive representation of the negative value.]*/
            isNegative = true;
            runner++;
        }

        if ((*runner) == '0')
        {
            if ((*(runner+1) == 'x') || (*(runner+1) == 'X'))
            {
                /*Codes_SRS_CRT_ABSTRACTIONS_21_008: [If the base is 0 and '0x' or '0X' precedes the number, strtoull_s must convert to a hexadecimal (base 16).]*/
                /* hexadecimal... */
                if ((base == 0) || (base == 16))
                {
                    base = 16;
                    runner += 2;
                }
            }
            else if((base == 0) || (base == 8))
            {
                /*Codes_SRS_CRT_ABSTRACTIONS_21_009: [If the base is 0 and '0' precedes the number, strtoull_s must convert to an octal (base 8).]*/
                /* octal... */
                base = 8;
                runner++;
            }
        }

        if(base == 0)
        {
            /*Codes_SRS_CRT_ABSTRACTIONS_21_007: [If the base is 0 and no special chars precedes the number, strtoull_s must convert to a decimal (base 10).]*/
            /* decimal... */
            base = 10;
        }

        digitVal = DIGIT_VAL(*runner);
        if (validStr && IN_BASE_RANGE(digitVal, base))
        {
            errno = 0;
            do
            {
                if (((ULLONG_MAX - digitVal) / base) < result)
                {
                    /*Codes_SRS_CRT_ABSTRACTIONS_21_014: [If the correct value is outside the range, the strtoull_s returns the value ULLONG_MAX, and errno will receive the value ERANGE.]*/
                    /* overflow... */
                    result = ULLONG_MAX;
                    errno = ERANGE;
                }
                else
                {
                    result = result * base + digitVal;
                }
                runner++;
                digitVal = DIGIT_VAL(*runner);
            } while (IN_BASE_RANGE(digitVal, base));
        }
        else
        {
            runner = (char*)nptr;
        }
    }

    /*Codes_SRS_CRT_ABSTRACTIONS_21_004: [The strtoull_s must return in endptr a final string of one or more unrecognized characters, including the terminating null character of the input string.]*/
    if (endptr != NULL)
    {
        (*endptr) = (char*)runner;
    }

    /*Codes_SRS_CRT_ABSTRACTIONS_21_038: [If the subject sequence starts with a negative sign, the strtoull_s will convert it to the posive representation of the negative value.]*/
    if (isNegative)
    {
        result = ULLONG_MAX - result + 1;
    }

    return result;
}