/*
 * Original source code from PSXSDK, by Giuseppe Gata.
 * Released under a weak copyleft-like license, pasted below:
 *
 * You can use this library for any project, commercial and non-commercial,
 * open-source and closed-source. But if you modify the library, you must
 * redistribute the source for the modifications you did to it.
 * Not doing that constitutes an infringement of this license.
 * You are not obliged to redistribute the source code of this library if it
 * was not modified at all by you or anyone related to you.
 *
 * There is no advertising clause; you aren't obliged to mention this library
 * in any documentation of your work using it; however, it would be a nice gesture
 * if you did so.
 *
 * These terms were written to not make people close this work which was released
 * for all to share. In fact, no use is otherwise restricted.
 */

#include <stdlib.h>
#include <ctype.h>
#include <errno.h>
#include <limits.h>

unsigned long long strtoull(const char *nptr, char **endptr, int base)
{
    int r = 0;
    int t = 0;
    int n = 0;

    while(*nptr && isspace(*nptr))
        nptr++;

    if(*nptr == '0')
    {
        if(*(nptr+1) == 'x' || *(nptr+1) == 'X')
        {
            if(base != 0 && base != 16)
            {
                errno = EINVAL;
                return 0;
            }

            base = 16;
            nptr+=2;
        }
        else if(base != 0 && base != 8)
        {
            errno = EINVAL;
            return 0;
        }
        else
            base = 8;
    }
    else if (base == 0)
        base = 10;

    if(base < 2 || base > 36)
    {
        errno = EINVAL;
        return 0;
    }

    while(*nptr)
    {
        if (*nptr >= '0' && *nptr <= '9')
            t = *nptr - '0';
        else if (*nptr >= 'a' && *nptr <= 'z')
            t = (*nptr - 'a') + 10;
        else if (*nptr >= 'A' && *nptr <= 'Z')
            t = (*nptr - 'A') + 10;
        else
            t = 1000;

        if(t>=base)
            break;

        r*=base;
        r+=t;
        nptr++;
    }

    if(endptr)*endptr = (char*)nptr;
    return n?-r:r;
}
