Another round at reorganization
[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 strncpy(char *dst, const char *src, size_t size) {
42         size_t i;
43         char *ret;
44
45         ret = dst;
46         for (i = 0; i < size; i++) {
47                 *dst++ = *src;
48                 // If strlen(src) < size, null-pad 'dst' out to 'size' chars
49                 if (*src != '\0')
50                         src++;
51         }
52         return ret;
53 }
54
55 size_t
56 strlcpy(char *dst, const char *src, size_t size)
57 {
58         char *dst_in;
59
60         dst_in = dst;
61         if (size > 0) {
62                 while (--size > 0 && *src != '\0')
63                         *dst++ = *src++;
64                 *dst = '\0';
65         }
66         return dst - dst_in;
67 }
68
69 int
70 strcmp(const char *p, const char *q)
71 {
72         while (*p && *p == *q)
73                 p++, q++;
74         return (int) ((unsigned char) *p - (unsigned char) *q);
75 }
76
77 int
78 strncmp(const char *p, const char *q, size_t n)
79 {
80         while (n > 0 && *p && *p == *q)
81                 n--, p++, q++;
82         if (n == 0)
83                 return 0;
84         else
85                 return (int) ((unsigned char) *p - (unsigned char) *q);
86 }
87
88 // Return a pointer to the first occurrence of 'c' in 's',
89 // or a null pointer if the string has no 'c'.
90 char *
91 strchr(const char *s, char c)
92 {
93         for (; *s; s++)
94                 if (*s == c)
95                         return (char *) s;
96         return 0;
97 }
98
99 // Return a pointer to the first occurrence of 'c' in 's',
100 // or a pointer to the string-ending null character if the string has no 'c'.
101 char *
102 strfind(const char *s, char c)
103 {
104         for (; *s; s++)
105                 if (*s == c)
106                         break;
107         return (char *) s;
108 }
109
110
111 void *
112 memset(void *v, int c, size_t n)
113 {
114         char *p;
115         int m;
116
117         p = v;
118         m = n;
119         while (--m >= 0)
120                 *p++ = c;
121
122         return v;
123 }
124
125 void *
126 memcpy(void *dst, const void *src, size_t n)
127 {
128         const char *s;
129         char *d;
130
131         s = src;
132         d = dst;
133         while (n-- > 0)
134                 *d++ = *s++;
135
136         return dst;
137 }
138
139 void *
140 memmove(void *dst, const void *src, size_t n)
141 {
142         const char *s;
143         char *d;
144         
145         s = src;
146         d = dst;
147         if (s < d && s + n > d) {
148                 s += n;
149                 d += n;
150                 while (n-- > 0)
151                         *--d = *--s;
152         } else
153                 while (n-- > 0)
154                         *d++ = *s++;
155
156         return dst;
157 }
158
159 int
160 memcmp(const void *v1, const void *v2, size_t n)
161 {
162         const uint8_t *s1 = (const uint8_t *) v1;
163         const uint8_t *s2 = (const uint8_t *) v2;
164
165         while (n-- > 0) {
166                 if (*s1 != *s2)
167                         return (int) *s1 - (int) *s2;
168                 s1++, s2++;
169         }
170
171         return 0;
172 }
173
174 void *
175 memfind(const void *s, int c, size_t n)
176 {
177         const void *ends = (const char *) s + n;
178         for (; s < ends; s++)
179                 if (*(const unsigned char *) s == (unsigned char) c)
180                         break;
181         return (void *) s;
182 }
183
184 long
185 strtol(const char *s, char **endptr, int base)
186 {
187         int neg = 0;
188         long val = 0;
189
190         // gobble initial whitespace
191         while (*s == ' ' || *s == '\t')
192                 s++;
193
194         // plus/minus sign
195         if (*s == '+')
196                 s++;
197         else if (*s == '-')
198                 s++, neg = 1;
199
200         // hex or octal base prefix
201         if ((base == 0 || base == 16) && (s[0] == '0' && s[1] == 'x'))
202                 s += 2, base = 16;
203         else if (base == 0 && s[0] == '0')
204                 s++, base = 8;
205         else if (base == 0)
206                 base = 10;
207
208         // digits
209         while (1) {
210                 int dig;
211
212                 if (*s >= '0' && *s <= '9')
213                         dig = *s - '0';
214                 else if (*s >= 'a' && *s <= 'z')
215                         dig = *s - 'a' + 10;
216                 else if (*s >= 'A' && *s <= 'Z')
217                         dig = *s - 'A' + 10;
218                 else
219                         break;
220                 if (dig >= base)
221                         break;
222                 s++, val = (val * base) + dig;
223                 // we don't properly detect overflow!
224         }
225
226         if (endptr)
227                 *endptr = (char *) s;
228         return (neg ? -val : val);
229 }
230