Merge branch 'master' of ssh://waterman@scm.millennium.berkeley.edu/project/cs/radlab...
[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
10 int
11 strlen(const char *s)
12 {
13         int n;
14
15         for (n = 0; *s != '\0'; s++)
16                 n++;
17         return n;
18 }
19
20 int
21 strnlen(const char *s, size_t size)
22 {
23         int n;
24
25         for (n = 0; size > 0 && *s != '\0'; s++, size--)
26                 n++;
27         return n;
28 }
29
30 /* zra: These aren't being used, and they are dangerous, so I'm rm'ing them
31 char *
32 strcpy(char *dst, const char *src)
33 {
34         char *ret;
35
36         ret = dst;
37         while ((*dst++ = *src++) != '\0')
38                 ;
39         return ret;
40 }
41
42 char *
43 strcat(char *dst, const char *src)
44 {
45         strcpy(dst+strlen(dst),src);
46         return dst;
47 }
48 */
49
50 char *
51 strncpy(char *dst, const char *src, size_t size) {
52         size_t i;
53         char *ret;
54
55         ret = dst;
56         for (i = 0; i < size; i++) {
57                 // TODO: ivy bitches about this
58                 *dst++ = *src;
59                 // If strlen(src) < size, null-pad 'dst' out to 'size' chars
60                 if (*src != '\0')
61                         src++;
62         }
63         return ret;
64 }
65
66 size_t
67 strlcpy(char *dst, const char *src, size_t size)
68 {
69         char *dst_in;
70
71         dst_in = dst;
72         if (size > 0) {
73                 while (--size > 0 && *src != '\0')
74                         *dst++ = *src++;
75                 *dst = '\0';
76         }
77         return dst - dst_in;
78 }
79
80 int
81 strcmp(const char *p, const char *q)
82 {
83         while (*p && *p == *q)
84                 p++, q++;
85         return (int) ((unsigned char) *p - (unsigned char) *q);
86 }
87
88 int
89 strncmp(const char *p, const char *q, size_t n)
90 {
91         while (n > 0 && *p && *p == *q)
92                 n--, p++, q++;
93         if (n == 0)
94                 return 0;
95         else
96                 return (int) ((unsigned char) *p - (unsigned char) *q);
97 }
98
99 // Return a pointer to the first occurrence of 'c' in 's',
100 // or a null pointer if the string has no 'c'.
101 char *
102 strchr(const char *s, char c)
103 {
104         for (; *s; s++)
105                 if (*s == c)
106                         return (char *) s;
107         return 0;
108 }
109
110 // Return a pointer to the first occurrence of 'c' in 's',
111 // or a pointer to the string-ending null character if the string has no 'c'.
112 char *
113 strfind(const char *s, char c)
114 {
115         for (; *s; s++)
116                 if (*s == c)
117                         break;
118         return (char *) s;
119 }
120
121 // n must be a multiple of 16 and v must be uint32_t-aligned
122 static inline void *
123 memset16(uint32_t *COUNT(n/sizeof(uint32_t)) _v, uint32_t c, size_t n)
124 {
125         uint32_t *start, *end;
126         uint32_t *BND(_v, end) v;
127
128         start = _v;
129         end = _v + n/sizeof(uint32_t);
130         v = _v;
131         c = c | c<<8 | c<<16 | c<<24;
132
133         if(n >= 64 && ((intptr_t)v) % 8 == 0)
134         {
135                 uint64_t* v64 = (uint64_t*)v;
136                 uint64_t c64 = c | ((uint64_t)c)<<32;
137                 while(v64 < (uint64_t*)end-7)
138                 {
139                         v64[3] = v64[2] = v64[1] = v64[0] = c64;
140                         v64[7] = v64[6] = v64[5] = v64[4] = c64;
141                         v64 += 8;
142                 }
143                 v = (uint32_t*)v64;
144         }
145
146         while(v < end)
147         {
148                 v[3] = v[2] = v[1] = v[0] = c;
149                 v += 4;
150         }
151
152         return start;
153 }
154
155 // n must be a multiple of 16 and v must be 4-byte aligned.
156 // as allowed by ISO, behavior undefined if dst/src overlap
157 static inline void *
158 memcpy16(uint32_t *COUNT(n/sizeof(uint32_t)) _dst,
159          const uint32_t *COUNT(n/sizeof(uint32_t)) _src, size_t n)
160 {
161         uint32_t *dststart, *SNT dstend, *SNT srcend;
162         uint32_t *BND(_dst,dstend) dst;
163         const uint32_t *BND(_src,srcend) src;
164
165         dststart = _dst;
166         dstend = (uint32_t *SNT)(_dst + n/sizeof(uint32_t));
167         srcend = (uint32_t *SNT)(_src + n/sizeof(uint32_t));
168         dst = _dst;
169         src = _src;
170
171         while(dst < dstend && src < srcend)
172         {
173                 dst[0] = src[0];
174                 dst[1] = src[1];
175                 dst[2] = src[2];
176                 dst[3] = src[3];
177
178                 src += 4;
179                 dst += 4;
180         }
181
182         return dststart;
183 }
184
185 void *
186 pagecopy(void* dst, void* src)
187 {
188         uint64_t* s = (uint64_t*)src;
189         uint64_t* d = (uint64_t*)dst;
190         for(int i = 0; i < PGSIZE/sizeof(uint64_t); i += 8)
191         {
192                 d[i+0] = s[i+0];
193                 d[i+1] = s[i+1];
194                 d[i+2] = s[i+2];
195                 d[i+3] = s[i+3];
196                 d[i+4] = s[i+4];
197                 d[i+5] = s[i+5];
198                 d[i+6] = s[i+6];
199                 d[i+7] = s[i+7];
200         }
201         return dst;
202 }
203
204 void *
205 memset(void *COUNT(_n) v, int c, size_t _n)
206 {
207         char *BND(v,v+_n) p;
208         size_t n0;
209         size_t n = _n;
210
211         if (n == 0) return NULL; // zra: complain here?
212
213         p = v;
214
215     while (n > 0 && ((uintptr_t)p & 7))
216         {
217                 *p++ = c;
218                 n--;
219         }
220
221         if(n >= 16 && ((uintptr_t)p & 3) == 0)
222         {
223                 n0 = (n/16)*16;
224                 memset16((uint32_t*COUNT(n0/sizeof(uint32_t)))p,c,n0);
225                 n -= n0;
226                 p += n0;
227         }
228
229         while (n > 0)
230         {
231                 *p++ = c;
232                 n--;
233         }
234
235         return v;
236 }
237
238 void *
239 (DMEMCPY(1,2,3) memcpy)(void *COUNT(_n) dst, const void *COUNT(_n) src, size_t _n)
240 {
241         const char *BND(src,src+_n) s;
242         char *BND(dst,dst+_n) d;
243         size_t n0;
244         size_t n = _n;
245
246         s = src;
247         d = dst;
248
249         if(n >= 16 && ((uintptr_t)src  & 3) == 0 && ((uintptr_t)dst & 3) == 0)
250         {
251                 n0 = (n/16)*16;
252                 memcpy16((uint32_t*COUNT(n0/sizeof(uint32_t)))dst,
253                  (const uint32_t*COUNT(n0/sizeof(uint32_t)))src,n0);
254                 n -= n0;
255                 s += n0;
256                 d += n0;
257         }
258
259         while (n-- > 0)
260                 *d++ = *s++;
261
262         return dst;
263 }
264
265 void *
266 memmove(void *COUNT(_n) dst, const void *COUNT(_n) src, size_t _n)
267 {
268         const char *BND(src,src+_n) s;
269         char *BND(dst,dst+_n) d;
270         size_t n = _n;
271         
272         s = src;
273         d = dst;
274         if (s < d && s + n > d) {
275                 s += n;
276                 d += n;
277                 while (n-- > 0)
278                         *--d = *--s;
279         } else
280                 while (n-- > 0)
281                         *d++ = *s++;
282
283         return dst;
284 }
285
286 int
287 memcmp(const void *COUNT(n) v1, const void *COUNT(n) v2, size_t n)
288 {
289         const uint8_t *BND(v1,v1+n) s1 = (const uint8_t *) v1;
290         const uint8_t *BND(v2,v2+n) s2 = (const uint8_t *) v2;
291
292         while (n-- > 0) {
293                 if (*s1 != *s2)
294                         return (int) *s1 - (int) *s2;
295                 s1++, s2++;
296         }
297
298         return 0;
299 }
300
301 void *
302 memfind(const void *COUNT(n) _s, int c, size_t n)
303 {
304         const void *SNT ends = (const char *) _s + n;
305         const void *BND(_s,_s + n) s = _s;
306         for (; s < ends; s++)
307                 if (*(const unsigned char *) s == (unsigned char) c)
308                         break;
309         return (void *BND(_s,_s+n)) s;
310 }
311
312 long
313 strtol(const char *s, char **endptr, int base)
314 {
315         int neg = 0;
316         long val = 0;
317
318         // gobble initial whitespace
319         while (*s == ' ' || *s == '\t')
320                 s++;
321
322         // plus/minus sign
323         if (*s == '+')
324                 s++;
325         else if (*s == '-')
326                 s++, neg = 1;
327
328         // hex or octal base prefix
329         if ((base == 0 || base == 16) && (s[0] == '0' && s[1] == 'x'))
330                 s += 2, base = 16;
331         else if (base == 0 && s[0] == '0')
332                 s++, base = 8;
333         else if (base == 0)
334                 base = 10;
335
336         // digits
337         while (1) {
338                 int dig;
339
340                 if (*s >= '0' && *s <= '9')
341                         dig = *s - '0';
342                 else if (*s >= 'a' && *s <= 'z')
343                         dig = *s - 'a' + 10;
344                 else if (*s >= 'A' && *s <= 'Z')
345                         dig = *s - 'A' + 10;
346                 else
347                         break;
348                 if (dig >= base)
349                         break;
350                 s++, val = (val * base) + dig;
351                 // we don't properly detect overflow!
352         }
353
354         if (endptr)
355                 *endptr = (char *) s;
356         return (neg ? -val : val);
357 }
358
359 int
360 atoi(const char* s)
361 {
362         // no overflow detection
363         return (int)strtol(s,NULL,10);
364 }