diff --git a/scan/scan_ulong.c b/scan/scan_ulong.c index 385f98e..e11f564 100644 --- a/scan/scan_ulong.c +++ b/scan/scan_ulong.c @@ -5,9 +5,13 @@ unsigned int scan_ulong(const char* src,unsigned long int* dest) { register unsigned long int l=0; register unsigned char c; while ((c=*tmp-'0')<10) { - unsigned long int m=l; - l=l*10+c; - if ((l>>3) < m) break; + 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; } *dest=l; diff --git a/scan/scan_ulonglong.c b/scan/scan_ulonglong.c index 77e87d1..6d53c58 100644 --- a/scan/scan_ulonglong.c +++ b/scan/scan_ulonglong.c @@ -5,9 +5,13 @@ unsigned int scan_ulonglong(const char *src,unsigned long long *dest) { register unsigned long long l=0; register unsigned char c; while ((c=*tmp-'0')<10) { - unsigned long long m=l; - l=l*10+c; - if ((l>>3) < m) break; + unsigned long long 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; } *dest=l; diff --git a/test/scan.c b/test/scan.c new file mode 100644 index 0000000..10c4614 --- /dev/null +++ b/test/scan.c @@ -0,0 +1,16 @@ +#include +#include +#include "scan.h" + +int main() { + unsigned long l; + char buf[100]; + assert(scan_ulong("12345",&l)==5 && l==12345); + assert(scan_ulong("-12345",&l)==0); + assert(scan_ulong("4294967295",&l)==10 && l==4294967295ul); + if (sizeof(unsigned long)==4) { + assert(scan_ulong("4294967296",&l)==9 && l==429496729); + assert(scan_ulong("42949672950",&l)==10 && l==4294967295ul); + assert(scan_ulong("5294967295",&l)==9 && l==529496729); + } +}