forked from runshenzhu/6.828-MIT-OS
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathstring.c
285 lines (244 loc) · 4.71 KB
/
string.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
// Basic string routines. Not hardware optimized, but not shabby.
#include <inc/string.h>
// Using assembly for memset/memmove
// makes some difference on real hardware,
// but it makes an even bigger difference on bochs.
// Primespipe runs 3x faster this way.
#define ASM 1
int
strlen(const char *s)
{
int n;
for (n = 0; *s != '\0'; s++)
n++;
return n;
}
int
strnlen(const char *s, size_t size)
{
int n;
for (n = 0; size > 0 && *s != '\0'; s++, size--)
n++;
return n;
}
char *
strcpy(char *dst, const char *src)
{
char *ret;
ret = dst;
while ((*dst++ = *src++) != '\0')
/* do nothing */;
return ret;
}
char *
strcat(char *dst, const char *src)
{
int len = strlen(dst);
strcpy(dst + len, src);
return dst;
}
char *
strncpy(char *dst, const char *src, size_t size) {
size_t i;
char *ret;
ret = dst;
for (i = 0; i < size; i++) {
*dst++ = *src;
// If strlen(src) < size, null-pad 'dst' out to 'size' chars
if (*src != '\0')
src++;
}
return ret;
}
size_t
strlcpy(char *dst, const char *src, size_t size)
{
char *dst_in;
dst_in = dst;
if (size > 0) {
while (--size > 0 && *src != '\0')
*dst++ = *src++;
*dst = '\0';
}
return dst - dst_in;
}
int
strcmp(const char *p, const char *q)
{
while (*p && *p == *q)
p++, q++;
return (int) ((unsigned char) *p - (unsigned char) *q);
}
int
strncmp(const char *p, const char *q, size_t n)
{
while (n > 0 && *p && *p == *q)
n--, p++, q++;
if (n == 0)
return 0;
else
return (int) ((unsigned char) *p - (unsigned char) *q);
}
// Return a pointer to the first occurrence of 'c' in 's',
// or a null pointer if the string has no 'c'.
char *
strchr(const char *s, char c)
{
for (; *s; s++)
if (*s == c)
return (char *) s;
return 0;
}
// Return a pointer to the first occurrence of 'c' in 's',
// or a pointer to the string-ending null character if the string has no 'c'.
char *
strfind(const char *s, char c)
{
for (; *s; s++)
if (*s == c)
break;
return (char *) s;
}
#if ASM
void *
memset(void *v, int c, size_t n)
{
char *p;
if (n == 0)
return v;
if ((int)v%4 == 0 && n%4 == 0) {
c &= 0xFF;
c = (c<<24)|(c<<16)|(c<<8)|c;
asm volatile("cld; rep stosl\n"
:: "D" (v), "a" (c), "c" (n/4)
: "cc", "memory");
} else
asm volatile("cld; rep stosb\n"
:: "D" (v), "a" (c), "c" (n)
: "cc", "memory");
return v;
}
void *
memmove(void *dst, const void *src, size_t n)
{
const char *s;
char *d;
s = src;
d = dst;
if (s < d && s + n > d) {
s += n;
d += n;
if ((int)s%4 == 0 && (int)d%4 == 0 && n%4 == 0)
asm volatile("std; rep movsl\n"
:: "D" (d-4), "S" (s-4), "c" (n/4) : "cc", "memory");
else
asm volatile("std; rep movsb\n"
:: "D" (d-1), "S" (s-1), "c" (n) : "cc", "memory");
// Some versions of GCC rely on DF being clear
asm volatile("cld" ::: "cc");
} else {
if ((int)s%4 == 0 && (int)d%4 == 0 && n%4 == 0)
asm volatile("cld; rep movsl\n"
:: "D" (d), "S" (s), "c" (n/4) : "cc", "memory");
else
asm volatile("cld; rep movsb\n"
:: "D" (d), "S" (s), "c" (n) : "cc", "memory");
}
return dst;
}
#else
void *
memset(void *v, int c, size_t n)
{
char *p;
int m;
p = v;
m = n;
while (--m >= 0)
*p++ = c;
return v;
}
void *
memmove(void *dst, const void *src, size_t n)
{
const char *s;
char *d;
s = src;
d = dst;
if (s < d && s + n > d) {
s += n;
d += n;
while (n-- > 0)
*--d = *--s;
} else
while (n-- > 0)
*d++ = *s++;
return dst;
}
#endif
void *
memcpy(void *dst, const void *src, size_t n)
{
return memmove(dst, src, n);
}
int
memcmp(const void *v1, const void *v2, size_t n)
{
const uint8_t *s1 = (const uint8_t *) v1;
const uint8_t *s2 = (const uint8_t *) v2;
while (n-- > 0) {
if (*s1 != *s2)
return (int) *s1 - (int) *s2;
s1++, s2++;
}
return 0;
}
void *
memfind(const void *s, int c, size_t n)
{
const void *ends = (const char *) s + n;
for (; s < ends; s++)
if (*(const unsigned char *) s == (unsigned char) c)
break;
return (void *) s;
}
long
strtol(const char *s, char **endptr, int base)
{
int neg = 0;
long val = 0;
// gobble initial whitespace
while (*s == ' ' || *s == '\t')
s++;
// plus/minus sign
if (*s == '+')
s++;
else if (*s == '-')
s++, neg = 1;
// hex or octal base prefix
if ((base == 0 || base == 16) && (s[0] == '0' && s[1] == 'x'))
s += 2, base = 16;
else if (base == 0 && s[0] == '0')
s++, base = 8;
else if (base == 0)
base = 10;
// digits
while (1) {
int dig;
if (*s >= '0' && *s <= '9')
dig = *s - '0';
else if (*s >= 'a' && *s <= 'z')
dig = *s - 'a' + 10;
else if (*s >= 'A' && *s <= 'Z')
dig = *s - 'A' + 10;
else
break;
if (dig >= base)
break;
s++, val = (val * base) + dig;
// we don't properly detect overflow!
}
if (endptr)
*endptr = (char *) s;
return (neg ? -val : val);
}