blob: ec6be1dfb49d79eeb3c03f2031dd6082e2d705fc [file] [log] [blame]
Jordan Crousef6145c32008-03-19 23:56:58 +00001/*
2 * This file is part of the libpayload project.
3 *
4 * Copyright (C) 2007 Uwe Hermann <uwe@hermann-uwe.de>
5 * Copyright (C) 2008 Advanced Micro Devices, Inc.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31#include <libpayload.h>
Jordan Crousef6145c32008-03-19 23:56:58 +000032
33/**
34 * Calculate the length of a fixed-size string.
35 *
36 * @param str The input string.
37 * @param maxlen Return at most maxlen characters as length of the string.
38 * @return The length of the string, not including the final NUL character.
39 * The maximum length returned is maxlen.
40 */
41size_t strnlen(const char *str, size_t maxlen)
42{
43 size_t len = 0;
44
45 /* NULL and empty strings have length 0. */
46 if (!str)
47 return 0;
48
49 /* Loop until we find a NUL character, or maxlen is reached. */
50 while ((*str++ != '\0') && (len < maxlen))
51 len++;
52
53 return len;
54}
55
56/**
57 * Calculate the length of a string.
58 *
59 * @param str The input string.
60 * @return The length of the string, not including the final NUL character.
61 */
62size_t strlen(const char *str)
63{
64 size_t len = 0;
65
66 /* NULL and empty strings have length 0. */
67 if (!str)
68 return 0;
69
70 /* Loop until we find a NUL character. */
71 while (*str++ != '\0')
72 len++;
73
74 return len;
75}
76
77/**
78 * Compare two strings.
79 *
80 * @param s1 The first string.
81 * @param s2 The second string.
82 * @return Returns a value less than zero, if s1 is shorter than s2. Returns
83 * zero, if s1 equals s2. Returns a value greater than zero, if
84 * s1 is longer than s2.
85 */
86int strcmp(const char *s1, const char *s2)
87{
88 char c1, c2;
89
90 /* Set c1 == c2, so that we can enter the while loop. */
91 c1 = 0;
92 c2 = 0;
93
94 /* Compare characters until they differ, or one of the strings ends. */
95 while (c1 == c2) {
96 /* Read the next character from each string. */
97 c1 = *s1++;
98 c2 = *s2++;
99
100 /* Return something negative (if s1 is shorter than s2), or
101 zero (if s1 equals s2). */
102 if (c1 == '\0')
103 return c1 - c2;
104 }
105
Uwe Hermann661e3802008-03-21 18:37:23 +0000106 /* Return something positive (if s1 is longer than s2), or zero (if s1
Jordan Crousef6145c32008-03-19 23:56:58 +0000107 and s2 are equal). */
108 return c1 - c2;
109}
110
111/**
112 * Compare two strings with fixed length.
113 *
114 * @param s1 The first string.
115 * @param s2 The second string.
116 * @param maxlen Return at most maxlen characters as length of the string.
117 * @return A non-zero value if s1 and s2 differ, or zero if s1 equals s2.
118 */
Stefan Reinauer3b9d1b82008-08-26 21:51:04 +0000119int strncmp(const char *s1, const char *s2, size_t maxlen)
Jordan Crousef6145c32008-03-19 23:56:58 +0000120{
121 int i;
122
123 for (i = 0; i < maxlen; i++) {
124 if (s1[i] != s2[i])
125 return s1[i] - s2[i];
126 }
127
128 return 0;
129}
130
Stefan Reinauer41514392008-09-26 18:42:40 +0000131/**
132 * Copy a string with a maximum length.
133 *
134 * @param d The destination memory.
135 * @param s The source string.
136 * @param n Copy at most n characters as length of the string.
137 * @return A pointer to the destination memory.
138 */
Stefan Reinauer3b9d1b82008-08-26 21:51:04 +0000139char *strncpy(char *d, const char *s, size_t n)
Jordan Crousef6145c32008-03-19 23:56:58 +0000140{
Uwe Hermann29014052008-03-21 15:47:38 +0000141 /* Use +1 to get the NUL terminator. */
Jordan Crousef6145c32008-03-19 23:56:58 +0000142 int max = n > strlen(s) + 1 ? strlen(s) + 1 : n;
143 int i;
144
Uwe Hermann6a441bf2008-03-20 19:54:59 +0000145 for (i = 0; i < max; i++)
146 d[i] = (char)s[i];
Jordan Crousef6145c32008-03-19 23:56:58 +0000147
148 return d;
149}
150
Stefan Reinauer41514392008-09-26 18:42:40 +0000151/**
152 * Copy a string.
153 *
154 * @param d The destination memory.
155 * @param s The source string.
156 * @return A pointer to the destination memory.
157 */
Jordan Crouse2c7bb9e2008-03-20 01:13:28 +0000158char *strcpy(char *d, const char *s)
159{
Uwe Hermann29014052008-03-21 15:47:38 +0000160 return strncpy(d, s, strlen(s) + 1);
Jordan Crouse2c7bb9e2008-03-20 01:13:28 +0000161}
162
Stefan Reinauer41514392008-09-26 18:42:40 +0000163/**
164 * Concatenates two strings with a maximum length.
165 *
166 * @param d The destination string.
167 * @param s The source string.
168 * @param n The target string will have a length of n characters at most.
169 * @return A pointer to the destination string.
170 */
Stefan Reinauer3b9d1b82008-08-26 21:51:04 +0000171char *strncat(char *d, const char *s, size_t n)
Jordan Crousef6145c32008-03-19 23:56:58 +0000172{
173 char *p = d + strlen(d);
174 int max = n > strlen(s) ? strlen(s) : n;
175 int i;
176
Uwe Hermann6a441bf2008-03-20 19:54:59 +0000177 for (i = 0; i < max; i++)
Jordan Crousef6145c32008-03-19 23:56:58 +0000178 p[i] = s[i];
179
180 p[i] = '\0';
181 return d;
182}
183
Stefan Reinauer41514392008-09-26 18:42:40 +0000184/**
185 * Find a character in a string.
186 *
187 * @param s The string.
188 * @param c The character.
189 * @return A pointer to the first occurence of the character in the
190 * string, or NULL if the character was not encountered within the string.
191 */
Uwe Hermann6a441bf2008-03-20 19:54:59 +0000192char *strchr(const char *s, int c)
Jordan Crousef6145c32008-03-19 23:56:58 +0000193{
Uwe Hermann6a441bf2008-03-20 19:54:59 +0000194 char *p = (char *)s;
Jordan Crousef6145c32008-03-19 23:56:58 +0000195
Uwe Hermann6a441bf2008-03-20 19:54:59 +0000196 for (; *p != 0; p++) {
Jordan Crousef6145c32008-03-19 23:56:58 +0000197 if (*p == c)
198 return p;
199 }
200
201 return NULL;
202}
203
Stefan Reinauer41514392008-09-26 18:42:40 +0000204/**
205 * Duplicate a string.
206 *
207 * @param s The string to duplicate.
208 * @return A pointer to the copy of the original string.
209 */
Jordan Crousef6145c32008-03-19 23:56:58 +0000210char *strdup(const char *s)
211{
212 int n = strlen(s);
Jordan Crousec7815842008-04-25 23:07:39 +0000213 char *p = malloc(n + 1);
Jordan Crousef6145c32008-03-19 23:56:58 +0000214
Stefan Reinauerac29d612009-01-26 00:57:54 +0000215 if (p != NULL) {
Jordan Crousef6145c32008-03-19 23:56:58 +0000216 strncpy(p, s, n);
Stefan Reinauerac29d612009-01-26 00:57:54 +0000217 p[n] = 0;
218 }
Jordan Crousef6145c32008-03-19 23:56:58 +0000219 return p;
220}
221
Stefan Reinauer41514392008-09-26 18:42:40 +0000222/**
223 * Find a substring within a string.
224 *
225 * @param h The haystack string.
226 * @param n The needle string (substring).
227 * @return A pointer to the first occurence of the substring in
228 * the string, or NULL if the substring was not encountered within the string.
229 */
Jordan Crousef6145c32008-03-19 23:56:58 +0000230char *strstr(const char *h, const char *n)
231{
232 int hn = strlen(h);
233 int nn = strlen(n);
234 int i;
235
Uwe Hermann6a441bf2008-03-20 19:54:59 +0000236 for (i = 0; i <= hn - nn; i++)
Stefan Reinauer0d348f92009-03-06 17:43:20 +0000237 if (!memcmp(&h[i], n, nn))
Uwe Hermann6a441bf2008-03-20 19:54:59 +0000238 return (char *)&h[i];
Jordan Crousef6145c32008-03-19 23:56:58 +0000239
240 return NULL;
241}
Stefan Reinauer41514392008-09-26 18:42:40 +0000242
243/**
244 * Separate strings.
245 *
246 * @param stringp reference of the string to separate.
247 * @param delim string containing all delimiters.
248 * @return Token string.
249 */
250char *strsep(char **stringp, const char *delim)
251{
252 char *walk, *token;
253
254 if (!stringp || !*stringp || !**stringp)
255 return NULL;
256
257 token = walk = *stringp;
258
259 /* Walk, search for delimiters */
260 while(*walk && !strchr(delim, *walk))
261 walk++;
262
263 if (*walk) {
264 /* NUL terminate */
265 *walk = '\0';
266 walk++;
267 }
268
269 *stringp = walk;
270
271 return token;
272}
273
Jordan Crousec53cdd72008-10-20 17:07:47 +0000274/* Check that a character is in the valid range for the
275 given base
276*/
277
278static int _valid(char ch, int base)
279{
280 char end = (base > 9) ? '9' : '0' + (base - 1);
281
282 /* all bases will be some subset of the 0-9 range */
283
284 if (ch >= '0' && ch <= end)
285 return 1;
286
287 /* Bases > 11 will also have to match in the a-z range */
288
289 if (base > 11) {
290 if (tolower(ch) >= 'a' &&
291 tolower(ch) <= 'a' + (base - 11))
292 return 1;
293 }
294
295 return 0;
296}
297
298/* Return the "value" of the character in the given base */
299
300static int _offset(char ch, int base)
301{
302 if (ch >= '0' && ch <= '9')
303 return ch - '0';
304 else
305 return tolower(ch) - 'a';
306}
307
308/**
309 * Convert the initial portion of a string into an unsigned int
310 * @param ptr A pointer to the string to convert
311 * @param endptr A pointer to the unconverted part of the string
312 * @param base The base of the number to convert, or 0 for auto
313 * @return An unsigned integer representation of the string
314 */
315
316unsigned int strtoul(const char *ptr, char **endptr, int base)
317{
318 int ret = 0;
319
320 if (endptr != NULL)
321 *endptr = (char *) ptr;
322
323 /* Purge whitespace */
324
325 for( ; *ptr && isspace(*ptr); ptr++);
326
327 if (!*ptr)
328 return 0;
329
330 /* Determine the base */
331
332 if (base == 0) {
333 if (ptr[0] == '0' && (ptr[1] == 'x' || ptr[1] == 'X'))
334 base = 16;
335 else if (ptr[0] == '0') {
336 base = 8;
337 ptr++;
338 }
339 else
340 base = 10;
341 }
342
343 /* Base 16 allows the 0x on front - so skip over it */
344
345 if (base == 16) {
346 if (ptr[0] == '0' && (ptr[1] == 'x' || ptr[1] == 'X'))
347 ptr += 2;
348 }
349
350 /* If the first character isn't valid, then don't
351 * bother */
352
353 if (!*ptr || !_valid(*ptr, base))
354 return 0;
355
356 for( ; *ptr && _valid(*ptr, base); ptr++)
357 ret = (ret * base) + _offset(*ptr, base);
358
359 if (endptr != NULL)
360 *endptr = (char *) ptr;
361
362 return ret;
363}
364
365