Home | History | Annotate | Download | only in wcstox
      1 // ----------------------------------------------------------------------
      2 // Copyright  2005-2014 Rich Felker, et al.
      3 // Copyright 2014 The Android Open Source Project.
      4 //
      5 // Permission is hereby granted, free of charge, to any person obtaining
      6 // a copy of this software and associated documentation files (the
      7 // "Software"), to deal in the Software without restriction, including
      8 // without limitation the rights to use, copy, modify, merge, publish,
      9 // distribute, sublicense, and/or sell copies of the Software, and to
     10 // permit persons to whom the Software is furnished to do so, subject to
     11 // the following conditions:
     12 //
     13 // The above copyright notice and this permission notice shall be
     14 // included in all copies or substantial portions of the Software.
     15 //
     16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     17 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     18 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     19 // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
     20 // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     21 // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     22 // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     23 // ----------------------------------------------------------------------
     24 
     25 #include <limits.h>
     26 #include <errno.h>
     27 #include <ctype.h>
     28 #include "shgetc.h"
     29 
     30 // ANDROID: Redefine FILE to use our custom stream abstraction.
     31 #undef FILE
     32 #define FILE struct fake_file_t
     33 
     34 /* Lookup table for digit values. -1==255>=36 -> invalid */
     35 static const unsigned char table[] = { -1,
     36 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
     37 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
     38 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
     39  0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1,
     40 -1,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,
     41 25,26,27,28,29,30,31,32,33,34,35,-1,-1,-1,-1,-1,
     42 -1,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,
     43 25,26,27,28,29,30,31,32,33,34,35,-1,-1,-1,-1,-1,
     44 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
     45 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
     46 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
     47 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
     48 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
     49 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
     50 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
     51 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
     52 };
     53 
     54 unsigned long long __intscan(FILE *f, unsigned base, int pok, unsigned long long lim)
     55 {
     56 	const unsigned char *val = table+1;
     57 	int c, neg=0;
     58 	unsigned x;
     59 	unsigned long long y;
     60 	if (base > 36) {
     61 		errno = EINVAL;
     62 		return 0;
     63 	}
     64 	while (isspace((c=shgetc(f))));
     65 	if (c=='+' || c=='-') {
     66 		neg = -(c=='-');
     67 		c = shgetc(f);
     68 	}
     69 	if ((base == 0 || base == 16) && c=='0') {
     70 		c = shgetc(f);
     71 		if ((c|32)=='x') {
     72 			c = shgetc(f);
     73 			if (val[c]>=16) {
     74 				shunget(f);
     75 				if (pok) shunget(f);
     76 				else shlim(f, 0);
     77 				return 0;
     78 			}
     79 			base = 16;
     80 		} else if (base == 0) {
     81 			base = 8;
     82 		}
     83 	} else {
     84 		if (base == 0) base = 10;
     85 		if (val[c] >= base) {
     86 			shunget(f);
     87 			shlim(f, 0);
     88 			errno = EINVAL;
     89 			return 0;
     90 		}
     91 	}
     92 	if (base == 10) {
     93 		for (x=0; c-'0'<10U && x<=UINT_MAX/10-1; c=shgetc(f))
     94 			x = x*10 + (c-'0');
     95 		for (y=x; c-'0'<10U && y<=ULLONG_MAX/10 && 10*y<=ULLONG_MAX-(c-'0'); c=shgetc(f))
     96 			y = y*10 + (c-'0');
     97 		if (c-'0'>=10U) goto done;
     98 	} else if (!(base & base-1)) {
     99 		int bs = "\0\1\2\4\7\3\6\5"[(0x17*base)>>5&7];
    100 		for (x=0; val[c]<base && x<=UINT_MAX/32; c=shgetc(f))
    101 			x = x<<bs | val[c];
    102 		for (y=x; val[c]<base && y<=ULLONG_MAX>>bs; c=shgetc(f))
    103 			y = y<<bs | val[c];
    104 	} else {
    105 		for (x=0; val[c]<base && x<=UINT_MAX/36-1; c=shgetc(f))
    106 			x = x*base + val[c];
    107 		for (y=x; val[c]<base && y<=ULLONG_MAX/base && base*y<=ULLONG_MAX-val[c]; c=shgetc(f))
    108 			y = y*base + val[c];
    109 	}
    110 	if (val[c]<base) {
    111 		for (; val[c]<base; c=shgetc(f));
    112 		errno = ERANGE;
    113 		y = lim;
    114 	}
    115 done:
    116 	shunget(f);
    117 	if (y>=lim) {
    118 		if (!(lim&1) && !neg) {
    119 			errno = ERANGE;
    120 			return lim-1;
    121 		} else if (y>lim) {
    122 			errno = ERANGE;
    123 			return lim;
    124 		}
    125 	}
    126 	return (y^neg)-neg;
    127 }
    128