xref: /DragonStub/apps/lib/string.c (revision 3e6106c4d60a23aae3c0740979c5e6fb728b63c3)
1 
2 #include <dragonstub/dragonstub.h>
3 
4 char *skip_spaces(const char *str)
5 {
6 	while (isspace(*str))
7 		++str;
8 	return (char *)str;
9 }
10 
11 unsigned int atou(const char *s)
12 {
13 	unsigned int i = 0;
14 	while (isdigit(*s))
15 		i = i * 10 + (*s++ - '0');
16 	return i;
17 }
18 
19 /* Works only for digits and letters, but small and fast */
20 #define TOLOWER(x) ((x) | 0x20)
21 
22 static unsigned int simple_guess_base(const char *cp)
23 {
24 	if (cp[0] == '0') {
25 		if (TOLOWER(cp[1]) == 'x' && isxdigit(cp[2]))
26 			return 16;
27 		else
28 			return 8;
29 	} else {
30 		return 10;
31 	}
32 }
33 
34 /**
35  * strlen - Find the length of a string
36  * @s: The string to be sized
37  */
38 size_t strlen(const char *s)
39 {
40 	const char *sc;
41 
42 	for (sc = s; *sc != '\0'; ++sc)
43 		/* nothing */;
44 	return sc - s;
45 }
46 
47 /**
48  * simple_strtoull - convert a string to an unsigned long long
49  * @cp: The start of the string
50  * @endp: A pointer to the end of the parsed string will be placed here
51  * @base: The number base to use
52  */
53 unsigned long long simple_strtoull(const char *cp, char **endp,
54 				   unsigned int base)
55 {
56 	unsigned long long result = 0;
57 
58 	if (!base)
59 		base = simple_guess_base(cp);
60 
61 	if (base == 16 && cp[0] == '0' && TOLOWER(cp[1]) == 'x')
62 		cp += 2;
63 
64 	while (isxdigit(*cp)) {
65 		unsigned int value;
66 
67 		value = isdigit(*cp) ? *cp - '0' : TOLOWER(*cp) - 'a' + 10;
68 		if (value >= base)
69 			break;
70 		result = result * base + value;
71 		cp++;
72 	}
73 	if (endp)
74 		*endp = (char *)cp;
75 
76 	return result;
77 }
78 
79 long simple_strtol(const char *cp, char **endp, unsigned int base)
80 {
81 	if (*cp == '-')
82 		return -simple_strtoull(cp + 1, endp, base);
83 
84 	return simple_strtoull(cp, endp, base);
85 }
86 
87 int strcmp(const char *str1, const char *str2)
88 {
89 	const unsigned char *s1 = (const unsigned char *)str1;
90 	const unsigned char *s2 = (const unsigned char *)str2;
91 	int delta = 0;
92 
93 	while (*s1 || *s2) {
94 		delta = *s1 - *s2;
95 		if (delta)
96 			return delta;
97 		s1++;
98 		s2++;
99 	}
100 	return 0;
101 }
102 
103 int strncmp(const char *cs, const char *ct, size_t count)
104 {
105 	unsigned char c1, c2;
106 
107 	while (count) {
108 		c1 = *cs++;
109 		c2 = *ct++;
110 		if (c1 != c2)
111 			return c1 < c2 ? -1 : 1;
112 		if (!c1)
113 			break;
114 		count--;
115 	}
116 	return 0;
117 }
118 
119 size_t strnlen(const char *s, size_t maxlen)
120 {
121 	const char *es = s;
122 	while (*es && maxlen) {
123 		es++;
124 		maxlen--;
125 	}
126 
127 	return (es - s);
128 }
129 
130 #define __ALIGN (sizeof(size_t))
131 #define ONES ((size_t)-1 / UCHAR_MAX)
132 #define HIGHS (ONES * (UCHAR_MAX / 2 + 1))
133 #define HASZERO(x) ((x)-ONES & ~(x)&HIGHS)
134 
135 char *__strchrnul(const char *s, int c)
136 {
137 	c = (unsigned char)c;
138 	if (!c)
139 		return (char *)s + strlen(s);
140 
141 #ifdef __GNUC__
142 	typedef size_t __attribute__((__may_alias__)) word;
143 	const word *w;
144 	for (; (uintptr_t)s % __ALIGN; s++)
145 		if (!*s || *(unsigned char *)s == c)
146 			return (char *)s;
147 	size_t k = ONES * c;
148 	for (w = (void *)s; !HASZERO(*w) && !HASZERO(*w ^ k); w++)
149 		;
150 	s = (void *)w;
151 #endif
152 	for (; *s && *(unsigned char *)s != c; s++)
153 		;
154 	return (char *)s;
155 }
156 
157 char *strrchr(const char *s, int c)
158 {
159 	return memrchr(s, c, strlen(s) + 1);
160 }
161 
162 char *strchr(const char *s, int c)
163 {
164 	char *r = __strchrnul(s, c);
165 	return *(unsigned char *)r == (unsigned char)c ? r : 0;
166 }