xref: /inferno-os/libkern/strtoull.c (revision 8a8c2d742b51525f66c2210e3c8a251de10022ff)
1*8a8c2d74SCharles.Forsyth #include <lib9.h>
2*8a8c2d74SCharles.Forsyth 
3*8a8c2d74SCharles.Forsyth #define UVLONG_MAX	(1LL<<63)
4*8a8c2d74SCharles.Forsyth 
5*8a8c2d74SCharles.Forsyth uvlong
strtoull(char * nptr,char ** endptr,int base)6*8a8c2d74SCharles.Forsyth strtoull(char *nptr, char **endptr, int base)
7*8a8c2d74SCharles.Forsyth {
8*8a8c2d74SCharles.Forsyth 	char *p;
9*8a8c2d74SCharles.Forsyth 	uvlong n, nn, m;
10*8a8c2d74SCharles.Forsyth 	int c, ovfl, v, neg, ndig;
11*8a8c2d74SCharles.Forsyth 
12*8a8c2d74SCharles.Forsyth 	p = nptr;
13*8a8c2d74SCharles.Forsyth 	neg = 0;
14*8a8c2d74SCharles.Forsyth 	n = 0;
15*8a8c2d74SCharles.Forsyth 	ndig = 0;
16*8a8c2d74SCharles.Forsyth 	ovfl = 0;
17*8a8c2d74SCharles.Forsyth 
18*8a8c2d74SCharles.Forsyth 	/*
19*8a8c2d74SCharles.Forsyth 	 * White space
20*8a8c2d74SCharles.Forsyth 	 */
21*8a8c2d74SCharles.Forsyth 	for(;; p++) {
22*8a8c2d74SCharles.Forsyth 		switch(*p) {
23*8a8c2d74SCharles.Forsyth 		case ' ':
24*8a8c2d74SCharles.Forsyth 		case '\t':
25*8a8c2d74SCharles.Forsyth 		case '\n':
26*8a8c2d74SCharles.Forsyth 		case '\f':
27*8a8c2d74SCharles.Forsyth 		case '\r':
28*8a8c2d74SCharles.Forsyth 		case '\v':
29*8a8c2d74SCharles.Forsyth 			continue;
30*8a8c2d74SCharles.Forsyth 		}
31*8a8c2d74SCharles.Forsyth 		break;
32*8a8c2d74SCharles.Forsyth 	}
33*8a8c2d74SCharles.Forsyth 
34*8a8c2d74SCharles.Forsyth 	/*
35*8a8c2d74SCharles.Forsyth 	 * Sign
36*8a8c2d74SCharles.Forsyth 	 */
37*8a8c2d74SCharles.Forsyth 	if(*p == '-' || *p == '+')
38*8a8c2d74SCharles.Forsyth 		if(*p++ == '-')
39*8a8c2d74SCharles.Forsyth 			neg = 1;
40*8a8c2d74SCharles.Forsyth 
41*8a8c2d74SCharles.Forsyth 	/*
42*8a8c2d74SCharles.Forsyth 	 * Base
43*8a8c2d74SCharles.Forsyth 	 */
44*8a8c2d74SCharles.Forsyth 	if(base == 0) {
45*8a8c2d74SCharles.Forsyth 		base = 10;
46*8a8c2d74SCharles.Forsyth 		if(*p == '0') {
47*8a8c2d74SCharles.Forsyth 			base = 8;
48*8a8c2d74SCharles.Forsyth 			if(p[1] == 'x' || p[1] == 'X'){
49*8a8c2d74SCharles.Forsyth 				p += 2;
50*8a8c2d74SCharles.Forsyth 				base = 16;
51*8a8c2d74SCharles.Forsyth 			}
52*8a8c2d74SCharles.Forsyth 		}
53*8a8c2d74SCharles.Forsyth 	} else
54*8a8c2d74SCharles.Forsyth 	if(base == 16 && *p == '0') {
55*8a8c2d74SCharles.Forsyth 		if(p[1] == 'x' || p[1] == 'X')
56*8a8c2d74SCharles.Forsyth 			p += 2;
57*8a8c2d74SCharles.Forsyth 	} else
58*8a8c2d74SCharles.Forsyth 	if(base < 0 || 36 < base)
59*8a8c2d74SCharles.Forsyth 		goto Return;
60*8a8c2d74SCharles.Forsyth 
61*8a8c2d74SCharles.Forsyth 	/*
62*8a8c2d74SCharles.Forsyth 	 * Non-empty sequence of digits
63*8a8c2d74SCharles.Forsyth 	 */
64*8a8c2d74SCharles.Forsyth 	m = UVLONG_MAX/base;
65*8a8c2d74SCharles.Forsyth 	for(;; p++,ndig++) {
66*8a8c2d74SCharles.Forsyth 		c = *p;
67*8a8c2d74SCharles.Forsyth 		v = base;
68*8a8c2d74SCharles.Forsyth 		if('0' <= c && c <= '9')
69*8a8c2d74SCharles.Forsyth 			v = c - '0';
70*8a8c2d74SCharles.Forsyth 		else
71*8a8c2d74SCharles.Forsyth 		if('a' <= c && c <= 'z')
72*8a8c2d74SCharles.Forsyth 			v = c - 'a' + 10;
73*8a8c2d74SCharles.Forsyth 		else
74*8a8c2d74SCharles.Forsyth 		if('A' <= c && c <= 'Z')
75*8a8c2d74SCharles.Forsyth 			v = c - 'A' + 10;
76*8a8c2d74SCharles.Forsyth 		if(v >= base)
77*8a8c2d74SCharles.Forsyth 			break;
78*8a8c2d74SCharles.Forsyth 		if(n > m)
79*8a8c2d74SCharles.Forsyth 			ovfl = 1;
80*8a8c2d74SCharles.Forsyth 		nn = n*base + v;
81*8a8c2d74SCharles.Forsyth 		if(nn < n)
82*8a8c2d74SCharles.Forsyth 			ovfl = 1;
83*8a8c2d74SCharles.Forsyth 		n = nn;
84*8a8c2d74SCharles.Forsyth 	}
85*8a8c2d74SCharles.Forsyth 
86*8a8c2d74SCharles.Forsyth Return:
87*8a8c2d74SCharles.Forsyth 	if(ndig == 0)
88*8a8c2d74SCharles.Forsyth 		p = nptr;
89*8a8c2d74SCharles.Forsyth 	if(endptr)
90*8a8c2d74SCharles.Forsyth 		*endptr = p;
91*8a8c2d74SCharles.Forsyth 	if(ovfl)
92*8a8c2d74SCharles.Forsyth 		return UVLONG_MAX;
93*8a8c2d74SCharles.Forsyth 	if(neg)
94*8a8c2d74SCharles.Forsyth 		return -n;
95*8a8c2d74SCharles.Forsyth 	return n;
96*8a8c2d74SCharles.Forsyth }
97