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