strto_l_ul.c 1.64 KB
/* simple replacement of strtol */
#include <stdlib.h>
#include <limits.h>

long long int internal_strtol(const char *nptr, char **endptr, int base)
{
  long long int res = 0;
  long int dig;
  int sign = 0;
  do {
  /* skip spaces (isspace) */
    while (*nptr==' ' || *nptr=='\t' || *nptr=='\n' ||
           *nptr=='\v' || *nptr=='\f' || *nptr=='\r') {
      nptr++;
    }
    if (*nptr==0) break;

  /* test sign */
    if (*nptr=='-' || *nptr=='+') {
      if (*nptr=='-') sign = 1;
      nptr++;
    }
    if (*nptr==0) break;

  /* select base if base was 0 */
    if (base==0 && *nptr=='0') {
      nptr++;
      if (*nptr==0) break;
      if (*nptr=='b') base = 2;
      else if (*nptr=='x') base = 16;
      else base = 8;
    }
    if (base==0) base = 10;
  /* read digits in the loop */
    do {
      if (*nptr==0) break;
      if (*nptr>='0' && *nptr<='9')
        dig = *nptr-'0';
      else if (*nptr>='A' && *nptr<='Z')
        dig = *nptr - 'A' + 10;
      else if (*nptr>='a' && *nptr<='z')
        dig = *nptr - 'a' + 10;
      else
        break;
      if (dig<0 || dig>=base) break;
      res = res*base + dig;
      nptr++;
    } while(1);

  } while(0);
  if (endptr) *endptr = (char *)nptr;
  if (sign) res = -res;
  return res;
}


long int strtol(const char *nptr, char **endptr, int base)
{
  long long ir = internal_strtol(nptr, endptr, base);
  if (ir<LONG_MIN) return LONG_MIN;
  if (ir>LONG_MAX) return LONG_MAX;
  return (long)ir;
}

unsigned long int strtoul(const char *nptr, char **endptr, int base)
{
  long long ir = internal_strtol(nptr, endptr, base);
  if (ir<0) return 0;
  if (ir>ULONG_MAX) return ULONG_MAX;
  return (unsigned long) ir;
}