diff --git a/scan/scan_8long.c b/scan/scan_8long.c index 14136c8..72078b2 100644 --- a/scan/scan_8long.c +++ b/scan/scan_8long.c @@ -1,13 +1,5 @@ #include "scan.h" size_t scan_8long(const char *src,unsigned long *dest) { - register const char *tmp=src; - register unsigned long l=0; - register unsigned char c; - while ((c=*tmp-'0')<8) { - l=l*8+c; - ++tmp; - } - *dest=l; - return tmp-src; + return scan_8longn(src,-1,dest); } diff --git a/scan/scan_long.c b/scan/scan_long.c index 05801a9..5efcbfe 100644 --- a/scan/scan_long.c +++ b/scan/scan_long.c @@ -1,21 +1,5 @@ #include "scan.h" size_t scan_long(const char *src,long *dest) { - register const char *tmp; - register long int l; - register unsigned char c; - int neg; - int ok; - tmp=src; l=0; ok=neg=0; - switch (*tmp) { - case '-': neg=1; - case '+': ++tmp; - } - while ((c=*tmp-'0')<10) { - l=l*10+c; - ++tmp; - ok=1; - } - if (ok) *dest=(neg?-l:l); - return tmp-src; + return scan_longn(src,-1,dest); } diff --git a/scan/scan_netstring.c b/scan/scan_netstring.c new file mode 100644 index 0000000..22ffbb3 --- /dev/null +++ b/scan/scan_netstring.c @@ -0,0 +1,25 @@ +#include "scan.h" + +/* parse a netstring, input buffer is in (len bytes). + * if parsing is successful: + * *dest points to string and *slen is size of string + * return number of bytes parsed + * else + * return 0 + * Note: *dest will point inside the input buffer! + */ +size_t scan_netstring(const char* in,size_t len,char** dest,size_t* slen) { + // [len]":"[string]"," + // 3:foo,3:bar,4:fini, + unsigned long l; + size_t n=scan_ulongn(in,len,&l); + if (!n || /* did not start with a number */ + n+2+llen || /* longer than we have input data */ + in[n]!=':' || /* syntax error */ + in[n+l+1]!=',') + return 0; + *dest=(char*)in+n+1; + *slen=n; + return n+2+l; +} diff --git a/scan/scan_ulong.c b/scan/scan_ulong.c index b312c52..9323d35 100644 --- a/scan/scan_ulong.c +++ b/scan/scan_ulong.c @@ -1,19 +1,5 @@ #include "scan.h" size_t scan_ulong(const char* src,unsigned long int* dest) { - register const char *tmp=src; - register unsigned long int l=0; - register unsigned char c; - while ((c=*tmp-'0')<10) { - unsigned long int n; - /* division is very slow on most architectures */ - n=l<<3; if ((n>>3)!=l) break; - if (n+(l<<1) < n) break; - n+=l<<1; - if (n+c < n) break; - l=n+c; - ++tmp; - } - if (tmp-src) *dest=l; - return tmp-src; + return scan_ulongn(src,(size_t)-1,dest); } diff --git a/scan/scan_xlong.c b/scan/scan_xlong.c index cca6d47..b0e9e05 100644 --- a/scan/scan_xlong.c +++ b/scan/scan_xlong.c @@ -1,13 +1,5 @@ #include "scan.h" size_t scan_xlong(const char *src,unsigned long *dest) { - register const char *tmp=src; - register unsigned long l=0; - register unsigned char c; - while ((c=scan_fromhex(*tmp))<16) { - l=(l<<4)+c; - ++tmp; - } - *dest=l; - return tmp-src; + return scan_xlongn(src,(size_t)-1,dest); } diff --git a/test/scan_long.c b/test/scan_long.c index f13bf5c..5cde77a 100644 --- a/test/scan_long.c +++ b/test/scan_long.c @@ -6,6 +6,14 @@ int main() { char buf[1024]; unsigned long long int i; + unsigned long l; + if (sizeof(unsigned long)==4) { + assert(scan_ulong("4294967295",&l) == 10 && l==4294967295ul); + assert(scan_ulong("4294967296",&l) == 9 && l==429496729); + } else { + assert(scan_ulong("18446744073709551615",&l) == 20 && l==18446744073709551615ull); + assert(scan_ulong("18446744073709551616",&l) == 19 && l==1844674407370955161ull); + } if (sizeof(unsigned long) != 4) return 0; for (i=1; i<0xfffffffffull; i+=i+1) { diff --git a/test/scan_netstring.c b/test/scan_netstring.c new file mode 100644 index 0000000..ac10e3b --- /dev/null +++ b/test/scan_netstring.c @@ -0,0 +1,11 @@ +#include "scan.h" +#include + +int main() { + char* s; + size_t l; + const char* orig; + orig="3:foo,"; assert(scan_netstring(orig,6,&s,&l)==6); assert(s==orig+2); + orig="4294967295:foo,"; assert(scan_netstring(orig,15,&s,&l)==0); + orig="18446744073709551615:foo,"; assert(scan_netstring(orig,25,&s,&l)==0); +}