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