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