micropython/py/strtonum.c
2014-01-14 21:39:05 +08:00

169 lines
4.8 KiB
C

#if defined(UNIX)
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "misc.h"
#include "mpconfig.h"
#include "mpqstr.h"
#include "nlr.h"
#include "obj.h"
long strtonum(const char *restrict s, int base) {
int c, neg = 0;
const char *p = s;
char *num;
long found;
// check radix base
if ((base != 0 && base < 2) || base > 36) {
printf("ValueError: int() arg 2 must be >=2 and <= 36\n");
return 0;
}
// skip surrounded whitespace
while (isspace((c = *(p++))));
if (c == 0) {
goto value_error;
}
// preced sign
if (c == '+' || c == '-') {
neg = - (c == '-');
c = *(p++);
}
// find real radix base, and strip preced '0x', '0o' and '0b'
if ((base == 0 || base == 16) && c == '0') {
c = *(p++);
if ((c | 32) == 'x') {
base = 16;
} else if (base == 0 && (c | 32) == 'o') {
base = 8;
} else if (base == 0 && (c | 32) == 'b') {
base = 2;
} else {
base = 10;
p -= 2;
}
} else if (base == 8 && c == '0') {
if ((c | 32) == 'o') {
base = 8;
} else {
goto value_error;
}
} else if (base == 2 && c == '0') {
if ((c | 32) == 'b') {
base = 2;
} else {
goto value_error;
}
} else {
if (base == 0) base = 10;
p--;
}
found = strtol(p, &num, base);
if (errno) {
goto value_error;
} else if (found && *(num) == 0) {
goto done;
} else if (found || num != p) {
goto check_tail_space;
} else {
goto value_error;
}
check_tail_space:
if (*(num) != 0) {
while (isspace((c = *(num++))));
if (c != 0) {
goto value_error;
}
}
done:
return (found ^ neg) - neg;
value_error:
nlr_jump(mp_obj_new_exception_msg_2_args(MP_QSTR_ValueError, "invalid literal for int() with base %d: '%s'", (void*)(machine_uint_t)base, s));
//printf("invalid literal for int() with base %d: '%s'\n", base, s);
//return 0;
}
/*
int main(void) {
printf(" 0 %ld\n", strtonum("0", 0));
printf(" 1 %ld\n", strtonum("1", 0));
printf(" 1 %ld\n", strtonum("+1", 0));
printf(" -1 %ld\n", strtonum("-1", 0));
printf(" 0 %ld\n", strtonum("+0", 0));
printf(" 0 %ld\n", strtonum("-0", 0));
printf(" 1 %ld\n", strtonum("01", 0));
printf(" 9 %ld\n", strtonum("9", 0));
printf(" 10 %ld\n", strtonum("10", 0));
printf(" 10 %ld\n", strtonum("+10", 0));
printf("-10 %ld\n", strtonum("-10", 0));
printf(" 12 %ld\n", strtonum("12", 0));
printf("-12 %ld\n", strtonum("-12", 0));
printf(" 99 %ld\n", strtonum("99", 0));
printf("100 %ld\n", strtonum("100", 0));
printf("314 %ld\n", strtonum("314", 0));
printf("314 %ld\n", strtonum(" 314", 0));
printf("314 %ld\n", strtonum("314 ", 0));
printf("314 %ld\n", strtonum(" \t\t 314 \t\t ", 0));
printf(" 1 %ld\n", strtonum(" 1 ", 0));
printf(" -3 %ld\n", strtonum(" -3 ", 0));
printf(" 83 %ld\n", strtonum("0o123", 0));
printf(" 18 %ld\n", strtonum("0x12", 0));
printf(" 10 %ld\n", strtonum("0o12", 0));
printf(" 10 %ld\n", strtonum("0o12", 0));
printf(" 10 %ld\n", strtonum(" \t 0o12", 0));
printf(" 10 %ld\n", strtonum("0o12 \t ", 0));
printf(" 10 %ld\n", strtonum("0O12", 0));
printf(" 5 %ld\n", strtonum("0b101", 0));
printf(" 5 %ld\n", strtonum("0b101", 0));
printf(" 0 %ld\n", strtonum("0", 10));
printf(" 1 %ld\n", strtonum("1", 10));
printf(" 1 %ld\n", strtonum(" \t 1 \t ", 10));
printf(" 11 %ld\n", strtonum("11", 10));
printf(" 17 %ld\n", strtonum("11", 16));
printf(" 9 %ld\n", strtonum("11", 8));
printf(" 3 %ld\n", strtonum("11", 2));
printf(" 37 %ld\n", strtonum("11", 36));
printf("4294967296 %ld\n", strtonum("4294967296", 0));
printf("%ld\n", strtonum("x", 0));
printf("%ld\n", strtonum("1x", 0));
printf("%ld\n", strtonum(" 1x", 0));
printf("%ld\n", strtonum(" 1\02 ", 0));
printf("%ld\n", strtonum("", 0));
printf("%ld\n", strtonum(" ", 0));
printf("%ld\n", strtonum(" \t\t ", 0));
printf("%ld\n", strtonum("0x", 0));
printf("%ld\n", strtonum("0x", 16));
printf("%ld\n", strtonum("0o", 0));
printf("%ld\n", strtonum("0o", 8));
printf("%ld\n", strtonum("0b", 0));
printf("%ld\n", strtonum("0b", 2));
printf("%ld\n", strtonum("0b2", 2));
printf("%ld\n", strtonum("0o8", 8));
printf("%ld\n", strtonum("0xg", 16));
printf("%ld\n", strtonum("1 1", 0));
printf("%ld\n", strtonum("18446744073709551616", 0));
}
*/
#else /* defined(UNIX) */
long strtonum(const char *restrict s, int base) {
// TODO port strtol to stm
return 0;
}
#endif /* defined(UNIX) */