chiark / gitweb /
volume_id: provide libvolume_id.a file
[elogind.git] / klibc / klibc / strntoumax.c
1 /*
2  * strntoumax.c
3  *
4  * The strntoumax() function and associated
5  */
6
7 #include <stddef.h>
8 #include <stdint.h>
9 #include <ctype.h>
10
11 static inline int digitval(int ch)
12 {
13   if ( ch >= '0' && ch <= '9' ) {
14     return ch-'0';
15   } else if ( ch >= 'A' && ch <= 'Z' ) {
16     return ch-'A'+10;
17   } else if ( ch >= 'a' && ch <= 'z' ) {
18     return ch-'a'+10;
19   } else {
20     return -1;
21   }
22 }
23
24 uintmax_t strntoumax(const char *nptr, char **endptr, int base, size_t n)
25 {
26   int minus = 0;
27   uintmax_t v = 0;
28   int d;
29
30   while ( n && isspace((unsigned char)*nptr) ) {
31     nptr++;
32     n--;
33   }
34
35   /* Single optional + or - */
36   if ( n ) {
37     char c = *nptr;
38     if ( c == '-' || c == '+' ) {
39       minus = (c == '-');
40       nptr++;
41       n--;
42     }
43   }
44
45   if ( base == 0 ) {
46     if ( n >= 2 && nptr[0] == '0' &&
47          (nptr[1] == 'x' || nptr[1] == 'X') ) {
48       n -= 2;
49       nptr += 2;
50       base = 16;
51     } else if ( n >= 1 && nptr[0] == '0' ) {
52       n--;
53       nptr++;
54       base = 8;
55     } else {
56       base = 10;
57     }
58   } else if ( base == 16 ) {
59     if ( n >= 2 && nptr[0] == '0' &&
60          (nptr[1] == 'x' || nptr[1] == 'X') ) {
61       n -= 2;
62       nptr += 2;
63     }
64   }
65
66   while ( n && (d = digitval(*nptr)) >= 0 && d < base ) {
67     v = v*base + d;
68     n--;
69     nptr++;
70   }
71
72   if ( endptr )
73     *endptr = (char *)nptr;
74
75   return minus ? -v : v;
76 }