chiark / gitweb /
[PATCH] added vsyslog support to klibc.
[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 && *nptr == '-' ) {
37     minus = 1;
38     nptr++;
39     n--;
40   } else if ( n && *nptr == '+' ) {
41     nptr++;
42   }
43
44   if ( base == 0 ) {
45     if ( n >= 2 && nptr[0] == '0' &&
46          (nptr[1] == 'x' || nptr[1] == 'X') ) {
47       n -= 2;
48       nptr += 2;
49       base = 16;
50     } else if ( n >= 1 && nptr[0] == '0' ) {
51       n--;
52       nptr++;
53       base = 8;
54     } else {
55       base = 10;
56     }
57   } else if ( base == 16 ) {
58     if ( n >= 2 && nptr[0] == '0' &&
59          (nptr[1] == 'x' || nptr[1] == 'X') ) {
60       n -= 2;
61       nptr += 2;
62     }
63   }
64
65   while ( n && (d = digitval(*nptr)) >= 0 && d < base ) {
66     v = v*base + d;
67     n--;
68     nptr++;
69   }
70
71   if ( endptr )
72     *endptr = (char *)nptr;
73
74   return minus ? -v : v;
75 }