89fa1f05c01f130bce10948d493a10cac6d29063
[pintos-anon] / src / lib / string.c
1 #include <string.h>
2
3 #ifdef KERNEL
4 #define NDEBUG
5 #endif
6 #include <debug.h>
7
8 /* Copies SIZE bytes from SRC to DST, which must not overlap.
9    Returns DST. */
10 void *
11 memcpy (void *dst_, const void *src_, size_t size) 
12 {
13   unsigned char *dst = dst_;
14   const unsigned char *src = src_;
15
16   ASSERT (dst != NULL || size == 0);
17   ASSERT (src != NULL || size == 0);
18
19   while (size-- > 0)
20     *dst++ = *src++;
21
22   return dst_;
23 }
24
25 /* Copies SIZE bytes from SRC to DST, which are allowed to
26    overlap.  Returns DST. */
27 void *
28 memmove (void *dst_, const void *src_, size_t size) 
29 {
30   unsigned char *dst = dst_;
31   const unsigned char *src = src_;
32
33   ASSERT (dst != NULL || size == 0);
34   ASSERT (src != NULL || size == 0);
35
36   if (dst < src) 
37     {
38       while (size-- > 0)
39         *dst++ = *src++;
40     }
41   else 
42     {
43       dst += size;
44       src += size;
45       while (size-- > 0)
46         *--dst = *--src;
47     }
48
49   return dst;
50 }
51
52 /* Find the first differing byte in the two blocks of SIZE bytes
53    at A and B.  Returns a positive value if the byte in A is
54    greater, a negative value if the byte in B is greater, or zero
55    if blocks A and B are equal. */
56 int
57 memcmp (const void *a_, const void *b_, size_t size) 
58 {
59   const unsigned char *a = a_;
60   const unsigned char *b = b_;
61
62   ASSERT (a != NULL || size == 0);
63   ASSERT (b != NULL || size == 0);
64
65   for (; size-- > 0; a++, b++)
66     if (*a != *b)
67       return *a > *b ? +1 : -1;
68   return 0;
69 }
70
71 /* Finds the first differing characters in strings A and B.
72    Returns a positive value if the character in A (as an unsigned
73    char) is greater, a negative value if the character in B (as
74    an unsigned char) is greater, or zero if strings A and B are
75    equal. */
76 int
77 strcmp (const char *a_, const char *b_) 
78 {
79   const unsigned char *a = (const unsigned char *) a_;
80   const unsigned char *b = (const unsigned char *) b_;
81
82   ASSERT (a != NULL);
83   ASSERT (b != NULL);
84
85   while (*a != '\0' && *a == *b) 
86     {
87       a++;
88       b++;
89     }
90
91   return *a < *b ? -1 : *a > *b;
92 }
93
94 /* Returns a pointer to the first occurrence of CH in the first
95    SIZE bytes starting at BLOCK.  Returns a null pointer if CH
96    does not occur in BLOCK. */
97 void *
98 memchr (const void *block_, int ch_, size_t size) 
99 {
100   const unsigned char *block = block_;
101   unsigned char ch = ch_;
102
103   ASSERT (block != NULL || size == 0);
104
105   for (; size-- > 0; block++)
106     if (*block == ch)
107       return (void *) block;
108
109   return NULL;
110 }
111
112 /* Finds and returns the first occurrence of C in STRING, or a
113    null pointer if C does not appear in STRING.  If C == '\0'
114    then returns a pointer to the null terminator at the end of
115    STRING. */
116 char *
117 strchr (const char *string, int c_) 
118 {
119   char c = c_;
120
121   ASSERT (string != NULL);
122
123   for (;;) 
124     if (*string == c)
125       return (char *) string;
126     else if (*string == '\0')
127       return NULL;
128     else
129       string++;
130 }
131
132 /* Returns the length of the initial substring of STRING that
133    consists of characters that are not in STOP. */
134 size_t
135 strcspn (const char *string, const char *stop) 
136 {
137   size_t length;
138
139   for (length = 0; string[length] != '\0'; length++)
140     if (strchr (stop, string[length]) != NULL)
141       break;
142   return length;
143 }
144
145 /* Returns a pointer to the first character in STRING that is
146    also in STOP.  If no character in STRING is in STOP, returns a
147    null pointer. */
148 char *
149 strpbrk (const char *string, const char *stop) 
150 {
151   for (; *string != '\0'; string++)
152     if (strchr (stop, *string) != NULL)
153       return (char *) string;
154   return NULL;
155 }
156
157 /* Returns a pointer to the last occurrence of C in STRING.
158    Returns a null pointer if C does not occur in STRING. */
159 char *
160 strrchr (const char *string, int c_) 
161 {
162   char c = c_;
163   const char *p = NULL;
164
165   for (; *string != '\0'; string++)
166     if (*string == c)
167       p = string;
168   return (char *) p;
169 }
170
171 /* Returns the length of the initial substring of STRING that
172    consists of characters in SKIP. */
173 size_t
174 strspn (const char *string, const char *skip) 
175 {
176   size_t length;
177   
178   for (length = 0; string[length] != '\0'; length++)
179     if (strchr (skip, string[length]) == NULL)
180       break;
181   return length;
182 }
183
184 /* Returns a pointer to the first occurrence of NEEDLE within
185    HAYSTACK.  Returns a null pointer if NEEDLE does not exist
186    within HAYSTACK. */
187 char *
188 strstr (const char *haystack, const char *needle) 
189 {
190   size_t haystack_len = strlen (haystack);
191   size_t needle_len = strlen (needle);
192
193   if (haystack_len >= needle_len) 
194     {
195       size_t i;
196
197       for (i = 0; i < haystack_len - needle_len; i++)
198         if (!memcmp (haystack + i, needle, needle_len))
199           return (char *) haystack + i;
200     }
201
202   return NULL;
203 }
204
205 /* Breaks a string into tokens separated by DELIMITERS.  The
206    first time this function is called, S should be the string to
207    tokenize, and in subsequent calls it must be a null pointer.
208    SAVE_PTR is the address of a `char *' variable used to keep
209    track of the tokenizer's position.  The return value each time
210    is the next token in the string, or a null pointer if no
211    tokens remain.
212
213    This function treats multiple adjacent delimiters as a single
214    delimiter.  The returned tokens will never be length 0.
215    DELIMITERS may change from one call to the next within a
216    single string.
217
218    strtok_r() modifies the string S, changing delimiters to null
219    bytes.  Thus, S must be a modifiable string.  String literals,
220    in particular, are *not* modifiable in C, even though for
221    backward compatibility they are not `const'.
222
223    Example usage:
224
225    char s[] = "  String to  tokenize. ";
226    char *token, *save_ptr;
227
228    for (token = strtok_r (s, " ", &save_ptr); token != NULL;
229         token = strtok_r (NULL, " ", &save_ptr))
230      printf ("'%s'\n", token);
231
232    outputs:
233
234      'String'
235      'to'
236      'tokenize.'
237 */
238 char *
239 strtok_r (char *s, const char *delimiters, char **save_ptr) 
240 {
241   char *token;
242   
243   ASSERT (delimiters != NULL);
244   ASSERT (save_ptr != NULL);
245
246   /* If S is nonnull, start from it.
247      If S is null, start from saved position. */
248   if (s == NULL)
249     s = *save_ptr;
250   ASSERT (s != NULL);
251
252   /* Skip any DELIMITERS at our current position. */
253   while (strchr (delimiters, *s) != NULL) 
254     {
255       /* strchr() will always return nonnull if we're searching
256          for a null byte, because every string contains a null
257          byte (at the end). */
258       if (*s == '\0')
259         {
260           *save_ptr = s;
261           return NULL;
262         }
263
264       s++;
265     }
266
267   /* Skip any non-DELIMITERS up to the end of the string. */
268   token = s;
269   while (strchr (delimiters, *s) == NULL)
270     s++;
271   if (*s != '\0') 
272     {
273       *s = '\0';
274       *save_ptr = s + 1;
275     }
276   else 
277     *save_ptr = s;
278   return token;
279 }
280
281 /* Sets the SIZE bytes in DST to VALUE. */
282 void *
283 memset (void *dst_, int value, size_t size) 
284 {
285   unsigned char *dst = dst_;
286
287   ASSERT (dst != NULL || size == 0);
288   
289   while (size-- > 0)
290     *dst++ = value;
291
292   return dst_;
293 }
294
295 /* Returns the length of STRING. */
296 size_t
297 strlen (const char *string) 
298 {
299   const char *p;
300
301   ASSERT (string != NULL);
302
303   for (p = string; *p != '\0'; p++)
304     continue;
305   return p - string;
306 }
307
308 /* If STRING is less than MAXLEN characters in length, returns
309    its actual length.  Otherwise, returns MAXLEN. */
310 size_t
311 strnlen (const char *string, size_t maxlen) 
312 {
313   size_t length;
314
315   for (length = 0; string[length] != '\0' && length < maxlen; length++)
316     continue;
317   return length;
318 }
319
320 /* Copies string SRC to DST.  If SRC is longer than SIZE - 1
321    characters, only SIZE - 1 characters are copied.  A null
322    terminator is always written to DST, unless SIZE is 0.
323    Returns the length of SRC, not including the null terminator.
324
325    strlcpy() is not in the standard C library, but it is an
326    increasingly popular extension.  See
327    http://www.courtesan.com/todd/papers/strlcpy.html for
328    information on strlcpy(). */
329 size_t
330 strlcpy (char *dst, const char *src, size_t size) 
331 {
332   size_t src_len;
333
334   ASSERT (dst != NULL);
335   ASSERT (src != NULL);
336
337   src_len = strlen (src);
338   if (size > 0) 
339     {
340       size_t dst_len = size - 1;
341       if (src_len < dst_len)
342         dst_len = src_len;
343       memcpy (dst, src, dst_len);
344       dst[dst_len] = '\0';
345     }
346   return src_len;
347 }
348
349 /* Concatenates string SRC to DST.  The concatenated string is
350    limited to SIZE - 1 characters.  A null terminator is always
351    written to DST, unless SIZE is 0.  Returns the length that the
352    concatenated string would have assuming that there was
353    sufficient space, not including a null terminator.
354
355    strlcat() is not in the standard C library, but it is an
356    increasingly popular extension.  See
357    http://www.courtesan.com/todd/papers/strlcpy.html for
358    information on strlcpy(). */
359 size_t
360 strlcat (char *dst, const char *src, size_t size) 
361 {
362   size_t src_len, dst_len;
363
364   ASSERT (dst != NULL);
365   ASSERT (src != NULL);
366
367   src_len = strlen (src);
368   dst_len = strlen (dst);
369   if (size > 0 && dst_len < size) 
370     {
371       size_t copy_cnt = size - dst_len - 1;
372       if (src_len < copy_cnt)
373         copy_cnt = src_len;
374       memcpy (dst + dst_len, src, copy_cnt);
375       dst[dst_len + copy_cnt] = '\0';
376     }
377   return src_len + dst_len;
378 }
379