Skip to content
This repository has been archived by the owner on Feb 25, 2018. It is now read-only.

Commit

Permalink
custom parser for integer literals; tighter than strtol
Browse files Browse the repository at this point in the history
  • Loading branch information
rfk committed Apr 4, 2011
1 parent 1e42cab commit 943557e
Showing 1 changed file with 45 additions and 9 deletions.
54 changes: 45 additions & 9 deletions tnetstring/_tnetstring.c
Original file line number Diff line number Diff line change
Expand Up @@ -293,15 +293,14 @@ tns_parse_string(const char *data, size_t len)
static inline int
tns_str_is_float(const char *data, size_t len)
{
size_t i=0;
while(i < len) {
switch(data[i]) {
const char* dend = data + len;
while(data < dend) {
switch(*data++) {
case '.':
case 'e':
case 'E':
return 1;
}
i++;
}
return 0;
}
Expand All @@ -310,21 +309,58 @@ tns_str_is_float(const char *data, size_t len)
static inline void*
tns_parse_number(const char *data, size_t len)
{
double d;
long long l;
double d = 0;
int neg = 0;
long l = 0;
char c;
char *dataend;
const char *pos, *eod;
if(tns_str_is_float(data, len)) {
// Technically this allows whitespace around the float, which
// isn't valid in a tnetstring. But I don't want to waste the
// time checking and I am *not* reimplementing strtod.
d = strtod(data, &dataend);
if(dataend != data + len) {
return NULL;
}
return PyFloat_FromDouble(d);
} else {
l = strtoll(data, &dataend, 10);
if(dataend != data + len) {
// We need tighter error-checking than strtol gives us.
pos = data;
eod = data + len;
c = *pos++;
switch(c) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
l = c - '0';
break;
case '+':
break;
case '-':
neg = 1;
break;
default:
return NULL;
}
return PyLong_FromLongLong(l);
while(pos < eod) {
c = *pos++;
if(c < '0' || c > '9') {
return NULL;
}
l = (l * 10) + (c - '0');
}
if(neg) {
l = -1* l;
}
return PyLong_FromLong(l);
}
return NULL;
}
Expand Down

0 comments on commit 943557e

Please sign in to comment.