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