* same with xv6
[mascara-docs.git] / i386 / MIT / course / src / src.lab / lib / string.c
blobd018b31af40d2803cb8d5bf6a38827e24cea165e
1 // Basic string routines. Not hardware optimized, but not shabby.
3 #include <inc/string.h>
5 // Using assembly for memset/memmove
6 // makes some difference on real hardware,
7 // but it makes an even bigger difference on bochs.
8 // Primespipe runs 3x faster this way.
9 #define ASM 1
11 int
12 strlen(const char *s)
14 int n;
16 for (n = 0; *s != '\0'; s++)
17 n++;
18 return n;
21 int
22 strnlen(const char *s, size_t size)
24 int n;
26 for (n = 0; size > 0 && *s != '\0'; s++, size--)
27 n++;
28 return n;
31 char *
32 strcpy(char *dst, const char *src)
34 char *ret;
36 ret = dst;
37 while ((*dst++ = *src++) != '\0')
38 /* do nothing */;
39 return ret;
42 char *
43 strcat(char *dst, const char *src)
45 int len = strlen(dst);
46 strcpy(dst + len, src);
47 return dst;
50 char *
51 strncpy(char *dst, const char *src, size_t size) {
52 size_t i;
53 char *ret;
55 ret = dst;
56 for (i = 0; i < size; i++) {
57 *dst++ = *src;
58 // If strlen(src) < size, null-pad 'dst' out to 'size' chars
59 if (*src != '\0')
60 src++;
62 return ret;
65 size_t
66 strlcpy(char *dst, const char *src, size_t size)
68 char *dst_in;
70 dst_in = dst;
71 if (size > 0) {
72 while (--size > 0 && *src != '\0')
73 *dst++ = *src++;
74 *dst = '\0';
76 return dst - dst_in;
79 int
80 strcmp(const char *p, const char *q)
82 while (*p && *p == *q)
83 p++, q++;
84 return (int) ((unsigned char) *p - (unsigned char) *q);
87 int
88 strncmp(const char *p, const char *q, size_t n)
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);
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)
103 for (; *s; s++)
104 if (*s == c)
105 return (char *) s;
106 return 0;
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)
114 for (; *s; s++)
115 if (*s == c)
116 break;
117 return (char *) s;
120 #if ASM
121 void *
122 memset(void *v, int c, size_t n)
124 char *p;
126 if (n == 0)
127 return v;
128 if ((int)v%4 == 0 && n%4 == 0) {
129 c &= 0xFF;
130 c = (c<<24)|(c<<16)|(c<<8)|c;
131 asm volatile("cld; rep stosl\n"
132 :: "D" (v), "a" (c), "c" (n/4)
133 : "cc", "memory");
134 } else
135 asm volatile("cld; rep stosb\n"
136 :: "D" (v), "a" (c), "c" (n)
137 : "cc", "memory");
138 return v;
141 void *
142 memmove(void *dst, const void *src, size_t n)
144 const char *s;
145 char *d;
147 s = src;
148 d = dst;
149 if (s < d && s + n > d) {
150 s += n;
151 d += n;
152 if ((int)s%4 == 0 && (int)d%4 == 0 && n%4 == 0)
153 asm volatile("std; rep movsl\n"
154 :: "D" (d-4), "S" (s-4), "c" (n/4) : "cc", "memory");
155 else
156 asm volatile("std; rep movsb\n"
157 :: "D" (d-1), "S" (s-1), "c" (n) : "cc", "memory");
158 // Some versions of GCC rely on DF being clear
159 asm volatile("cld" ::: "cc");
160 } else {
161 if ((int)s%4 == 0 && (int)d%4 == 0 && n%4 == 0)
162 asm volatile("cld; rep movsl\n"
163 :: "D" (d), "S" (s), "c" (n/4) : "cc", "memory");
164 else
165 asm volatile("cld; rep movsb\n"
166 :: "D" (d), "S" (s), "c" (n) : "cc", "memory");
168 return dst;
171 #else
173 void *
174 memset(void *v, int c, size_t n)
176 char *p;
177 int m;
179 p = v;
180 m = n;
181 while (--m >= 0)
182 *p++ = c;
184 return v;
187 /* no memcpy - use memmove instead */
189 void *
190 memmove(void *dst, const void *src, size_t n)
192 const char *s;
193 char *d;
195 s = src;
196 d = dst;
197 if (s < d && s + n > d) {
198 s += n;
199 d += n;
200 while (n-- > 0)
201 *--d = *--s;
202 } else
203 while (n-- > 0)
204 *d++ = *s++;
206 return dst;
208 #endif
210 /* sigh - gcc emits references to this for structure assignments! */
211 /* it is *not* prototyped in inc/string.h - do not use directly. */
212 void *
213 memcpy(void *dst, void *src, size_t n)
215 return memmove(dst, src, n);
219 memcmp(const void *v1, const void *v2, size_t n)
221 const uint8_t *s1 = (const uint8_t *) v1;
222 const uint8_t *s2 = (const uint8_t *) v2;
224 while (n-- > 0) {
225 if (*s1 != *s2)
226 return (int) *s1 - (int) *s2;
227 s1++, s2++;
230 return 0;
233 void *
234 memfind(const void *s, int c, size_t n)
236 const void *ends = (const char *) s + n;
237 for (; s < ends; s++)
238 if (*(const unsigned char *) s == (unsigned char) c)
239 break;
240 return (void *) s;
243 long
244 strtol(const char *s, char **endptr, int base)
246 int neg = 0;
247 long val = 0;
249 // gobble initial whitespace
250 while (*s == ' ' || *s == '\t')
251 s++;
253 // plus/minus sign
254 if (*s == '+')
255 s++;
256 else if (*s == '-')
257 s++, neg = 1;
259 // hex or octal base prefix
260 if ((base == 0 || base == 16) && (s[0] == '0' && s[1] == 'x'))
261 s += 2, base = 16;
262 else if (base == 0 && s[0] == '0')
263 s++, base = 8;
264 else if (base == 0)
265 base = 10;
267 // digits
268 while (1) {
269 int dig;
271 if (*s >= '0' && *s <= '9')
272 dig = *s - '0';
273 else if (*s >= 'a' && *s <= 'z')
274 dig = *s - 'a' + 10;
275 else if (*s >= 'A' && *s <= 'Z')
276 dig = *s - 'A' + 10;
277 else
278 break;
279 if (dig >= base)
280 break;
281 s++, val = (val * base) + dig;
282 // we don't properly detect overflow!
285 if (endptr)
286 *endptr = (char *) s;
287 return (neg ? -val : val);