xref: /DragonStub/apps/lib/string.c (revision 823f04931913f01ee1fc0dc0c7876156ad150388)
1 
2 #include <dragonstub/dragonstub.h>
3 
skip_spaces(const char * str)4 char *skip_spaces(const char *str)
5 {
6 	while (isspace(*str))
7 		++str;
8 	return (char *)str;
9 }
10 
atou(const char * s)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 
simple_guess_base(const char * cp)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  */
strlen(const char * s)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  */
simple_strtoull(const char * cp,char ** endp,unsigned int base)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 
simple_strtol(const char * cp,char ** endp,unsigned int base)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 
strcmp(const char * str1,const char * str2)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 
strncmp(const char * cs,const char * ct,size_t count)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 
strnlen(const char * s,size_t maxlen)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 
__strchrnul(const char * s,int c)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 
strrchr(const char * s,int c)157 char *strrchr(const char *s, int c)
158 {
159 	return memrchr(s, c, strlen(s) + 1);
160 }
161 
strchr(const char * s,int c)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 }
167 
168 /**
169  * strstr - Find the first substring in a %NUL terminated string
170  * @s1: The string to be searched
171  * @s2: The string to search for
172  */
strstr(const char * s1,const char * s2)173 char *strstr(const char *s1, const char *s2)
174 {
175 	size_t l1, l2;
176 
177 	l2 = strlen(s2);
178 	if (!l2)
179 		return (char *)s1;
180 	l1 = strlen(s1);
181 	while (l1 >= l2) {
182 		l1--;
183 		if (!memcmp(s1, s2, l2))
184 			return (char *)s1;
185 		s1++;
186 	}
187 	return NULL;
188 }