Mirror of :pserver:cvs@cvs.fefe.de:/cvs libowfat https://www.fefe.de/libowfat/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

40 lines
1.0 KiB

  1. #include "scan.h"
  2. size_t scan_ulonglong(const char *src,unsigned long long *dest) {
  3. register const char *tmp=src;
  4. register unsigned long long l=0;
  5. register unsigned char c;
  6. while ((c=(unsigned char)(*tmp-'0'))<10) {
  7. unsigned long long n;
  8. #if defined(__GNUC__) && (__GNUC__ >= 5)
  9. if (__builtin_mul_overflow(l,10,&n) || __builtin_add_overflow(n,c,&n))
  10. break;
  11. l=n;
  12. #else
  13. /* division is very slow on most architectures */
  14. n=l<<3; if ((n>>3)!=l) break;
  15. if (n+(l<<1) < n) break;
  16. n+=l<<1;
  17. if (n+c < n) break;
  18. l=n+c;
  19. #endif
  20. ++tmp;
  21. }
  22. if (tmp-src) *dest=l;
  23. return (size_t)(tmp-src);
  24. }
  25. #ifdef UNITTEST
  26. #include <assert.h>
  27. int main() {
  28. unsigned long long l;
  29. assert(scan_ulonglong("0",&l)==1 && l==0);
  30. assert(scan_ulonglong("1",&l)==1 && l==1);
  31. assert(scan_ulonglong("4294967295",&l) == 10 && l==4294967295ull);
  32. assert(scan_ulonglong("18446744073709551615",&l) == 20 && l==18446744073709551615ull);
  33. assert(scan_ulonglong("18446744073709551616",&l) == 19 && l==1844674407370955161ull);
  34. return 0;
  35. }
  36. #endif