summaryrefslogtreecommitdiff
path: root/user/lib/strtox.c
blob: 5f786f13ceada4f32e4ffc4db4d64281f2391a96 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include <stdlib.h>
#include <ctype.h>

#define STRTOX(name, type)                                               \
	type name(const char *restrict s, char **restrict endptr, int radix) \
	{                                                                    \
		const char *s_start = s;                                         \
		for (; isspace(*s); s++)                                         \
			;                                                            \
                                                                         \
		int sign = 0;                                                    \
		switch (*s) {                                                    \
		case '-':                                                        \
			sign = 1; /* fallthrough */                                  \
		case '+':                                                        \
			s++;                                                         \
			break;                                                       \
		}                                                                \
                                                                         \
		if ((radix == 0 || radix == 16) &&                               \
			(s[0] == '0' && (s[1] == 'x' || s[1] == 'X'))) {             \
			radix = 16;                                                  \
			s += 2;                                                      \
		} else if (radix == 0) {                                         \
			if (*s == '0') {                                             \
				radix = 8;                                               \
				s++;                                                     \
			} else {                                                     \
				radix = 10;                                              \
			}                                                            \
		}                                                                \
                                                                         \
		type num = 0;                                                    \
		int has_digit = 0;                                               \
                                                                         \
		while (1) {                                                      \
			int n = ctoi(*s++);                                          \
			if (n < 0 || n >= radix)                                     \
				break;                                                   \
			has_digit = 1;                                               \
			num = num * radix + n;                                       \
		}                                                                \
                                                                         \
		if (endptr != NULL) {                                            \
			*endptr = has_digit ? (char *)(s - 1) : (char *)s_start;     \
		}                                                                \
                                                                         \
		return sign ? -num : num;                                        \
	}

STRTOX(strtoi, int)
STRTOX(strtol, long int)
STRTOX(strtoll, long long int)