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