Merge branch 'master' into net-dev
[akaros.git] / kern / src / string.c
1 // Basic string routines.  Not hardware optimized, but not shabby.
2
3 #ifdef __DEPUTY__
4 #pragma nodeputy
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 char *
30 strcpy(char *dst, const char *src)
31 {
32         char *ret;
33
34         ret = dst;
35         while ((*dst++ = *src++) != '\0')
36                 /* do nothing */;
37         return ret;
38 }
39
40 char *
41 strcat(char *dst, const char *src)
42 {
43         strcpy(dst+strlen(dst),src);
44         return dst;
45 }
46
47 char *
48 strncpy(char *dst, const char *src, size_t size) {
49         size_t i;
50         char *ret;
51
52         ret = dst;
53         for (i = 0; i < size; i++) {
54                 *dst++ = *src;
55                 // If strlen(src) < size, null-pad 'dst' out to 'size' chars
56                 if (*src != '\0')
57                         src++;
58         }
59         return ret;
60 }
61
62 size_t
63 strlcpy(char *dst, const char *src, size_t size)
64 {
65         char *dst_in;
66
67         dst_in = dst;
68         if (size > 0) {
69                 while (--size > 0 && *src != '\0')
70                         *dst++ = *src++;
71                 *dst = '\0';
72         }
73         return dst - dst_in;
74 }
75
76 int
77 strcmp(const char *p, const char *q)
78 {
79         while (*p && *p == *q)
80                 p++, q++;
81         return (int) ((unsigned char) *p - (unsigned char) *q);
82 }
83
84 int
85 strncmp(const char *p, const char *q, size_t n)
86 {
87         while (n > 0 && *p && *p == *q)
88                 n--, p++, q++;
89         if (n == 0)
90                 return 0;
91         else
92                 return (int) ((unsigned char) *p - (unsigned char) *q);
93 }
94
95 // Return a pointer to the first occurrence of 'c' in 's',
96 // or a null pointer if the string has no 'c'.
97 char *
98 strchr(const char *s, char c)
99 {
100         for (; *s; s++)
101                 if (*s == c)
102                         return (char *) s;
103         return 0;
104 }
105
106 // Return a pointer to the first occurrence of 'c' in 's',
107 // or a pointer to the string-ending null character if the string has no 'c'.
108 char *
109 strfind(const char *s, char c)
110 {
111         for (; *s; s++)
112                 if (*s == c)
113                         break;
114         return (char *) s;
115 }
116
117 // n must be a multiple of 16 and v must be uint32_t-aligned
118 static inline void *
119 memset16(uint32_t *v, uint32_t c, size_t n)
120 {
121         uint32_t *start, *end;
122
123         start = v;
124         end = v + n/sizeof(uint32_t);
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* dst, const uint32_t* src, size_t n)
140 {
141         uint32_t *dststart, *dstend;
142
143         dststart = dst;
144         dstend = dst + n/sizeof(uint32_t);
145
146         while(dst < dstend)
147         {
148                 dst[0] = src[0];
149                 dst[1] = src[1];
150                 dst[2] = src[2];
151                 dst[3] = src[3];
152
153                 src += 4;
154                 dst += 4;
155         }
156
157         return dststart;
158 }
159
160 void *
161 memset(void *v, int c, size_t n)
162 {
163         char *p;
164         size_t n0;
165
166         p = v;
167
168         if(n >= 16 && ((uintptr_t)v & 3) == 0)
169         {
170                 n0 = (n/16)*16;
171                 memset16((uint32_t*)v,c,n0);
172                 n -= n0;
173                 p += n0;
174         }
175
176         while (n > 0)
177         {
178                 *p++ = c;
179                 n--;
180         }
181
182         return v;
183 }
184
185 void *
186 memcpy(void *dst, const void *src, size_t n)
187 {
188         const char *s;
189         char *d;
190         size_t n0;
191
192         s = src;
193         d = dst;
194
195         if(n >= 16 && ((uintptr_t)src  & 3) == 0 && ((uintptr_t)dst & 3) == 0)
196         {
197                 n0 = (n/16)*16;
198                 memcpy16((uint32_t*)dst,(const uint32_t*)src,n0);
199                 n -= n0;
200                 s += n0;
201                 d += n0;
202         }
203
204         while (n-- > 0)
205                 *d++ = *s++;
206
207         return dst;
208 }
209
210 void *
211 memmove(void *dst, const void *src, size_t n)
212 {
213         const char *s;
214         char *d;
215         
216         s = src;
217         d = dst;
218         if (s < d && s + n > d) {
219                 s += n;
220                 d += n;
221                 while (n-- > 0)
222                         *--d = *--s;
223         } else
224                 while (n-- > 0)
225                         *d++ = *s++;
226
227         return dst;
228 }
229
230 int
231 memcmp(const void *v1, const void *v2, size_t n)
232 {
233         const uint8_t *s1 = (const uint8_t *) v1;
234         const uint8_t *s2 = (const uint8_t *) v2;
235
236         while (n-- > 0) {
237                 if (*s1 != *s2)
238                         return (int) *s1 - (int) *s2;
239                 s1++, s2++;
240         }
241
242         return 0;
243 }
244
245 void *
246 memfind(const void *s, int c, size_t n)
247 {
248         const void *ends = (const char *) s + n;
249         for (; s < ends; s++)
250                 if (*(const unsigned char *) s == (unsigned char) c)
251                         break;
252         return (void *) s;
253 }
254
255 long
256 strtol(const char *s, char **endptr, int base)
257 {
258         int neg = 0;
259         long val = 0;
260
261         // gobble initial whitespace
262         while (*s == ' ' || *s == '\t')
263                 s++;
264
265         // plus/minus sign
266         if (*s == '+')
267                 s++;
268         else if (*s == '-')
269                 s++, neg = 1;
270
271         // hex or octal base prefix
272         if ((base == 0 || base == 16) && (s[0] == '0' && s[1] == 'x'))
273                 s += 2, base = 16;
274         else if (base == 0 && s[0] == '0')
275                 s++, base = 8;
276         else if (base == 0)
277                 base = 10;
278
279         // digits
280         while (1) {
281                 int dig;
282
283                 if (*s >= '0' && *s <= '9')
284                         dig = *s - '0';
285                 else if (*s >= 'a' && *s <= 'z')
286                         dig = *s - 'a' + 10;
287                 else if (*s >= 'A' && *s <= 'Z')
288                         dig = *s - 'A' + 10;
289                 else
290                         break;
291                 if (dig >= base)
292                         break;
293                 s++, val = (val * base) + dig;
294                 // we don't properly detect overflow!
295         }
296
297         if (endptr)
298                 *endptr = (char *) s;
299         return (neg ? -val : val);
300 }
301