github.com/afumu/libc@v0.0.6/musl/src/internal/intscan.c (about)

     1  #include <limits.h>
     2  #include <errno.h>
     3  #include <ctype.h>
     4  #include "shgetc.h"
     5  
     6  /* Lookup table for digit values. -1==255>=36 -> invalid */
     7  static const unsigned char table[] = { -1,
     8  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
     9  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
    10  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
    11   0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1,
    12  -1,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,
    13  25,26,27,28,29,30,31,32,33,34,35,-1,-1,-1,-1,-1,
    14  -1,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,
    15  25,26,27,28,29,30,31,32,33,34,35,-1,-1,-1,-1,-1,
    16  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
    17  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
    18  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
    19  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
    20  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
    21  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
    22  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
    23  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
    24  };
    25  
    26  unsigned long long __intscan(FILE *f, unsigned base, int pok, unsigned long long lim)
    27  {
    28  	const unsigned char *val = table+1;
    29  	int c, neg=0;
    30  	unsigned x;
    31  	unsigned long long y;
    32  	if (base > 36 || base == 1) {
    33  		errno = EINVAL;
    34  		return 0;
    35  	}
    36  	while (isspace((c=shgetc(f))));
    37  	if (c=='+' || c=='-') {
    38  		neg = -(c=='-');
    39  		c = shgetc(f);
    40  	}
    41  	if ((base == 0 || base == 16) && c=='0') {
    42  		c = shgetc(f);
    43  		if ((c|32)=='x') {
    44  			c = shgetc(f);
    45  			if (val[c]>=16) {
    46  				shunget(f);
    47  				if (pok) shunget(f);
    48  				else shlim(f, 0);
    49  				return 0;
    50  			}
    51  			base = 16;
    52  		} else if (base == 0) {
    53  			base = 8;
    54  		}
    55  	} else {
    56  		if (base == 0) base = 10;
    57  		if (val[c] >= base) {
    58  			shunget(f);
    59  			shlim(f, 0);
    60  			errno = EINVAL;
    61  			return 0;
    62  		}
    63  	}
    64  	if (base == 10) {
    65  		for (x=0; c-'0'<10U && x<=UINT_MAX/10-1; c=shgetc(f))
    66  			x = x*10 + (c-'0');
    67  		for (y=x; c-'0'<10U && y<=ULLONG_MAX/10 && 10*y<=ULLONG_MAX-(c-'0'); c=shgetc(f))
    68  			y = y*10 + (c-'0');
    69  		if (c-'0'>=10U) goto done;
    70  	} else if (!(base & base-1)) {
    71  		int bs = "\0\1\2\4\7\3\6\5"[(0x17*base)>>5&7];
    72  		for (x=0; val[c]<base && x<=UINT_MAX/32; c=shgetc(f))
    73  			x = x<<bs | val[c];
    74  		for (y=x; val[c]<base && y<=ULLONG_MAX>>bs; c=shgetc(f))
    75  			y = y<<bs | val[c];
    76  	} else {
    77  		for (x=0; val[c]<base && x<=UINT_MAX/36-1; c=shgetc(f))
    78  			x = x*base + val[c];
    79  		for (y=x; val[c]<base && y<=ULLONG_MAX/base && base*y<=ULLONG_MAX-val[c]; c=shgetc(f))
    80  			y = y*base + val[c];
    81  	}
    82  	if (val[c]<base) {
    83  		for (; val[c]<base; c=shgetc(f));
    84  		errno = ERANGE;
    85  		y = lim;
    86  		if (lim&1) neg = 0;
    87  	}
    88  done:
    89  	shunget(f);
    90  	if (y>=lim) {
    91  		if (!(lim&1) && !neg) {
    92  			errno = ERANGE;
    93  			return lim-1;
    94  		} else if (y>lim) {
    95  			errno = ERANGE;
    96  			return lim;
    97  		}
    98  	}
    99  	return (y^neg)-neg;
   100  }