Removes Ivy annotations (XCC)
[akaros.git] / kern / src / string.c
1 // Basic string routines.  Not hardware optimized, but not shabby.
2
3 #include <stdio.h>
4 #include <string.h>
5 #include <ros/memlayout.h>
6 #include <assert.h>
7
8 int
9 strlen(const char *s)
10 {
11         int n;
12
13         for (n = 0; *s != '\0'; s++)
14                 n++;
15         return n;
16 }
17
18 int
19 strnlen(const char *s, size_t size)
20 {
21         int n;
22
23         for (n = 0; size > 0 && *s != '\0'; s++, size--)
24                 n++;
25         return n;
26 }
27
28 /* zra: These aren't being used, and they are dangerous, so I'm rm'ing them
29 char *
30 strcpy(char *dst, const char *src)
31 {
32         char *ret;
33
34         ret = dst;
35         while ((*dst++ = *src++) != '\0')
36                 ;
37         return ret;
38 }
39
40 char *
41 strcat(char *dst, const char *src)
42 {
43         strcpy(dst+strlen(dst),src);
44         return dst;
45 }
46 */
47
48 char *
49 strncpy(char *dst, const char *src, size_t size) {
50         size_t i;
51         char *ret;
52
53         ret = dst;
54         for (i = 0; i < size; i++) {
55                 *dst++ = *src;
56                 // If strlen(src) < size, null-pad 'dst' out to 'size' chars
57                 if (*src != '\0')
58                         src++;
59         }
60         return ret;
61 }
62
63 size_t
64 strlcpy(char *dst, const char *src, size_t size)
65 {
66         char *dst_in;
67
68         dst_in = dst;
69         if (size > 0) {
70                 while (--size > 0 && *src != '\0')
71                         *dst++ = *src++;
72                 *dst = '\0';
73         }
74         return dst - dst_in;
75 }
76
77 int
78 strcmp(const char *p, const char *q)
79 {
80         while (*p && *p == *q)
81                 p++, q++;
82         return (int) ((unsigned char) *p - (unsigned char) *q);
83 }
84
85 int
86 strncmp(const char *p, const char *q, size_t n)
87 {
88         while (n > 0 && *p && *p == *q)
89                 n--, p++, q++;
90         if (n == 0)
91                 return 0;
92         else
93                 return (int) ((unsigned char) *p - (unsigned char) *q);
94 }
95
96 // Return a pointer to the first occurrence of 'c' in 's',
97 // or a null pointer if the string has no 'c'.
98 char *
99 strchr(const char *s, char c)
100 {
101         for (; *s; s++)
102                 if (*s == c)
103                         return (char *) s;
104         return 0;
105 }
106
107 // Return a pointer to the last occurrence of 'c' in 's',
108 // or a null pointer if the string has no 'c'.
109 char *
110 strrchr(const char *s, char c)
111 {
112         char *lastc = NULL;
113         for (; *s; s++)
114                 if (*s == c){
115                         lastc = (char*)s;
116                 }
117         return lastc;
118 }
119
120 void *
121 memchr(void* mem, int chr, int len)
122 {
123         char* s = (char*)mem;
124         for(int i = 0; i < len; i++)
125                 if(s[i] == (char)chr)
126                         return s+i;
127         return NULL;
128 }
129
130 // Return a pointer to the first occurrence of 'c' in 's',
131 // or a pointer to the string-ending null character if the string has no 'c'.
132 char *
133 strfind(const char *s, char c)
134 {
135         for (; *s; s++)
136                 if (*s == c)
137                         break;
138         return (char *) s;
139 }
140
141 // memset aligned words.
142 static inline void *
143 memsetw(long* _v, long c, size_t n)
144 {
145         long *start, *end, *v;
146
147         start = _v;
148         end = _v + n/sizeof(long);
149         v = _v;
150         c = c & 0xff;
151         c = c | c<<8;
152         c = c | c<<16;
153         #if NUM_ADDR_BITS == 64
154         c = c | c<<32;
155         #elif NUM_ADDR_BITS != 32
156         # error
157         #endif
158
159         while(v < end - (8-1))
160         {
161                 v[3] = v[2] = v[1] = v[0] = c;
162                 v += 4;
163                 v[3] = v[2] = v[1] = v[0] = c;
164                 v += 4;
165         }
166
167         while(v < end)
168           *v++ = c;
169
170         return start;
171 }
172
173 // copy aligned words.
174 // unroll 9 ways to get multiple misses in flight
175 #define memcpyw(type, _dst, _src, n) \
176   do { \
177         type* restrict src = (type*)(_src); \
178         type* restrict dst = (type*)(_dst); \
179         type* srcend = src + (n)/sizeof(type); \
180         type* dstend = dst + (n)/sizeof(type); \
181         while (dst < dstend - (9-1)) { \
182                 dst[0] = src[0]; \
183                 dst[1] = src[1]; \
184                 dst[2] = src[2]; \
185                 dst[3] = src[3]; \
186                 dst[4] = src[4]; \
187                 dst[5] = src[5]; \
188                 dst[6] = src[6]; \
189                 dst[7] = src[7]; \
190                 dst[8] = src[8]; \
191                 src += 9; \
192                 dst += 9; \
193         } \
194         while(dst < dstend) \
195           *dst++ = *src++; \
196   } while(0)
197
198 void *
199 memset(void *v, int c, size_t _n)
200 {
201         char *p;
202         size_t n0;
203         size_t n = _n;
204
205         if (n == 0) return NULL; // zra: complain here?
206
207         p = v;
208
209     while (n > 0 && ((uintptr_t)p & (sizeof(long)-1)))
210         {
211                 *p++ = c;
212                 n--;
213         }
214
215         if (n >= sizeof(long))
216         {
217                 n0 = n / sizeof(long) * sizeof(long);
218                 memsetw((long*)p, c, n0);
219                 n -= n0;
220                 p += n0;
221         }
222
223         while (n > 0)
224         {
225                 *p++ = c;
226                 n--;
227         }
228
229         return v;
230 }
231
232 void *
233 memcpy(void* dst, const void* src, size_t _n)
234 {
235         const char* s;
236         char* d;
237         size_t n0 = 0;
238         size_t n = _n;
239         int align = sizeof(long)-1;
240
241         s = src;
242         d = dst;
243
244         if ((((uintptr_t)s | (uintptr_t)d) & (sizeof(long)-1)) == 0)
245         {
246                 n0 = n / sizeof(long) * sizeof(long);
247                 memcpyw(long, d, s, n0);
248         }
249         else if ((((uintptr_t)s | (uintptr_t)d) & (sizeof(int)-1)) == 0)
250         {
251                 n0 = n / sizeof(int) * sizeof(int);
252                 memcpyw(int, d, s, n0);
253         }
254         else if ((((uintptr_t)s | (uintptr_t)d) & (sizeof(short)-1)) == 0)
255         {
256                 n0 = n / sizeof(short) * sizeof(short);
257                 memcpyw(short, d, s, n0);
258         }
259
260         n -= n0;
261         s += n0;
262         d += n0;
263
264         while (n-- > 0)
265                 *d++ = *s++;
266
267         return dst;
268 }
269
270 void *
271 memmove(void *dst, const void *src, size_t _n)
272 {
273 #ifdef CONFIG_X86
274         bcopy(src, dst, _n);
275         return dst;
276 #else
277         const char *s;
278         char *d;
279         size_t n = _n;
280         
281         s = src;
282         d = dst;
283         if (s < d && s + n > d) {
284                 s += n;
285                 d += n;
286                 while (n-- > 0)
287                         *--d = *--s;
288         } else
289                 while (n-- > 0)
290                         *d++ = *s++;
291
292         return dst;
293 #endif
294 }
295
296 int
297 memcmp(const void *v1, const void *v2, size_t n)
298 {
299         const uint8_t *s1 = (const uint8_t *) v1;
300         const uint8_t *s2 = (const uint8_t *) v2;
301
302         while (n-- > 0) {
303                 if (*s1 != *s2)
304                         return (int) *s1 - (int) *s2;
305                 s1++, s2++;
306         }
307
308         return 0;
309 }
310
311 void *
312 memfind(const void *_s, int c, size_t n)
313 {
314         const void *ends = (const char *) _s + n;
315         const void *s = _s;
316         for (; s < ends; s++)
317                 if (*(const unsigned char *) s == (unsigned char) c)
318                         break;
319         return (void *)s;
320 }
321
322 long
323 strtol(const char *s, char **endptr, int base)
324 {
325         int neg = 0;
326         long val = 0;
327
328         // gobble initial whitespace
329         while (*s == ' ' || *s == '\t')
330                 s++;
331
332         // plus/minus sign
333         if (*s == '+')
334                 s++;
335         else if (*s == '-')
336                 s++, neg = 1;
337
338         // hex or octal base prefix
339         if ((base == 0 || base == 16) && (s[0] == '0' && s[1] == 'x'))
340                 s += 2, base = 16;
341         else if (base == 0 && s[0] == '0')
342                 s++, base = 8;
343         else if (base == 0)
344                 base = 10;
345
346         // digits
347         while (1) {
348                 int dig;
349
350                 if (*s >= '0' && *s <= '9')
351                         dig = *s - '0';
352                 else if (*s >= 'a' && *s <= 'z')
353                         dig = *s - 'a' + 10;
354                 else if (*s >= 'A' && *s <= 'Z')
355                         dig = *s - 'A' + 10;
356                 else
357                         break;
358                 if (dig >= base)
359                         break;
360                 s++, val = (val * base) + dig;
361                 // we don't properly detect overflow!
362         }
363
364         if (endptr)
365                 *endptr = (char *) s;
366         return (neg ? -val : val);
367 }
368
369 unsigned long
370 strtoul(const char *s, char **endptr, int base)
371 {
372         int neg = 0;
373         unsigned long val = 0;
374
375         // gobble initial whitespace
376         while (*s == ' ' || *s == '\t')
377                 s++;
378
379         // plus/minus sign
380         if (*s == '+')
381                 s++;
382         else if (*s == '-')
383                 s++, neg = 1;
384
385         // hex or octal base prefix
386         if ((base == 0 || base == 16) && (s[0] == '0' && s[1] == 'x'))
387                 s += 2, base = 16;
388         else if (base == 0 && s[0] == '0')
389                 s++, base = 8;
390         else if (base == 0)
391                 base = 10;
392
393         // digits
394         while (1) {
395                 int dig;
396
397                 if (*s >= '0' && *s <= '9')
398                         dig = *s - '0';
399                 else if (*s >= 'a' && *s <= 'z')
400                         dig = *s - 'a' + 10;
401                 else if (*s >= 'A' && *s <= 'Z')
402                         dig = *s - 'A' + 10;
403                 else
404                         break;
405                 if (dig >= base)
406                         break;
407                 s++, val = (val * base) + dig;
408                 // we don't properly detect overflow!
409         }
410
411         if (endptr)
412                 *endptr = (char *) s;
413         return (neg ? -val : val);
414 }
415
416 int atoi(const char *s)
417 {
418         if (!s)
419                 return 0;
420         if (s[0] == '0' && s[1] == 'x')
421                 warn("atoi() used on a hex string!");
422         // no overflow detection
423         return (int)strtol(s,NULL,10);
424 }
425
426 int sigchecksum(void *address, int length)
427 {
428         uint8_t *p, sum;
429
430         sum = 0;
431         for (p = address; length-- > 0; p++)
432                 sum += *p;
433
434         return sum;
435 }
436
437 void *sigscan(uint8_t *address, int length, char *signature)
438 {
439         uint8_t *e, *p;
440         int siglength;
441
442         e = address + length;
443         siglength = strlen(signature);
444         for (p = address; p + siglength < e; p += 16) {
445                 if (memcmp(p, signature, siglength))
446                         continue;
447                 return p;
448         }
449
450         return NULL;
451 }