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