blob: 4a6275651274f7e96b39f88304018685e8451475 [file] [log] [blame]
xybc178ea42014-01-14 21:39:05 +08001#if defined(UNIX)
2
3#include <ctype.h>
4#include <errno.h>
xybc178ea42014-01-14 21:39:05 +08005#include <stdlib.h>
xybc178ea42014-01-14 21:39:05 +08006
7#include "misc.h"
Damien George2613ffd2014-02-22 17:49:15 +00008#include "strtonum.h"
xybc178ea42014-01-14 21:39:05 +08009#include "mpconfig.h"
Damien George55baff42014-01-21 21:40:13 +000010#include "qstr.h"
xybc178ea42014-01-14 21:39:05 +080011#include "nlr.h"
12#include "obj.h"
13
Damien George2613ffd2014-02-22 17:49:15 +000014long mp_strtonum(const char *restrict s, int base) {
xybc178ea42014-01-14 21:39:05 +080015 int c, neg = 0;
16 const char *p = s;
17 char *num;
18 long found;
19
20 // check radix base
21 if ((base != 0 && base < 2) || base > 36) {
Damien Georgec5966122014-02-15 16:10:44 +000022 nlr_jump(mp_obj_new_exception_msg(&mp_type_ValueError, "ValueError: int() arg 2 must be >=2 and <= 36"));
xybc178ea42014-01-14 21:39:05 +080023 }
24 // skip surrounded whitespace
25 while (isspace((c = *(p++))));
26 if (c == 0) {
27 goto value_error;
28 }
29 // preced sign
30 if (c == '+' || c == '-') {
31 neg = - (c == '-');
32 c = *(p++);
33 }
34
35 // find real radix base, and strip preced '0x', '0o' and '0b'
Damien George5573f9f2014-01-15 22:58:39 +000036 // TODO somehow merge with similar code in parse.c
xybc178ea42014-01-14 21:39:05 +080037 if ((base == 0 || base == 16) && c == '0') {
38 c = *(p++);
39 if ((c | 32) == 'x') {
40 base = 16;
41 } else if (base == 0 && (c | 32) == 'o') {
42 base = 8;
43 } else if (base == 0 && (c | 32) == 'b') {
44 base = 2;
45 } else {
46 base = 10;
47 p -= 2;
48 }
49 } else if (base == 8 && c == '0') {
xyb3270fb42014-01-15 19:58:11 +080050 c = *(p++);
51 if ((c | 32) != 'o') {
52 p -= 2;
xybc178ea42014-01-14 21:39:05 +080053 }
54 } else if (base == 2 && c == '0') {
xyb3270fb42014-01-15 19:58:11 +080055 c = *(p++);
56 if ((c | 32) != 'b') {
57 p -= 2;
xybc178ea42014-01-14 21:39:05 +080058 }
59 } else {
60 if (base == 0) base = 10;
61 p--;
62 }
63
Damien Georgeb99d9ea2014-01-15 23:08:33 +000064 errno = 0;
xybc178ea42014-01-14 21:39:05 +080065 found = strtol(p, &num, base);
66 if (errno) {
67 goto value_error;
68 } else if (found && *(num) == 0) {
69 goto done;
70 } else if (found || num != p) {
71 goto check_tail_space;
72 } else {
73 goto value_error;
74 }
75
76check_tail_space:
77 if (*(num) != 0) {
78 while (isspace((c = *(num++))));
79 if (c != 0) {
80 goto value_error;
81 }
82 }
83
84done:
85 return (found ^ neg) - neg;
86
87value_error:
Damien Georgec5966122014-02-15 16:10:44 +000088 nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "invalid literal for int() with base %d: '%s'", base, s));
xybc178ea42014-01-14 21:39:05 +080089}
90
xybc178ea42014-01-14 21:39:05 +080091#else /* defined(UNIX) */
92
Damien George2613ffd2014-02-22 17:49:15 +000093long mp_strtonum(const char *restrict s, int base) {
xybc178ea42014-01-14 21:39:05 +080094 // TODO port strtol to stm
95 return 0;
96}
97
98#endif /* defined(UNIX) */