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