Changed env_user_mem_walk to use return codes
[akaros.git] / kern / src / string.c
1 // Basic string routines.  Not hardware optimized, but not shabby.
2
3 #ifdef __SHARC__
4 #pragma nosharc
5 #endif
6
7 #include <string.h>
8 #include <ros/memlayout.h>
9 #include <assert.h>
10
11 int
12 strlen(const char *s)
13 {
14         int n;
15
16         for (n = 0; *s != '\0'; s++)
17                 n++;
18         return n;
19 }
20
21 int
22 strnlen(const char *s, size_t size)
23 {
24         int n;
25
26         for (n = 0; size > 0 && *s != '\0'; s++, size--)
27                 n++;
28         return n;
29 }
30
31 /* zra: These aren't being used, and they are dangerous, so I'm rm'ing them
32 char *
33 strcpy(char *dst, const char *src)
34 {
35         char *ret;
36
37         ret = dst;
38         while ((*dst++ = *src++) != '\0')
39                 ;
40         return ret;
41 }
42
43 char *
44 strcat(char *dst, const char *src)
45 {
46         strcpy(dst+strlen(dst),src);
47         return dst;
48 }
49 */
50
51 char *
52 strncpy(char *dst, const char *src, size_t size) {
53         size_t i;
54         char *ret;
55
56         ret = dst;
57         for (i = 0; i < size; i++) {
58                 // TODO: ivy bitches about this
59                 *dst++ = *src;
60                 // If strlen(src) < size, null-pad 'dst' out to 'size' chars
61                 if (*src != '\0')
62                         src++;
63         }
64         return ret;
65 }
66
67 size_t
68 strlcpy(char *dst, const char *src, size_t size)
69 {
70         char *dst_in;
71
72         dst_in = dst;
73         if (size > 0) {
74                 while (--size > 0 && *src != '\0')
75                         *dst++ = *src++;
76                 *dst = '\0';
77         }
78         return dst - dst_in;
79 }
80
81 int
82 strcmp(const char *p, const char *q)
83 {
84         while (*p && *p == *q)
85                 p++, q++;
86         return (int) ((unsigned char) *p - (unsigned char) *q);
87 }
88
89 int
90 strncmp(const char *p, const char *q, size_t n)
91 {
92         while (n > 0 && *p && *p == *q)
93                 n--, p++, q++;
94         if (n == 0)
95                 return 0;
96         else
97                 return (int) ((unsigned char) *p - (unsigned char) *q);
98 }
99
100 // Return a pointer to the first occurrence of 'c' in 's',
101 // or a null pointer if the string has no 'c'.
102 char *
103 strchr(const char *s, char c)
104 {
105         for (; *s; s++)
106                 if (*s == c)
107                         return (char *) s;
108         return 0;
109 }
110
111 void *
112 memchr(void* mem, int chr, int len)
113 {
114         char* s = (char*)mem;
115         for(int i = 0; i < len; i++)
116                 if(s[i] == (char)chr)
117                         return s+i;
118         return NULL;
119 }
120
121 // Return a pointer to the first occurrence of 'c' in 's',
122 // or a pointer to the string-ending null character if the string has no 'c'.
123 char *
124 strfind(const char *s, char c)
125 {
126         for (; *s; s++)
127                 if (*s == c)
128                         break;
129         return (char *) s;
130 }
131
132 // n must be a multiple of 16 and v must be uint32_t-aligned
133 static inline void *
134 memset16(uint32_t *COUNT(n/sizeof(uint32_t)) _v, uint32_t c, size_t n)
135 {
136         uint32_t *start, *end;
137         uint32_t *BND(_v, end) v;
138
139         start = _v;
140         end = _v + n/sizeof(uint32_t);
141         v = _v;
142         c = c | c<<8 | c<<16 | c<<24;
143
144         if(n >= 64 && ((intptr_t)v) % 8 == 0)
145         {
146                 uint64_t* v64 = (uint64_t*)v;
147                 uint64_t c64 = c | ((uint64_t)c)<<32;
148                 while(v64 < (uint64_t*)end-7)
149                 {
150                         v64[3] = v64[2] = v64[1] = v64[0] = c64;
151                         v64[7] = v64[6] = v64[5] = v64[4] = c64;
152                         v64 += 8;
153                 }
154                 v = (uint32_t*)v64;
155         }
156
157         while(v < end)
158         {
159                 v[3] = v[2] = v[1] = v[0] = c;
160                 v += 4;
161         }
162
163         return start;
164 }
165
166 // n must be a multiple of 16 and v must be 4-byte aligned.
167 // as allowed by ISO, behavior undefined if dst/src overlap
168 static inline void *
169 memcpy16(uint32_t *COUNT(n/sizeof(uint32_t)) _dst,
170          const uint32_t *COUNT(n/sizeof(uint32_t)) _src, size_t n)
171 {
172         uint32_t *dststart, *SNT dstend, *SNT srcend;
173         uint32_t *BND(_dst,dstend) dst;
174         const uint32_t *BND(_src,srcend) src;
175
176         dststart = _dst;
177         dstend = (uint32_t *SNT)(_dst + n/sizeof(uint32_t));
178         srcend = (uint32_t *SNT)(_src + n/sizeof(uint32_t));
179         dst = _dst;
180         src = _src;
181
182         while(dst < dstend && src < srcend)
183         {
184                 dst[0] = src[0];
185                 dst[1] = src[1];
186                 dst[2] = src[2];
187                 dst[3] = src[3];
188
189                 src += 4;
190                 dst += 4;
191         }
192
193         return dststart;
194 }
195
196 void *
197 pagecopy(void* d, void* s)
198 {
199         static_assert(PGSIZE % 64 == 0);
200         for(int i = 0; i < PGSIZE; i += 64)
201         {
202                 *((uint64_t*)(d+i+0)) = *((uint64_t*)(s+i+0));
203                 *((uint64_t*)(d+i+8)) = *((uint64_t*)(s+i+8));
204                 *((uint64_t*)(d+i+16)) = *((uint64_t*)(s+i+16));
205                 *((uint64_t*)(d+i+24)) = *((uint64_t*)(s+i+24));
206                 *((uint64_t*)(d+i+32)) = *((uint64_t*)(s+i+32));
207                 *((uint64_t*)(d+i+40)) = *((uint64_t*)(s+i+40));
208                 *((uint64_t*)(d+i+48)) = *((uint64_t*)(s+i+48));
209                 *((uint64_t*)(d+i+56)) = *((uint64_t*)(s+i+56));
210         }
211         return d;
212 }
213
214 void *
215 memset(void *COUNT(_n) v, int c, size_t _n)
216 {
217         char *BND(v,v+_n) p;
218         size_t n0;
219         size_t n = _n;
220
221         if (n == 0) return NULL; // zra: complain here?
222
223         p = v;
224
225     while (n > 0 && ((uintptr_t)p & 7))
226         {
227                 *p++ = c;
228                 n--;
229         }
230
231         if(n >= 16 && ((uintptr_t)p & 3) == 0)
232         {
233                 n0 = (n/16)*16;
234                 memset16((uint32_t*COUNT(n0/sizeof(uint32_t)))p,c,n0);
235                 n -= n0;
236                 p += n0;
237         }
238
239         while (n > 0)
240         {
241                 *p++ = c;
242                 n--;
243         }
244
245         return v;
246 }
247
248 void *
249 (DMEMCPY(1,2,3) memcpy)(void *COUNT(_n) dst, const void *COUNT(_n) src, size_t _n)
250 {
251         const char *BND(src,src+_n) s;
252         char *BND(dst,dst+_n) d;
253         size_t n0;
254         size_t n = _n;
255
256         s = src;
257         d = dst;
258
259         if(n >= 16 && ((uintptr_t)src  & 3) == 0 && ((uintptr_t)dst & 3) == 0)
260         {
261                 n0 = (n/16)*16;
262                 memcpy16((uint32_t*COUNT(n0/sizeof(uint32_t)))dst,
263                  (const uint32_t*COUNT(n0/sizeof(uint32_t)))src,n0);
264                 n -= n0;
265                 s += n0;
266                 d += n0;
267         }
268
269         while (n-- > 0)
270                 *d++ = *s++;
271
272         return dst;
273 }
274
275 void *
276 memmove(void *COUNT(_n) dst, const void *COUNT(_n) src, size_t _n)
277 {
278         const char *BND(src,src+_n) s;
279         char *BND(dst,dst+_n) d;
280         size_t n = _n;
281         
282         s = src;
283         d = dst;
284         if (s < d && s + n > d) {
285                 s += n;
286                 d += n;
287                 while (n-- > 0)
288                         *--d = *--s;
289         } else
290                 while (n-- > 0)
291                         *d++ = *s++;
292
293         return dst;
294 }
295
296 int
297 memcmp(const void *COUNT(n) v1, const void *COUNT(n) v2, size_t n)
298 {
299         const uint8_t *BND(v1,v1+n) s1 = (const uint8_t *) v1;
300         const uint8_t *BND(v2,v2+n) 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 *COUNT(n) _s, int c, size_t n)
313 {
314         const void *SNT ends = (const char *) _s + n;
315         const void *BND(_s,_s + n) s = _s;
316         for (; s < ends; s++)
317                 if (*(const unsigned char *) s == (unsigned char) c)
318                         break;
319         return (void *BND(_s,_s+n)) 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 int
370 atoi(const char* s)
371 {
372         // no overflow detection
373         return (int)strtol(s,NULL,10);
374 }