pintos: Avoid literal control character in Perl variable name.
[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.  String literals,
216    in particular, are *not* modifiable in C, even though for
217    backward compatibility they are not `const'.
218
219    Example usage:
220
221    char s[] = "  String to  tokenize. ";
222    char *token, *save_ptr;
223
224    for (token = strtok_r (s, " ", &save_ptr); token != NULL;
225         token = strtok_r (NULL, " ", &save_ptr))
226      printf ("'%s'\n", token);
227
228    outputs:
229
230      'String'
231      'to'
232      'tokenize.'
233 */
234 char *
235 strtok_r (char *s, const char *delimiters, char **save_ptr) 
236 {
237   char *token;
238   
239   ASSERT (delimiters != NULL);
240   ASSERT (save_ptr != NULL);
241
242   /* If S is nonnull, start from it.
243      If S is null, start from saved position. */
244   if (s == NULL)
245     s = *save_ptr;
246   ASSERT (s != NULL);
247
248   /* Skip any DELIMITERS at our current position. */
249   while (strchr (delimiters, *s) != NULL) 
250     {
251       /* strchr() will always return nonnull if we're searching
252          for a null byte, because every string contains a null
253          byte (at the end). */
254       if (*s == '\0')
255         {
256           *save_ptr = s;
257           return NULL;
258         }
259
260       s++;
261     }
262
263   /* Skip any non-DELIMITERS up to the end of the string. */
264   token = s;
265   while (strchr (delimiters, *s) == NULL)
266     s++;
267   if (*s != '\0') 
268     {
269       *s = '\0';
270       *save_ptr = s + 1;
271     }
272   else 
273     *save_ptr = s;
274   return token;
275 }
276
277 /* Sets the SIZE bytes in DST to VALUE. */
278 void *
279 memset (void *dst_, int value, size_t size) 
280 {
281   unsigned char *dst = dst_;
282
283   ASSERT (dst != NULL || size == 0);
284   
285   while (size-- > 0)
286     *dst++ = value;
287
288   return dst_;
289 }
290
291 /* Returns the length of STRING. */
292 size_t
293 strlen (const char *string) 
294 {
295   const char *p;
296
297   ASSERT (string != NULL);
298
299   for (p = string; *p != '\0'; p++)
300     continue;
301   return p - string;
302 }
303
304 /* If STRING is less than MAXLEN characters in length, returns
305    its actual length.  Otherwise, returns MAXLEN. */
306 size_t
307 strnlen (const char *string, size_t maxlen) 
308 {
309   size_t length;
310
311   for (length = 0; string[length] != '\0' && length < maxlen; length++)
312     continue;
313   return length;
314 }
315
316 /* Copies string SRC to DST.  If SRC is longer than SIZE - 1
317    characters, only SIZE - 1 characters are copied.  A null
318    terminator is always written to DST, unless SIZE is 0.
319    Returns the length of SRC, not including the null terminator.
320
321    strlcpy() is not in the standard C library, but it is an
322    increasingly popular extension.  See
323    http://www.courtesan.com/todd/papers/strlcpy.html for
324    information on strlcpy(). */
325 size_t
326 strlcpy (char *dst, const char *src, size_t size) 
327 {
328   size_t src_len;
329
330   ASSERT (dst != NULL);
331   ASSERT (src != NULL);
332
333   src_len = strlen (src);
334   if (size > 0) 
335     {
336       size_t dst_len = size - 1;
337       if (src_len < dst_len)
338         dst_len = src_len;
339       memcpy (dst, src, dst_len);
340       dst[dst_len] = '\0';
341     }
342   return src_len;
343 }
344
345 /* Concatenates string SRC to DST.  The concatenated string is
346    limited to SIZE - 1 characters.  A null terminator is always
347    written to DST, unless SIZE is 0.  Returns the length that the
348    concatenated string would have assuming that there was
349    sufficient space, not including a null terminator.
350
351    strlcat() is not in the standard C library, but it is an
352    increasingly popular extension.  See
353    http://www.courtesan.com/todd/papers/strlcpy.html for
354    information on strlcpy(). */
355 size_t
356 strlcat (char *dst, const char *src, size_t size) 
357 {
358   size_t src_len, dst_len;
359
360   ASSERT (dst != NULL);
361   ASSERT (src != NULL);
362
363   src_len = strlen (src);
364   dst_len = strlen (dst);
365   if (size > 0 && dst_len < size) 
366     {
367       size_t copy_cnt = size - dst_len - 1;
368       if (src_len < copy_cnt)
369         copy_cnt = src_len;
370       memcpy (dst + dst_len, src, copy_cnt);
371       dst[dst_len + copy_cnt] = '\0';
372     }
373   return src_len + dst_len;
374 }
375