blob: ce5767e4b08600e97b8629639b96750cf7c05203 [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.
Patrick Georgi980a69b2010-06-24 11:16:10 +00006 * Copyright (C) 2010 coresystems GmbH
Jordan Crousef6145c32008-03-19 23:56:58 +00007 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32#include <libpayload.h>
Patrick Georgi980a69b2010-06-24 11:16:10 +000033#include <string.h>
34#include <ctype.h>
35#include <errno.h>
Jordan Crousef6145c32008-03-19 23:56:58 +000036
37/**
38 * Calculate the length of a fixed-size string.
39 *
40 * @param str The input string.
41 * @param maxlen Return at most maxlen characters as length of the string.
42 * @return The length of the string, not including the final NUL character.
43 * The maximum length returned is maxlen.
44 */
45size_t strnlen(const char *str, size_t maxlen)
46{
47 size_t len = 0;
48
49 /* NULL and empty strings have length 0. */
50 if (!str)
51 return 0;
52
53 /* Loop until we find a NUL character, or maxlen is reached. */
54 while ((*str++ != '\0') && (len < maxlen))
55 len++;
56
57 return len;
58}
59
60/**
61 * Calculate the length of a string.
62 *
63 * @param str The input string.
64 * @return The length of the string, not including the final NUL character.
65 */
66size_t strlen(const char *str)
67{
68 size_t len = 0;
69
70 /* NULL and empty strings have length 0. */
71 if (!str)
72 return 0;
73
74 /* Loop until we find a NUL character. */
75 while (*str++ != '\0')
76 len++;
77
78 return len;
79}
80
81/**
82 * Compare two strings.
83 *
84 * @param s1 The first string.
85 * @param s2 The second string.
86 * @return Returns a value less than zero, if s1 is shorter than s2. Returns
87 * zero, if s1 equals s2. Returns a value greater than zero, if
88 * s1 is longer than s2.
89 */
Patrick Georgi980a69b2010-06-24 11:16:10 +000090int strcasecmp(const char *s1, const char *s2)
Jordan Crousef6145c32008-03-19 23:56:58 +000091{
Liu Taoe914b502010-09-08 10:27:13 +000092 int i, res;
Jordan Crousef6145c32008-03-19 23:56:58 +000093
Liu Taoe914b502010-09-08 10:27:13 +000094 for (i = 0; 1; i++) {
95 res = tolower(s1[i]) - tolower(s2[i]);
96 if (res || (s1[i] == '\0'))
97 break;
Jordan Crousef6145c32008-03-19 23:56:58 +000098 }
99
Liu Taoe914b502010-09-08 10:27:13 +0000100 return res;
Patrick Georgi980a69b2010-06-24 11:16:10 +0000101}
102
103/**
104 * Compare two strings with fixed length.
105 *
106 * @param s1 The first string.
107 * @param s2 The second string.
108 * @param maxlen Return at most maxlen characters as length of the string.
109 * @return A non-zero value if s1 and s2 differ, or zero if s1 equals s2.
110 */
111int strncasecmp(const char *s1, const char *s2, size_t maxlen)
112{
Liu Taoe914b502010-09-08 10:27:13 +0000113 int i, res;
Patrick Georgi980a69b2010-06-24 11:16:10 +0000114
Liu Taoe914b502010-09-08 10:27:13 +0000115 res = 0;
Patrick Georgi980a69b2010-06-24 11:16:10 +0000116 for (i = 0; i < maxlen; i++) {
Liu Taoe914b502010-09-08 10:27:13 +0000117 res = tolower(s1[i]) - tolower(s2[i]);
118 if (res || (s1[i] == '\0'))
119 break;
Patrick Georgi980a69b2010-06-24 11:16:10 +0000120 }
121
Liu Taoe914b502010-09-08 10:27:13 +0000122 return res;
Patrick Georgi980a69b2010-06-24 11:16:10 +0000123}
124
125/**
126 * Compare two strings.
127 *
128 * @param s1 The first string.
129 * @param s2 The second string.
130 * @return Returns a value less than zero, if s1 is shorter than s2. Returns
131 * zero, if s1 equals s2. Returns a value greater than zero, if
132 * s1 is longer than s2.
133 */
134int strcmp(const char *s1, const char *s2)
135{
Liu Taoe914b502010-09-08 10:27:13 +0000136 int i, res;
Patrick Georgi980a69b2010-06-24 11:16:10 +0000137
Liu Taoe914b502010-09-08 10:27:13 +0000138 for (i = 0; 1; i++) {
139 res = s1[i] - s2[i];
140 if (res || (s1[i] == '\0'))
141 break;
Patrick Georgi980a69b2010-06-24 11:16:10 +0000142 }
143
Liu Taoe914b502010-09-08 10:27:13 +0000144 return res;
Jordan Crousef6145c32008-03-19 23:56:58 +0000145}
146
147/**
148 * Compare two strings with fixed length.
149 *
150 * @param s1 The first string.
151 * @param s2 The second string.
152 * @param maxlen Return at most maxlen characters as length of the string.
153 * @return A non-zero value if s1 and s2 differ, or zero if s1 equals s2.
154 */
Stefan Reinauer3b9d1b82008-08-26 21:51:04 +0000155int strncmp(const char *s1, const char *s2, size_t maxlen)
Jordan Crousef6145c32008-03-19 23:56:58 +0000156{
Liu Taoe914b502010-09-08 10:27:13 +0000157 int i, res;
Jordan Crousef6145c32008-03-19 23:56:58 +0000158
Liu Taoe914b502010-09-08 10:27:13 +0000159 res = 0;
Jordan Crousef6145c32008-03-19 23:56:58 +0000160 for (i = 0; i < maxlen; i++) {
Liu Taoe914b502010-09-08 10:27:13 +0000161 res = s1[i] - s2[i];
162 if (res || (s1[i] == '\0'))
163 break;
Jordan Crousef6145c32008-03-19 23:56:58 +0000164 }
165
Liu Taoe914b502010-09-08 10:27:13 +0000166 return res;
Jordan Crousef6145c32008-03-19 23:56:58 +0000167}
168
Stefan Reinauer41514392008-09-26 18:42:40 +0000169/**
170 * Copy a string with a maximum length.
171 *
172 * @param d The destination memory.
173 * @param s The source string.
174 * @param n Copy at most n characters as length of the string.
175 * @return A pointer to the destination memory.
176 */
Stefan Reinauer3b9d1b82008-08-26 21:51:04 +0000177char *strncpy(char *d, const char *s, size_t n)
Jordan Crousef6145c32008-03-19 23:56:58 +0000178{
Uwe Hermann29014052008-03-21 15:47:38 +0000179 /* Use +1 to get the NUL terminator. */
Jordan Crousef6145c32008-03-19 23:56:58 +0000180 int max = n > strlen(s) + 1 ? strlen(s) + 1 : n;
181 int i;
182
Uwe Hermann6a441bf2008-03-20 19:54:59 +0000183 for (i = 0; i < max; i++)
184 d[i] = (char)s[i];
Jordan Crousef6145c32008-03-19 23:56:58 +0000185
186 return d;
187}
188
Stefan Reinauer41514392008-09-26 18:42:40 +0000189/**
190 * Copy a string.
191 *
192 * @param d The destination memory.
193 * @param s The source string.
194 * @return A pointer to the destination memory.
195 */
Jordan Crouse2c7bb9e2008-03-20 01:13:28 +0000196char *strcpy(char *d, const char *s)
197{
Uwe Hermann29014052008-03-21 15:47:38 +0000198 return strncpy(d, s, strlen(s) + 1);
Jordan Crouse2c7bb9e2008-03-20 01:13:28 +0000199}
200
Stefan Reinauer41514392008-09-26 18:42:40 +0000201/**
Patrick Georgi980a69b2010-06-24 11:16:10 +0000202 * Concatenates two strings
203 *
204 * @param d The destination string.
205 * @param s The source string.
206 * @return A pointer to the destination string.
207 */
208char *strcat(char *d, const char *s)
209{
210 char *p = d + strlen(d);
211 int sl = strlen(s);
212 int i;
213
214 for (i = 0; i < sl; i++)
215 p[i] = s[i];
216
217 p[i] = '\0';
218 return d;
219}
220
221/**
Stefan Reinauer41514392008-09-26 18:42:40 +0000222 * Concatenates two strings with a maximum length.
223 *
224 * @param d The destination string.
225 * @param s The source string.
Stefan Reinauer052d5912009-08-05 13:10:38 +0000226 * @param n Not more than n characters from s will be appended to d.
Stefan Reinauer41514392008-09-26 18:42:40 +0000227 * @return A pointer to the destination string.
228 */
Stefan Reinauer3b9d1b82008-08-26 21:51:04 +0000229char *strncat(char *d, const char *s, size_t n)
Jordan Crousef6145c32008-03-19 23:56:58 +0000230{
231 char *p = d + strlen(d);
Stefan Reinauere5d30b72010-03-25 22:15:19 +0000232 int sl = strlen(s);
233 int max = n > sl ? sl : n;
234 // int max = n > strlen(s) ? strlen(s) : n;
Jordan Crousef6145c32008-03-19 23:56:58 +0000235 int i;
236
Uwe Hermann6a441bf2008-03-20 19:54:59 +0000237 for (i = 0; i < max; i++)
Jordan Crousef6145c32008-03-19 23:56:58 +0000238 p[i] = s[i];
239
240 p[i] = '\0';
241 return d;
242}
243
Stefan Reinauer41514392008-09-26 18:42:40 +0000244/**
Stefan Reinauere5d30b72010-03-25 22:15:19 +0000245 * Concatenates two strings with a maximum length.
246 *
247 * @param d The destination string.
248 * @param s The source string.
249 * @param n Not more than n characters from s will be appended to d.
250 * @return A pointer to the destination string.
251 */
252size_t strlcat(char *d, const char *s, size_t n)
253{
254 int sl = strlen(s);
255 int dl = strlen(d);
256
257 char *p = d + dl;
258 int max = n > (sl + dl) ? sl : (n - dl - 1);
259 int i;
260
261 for (i = 0; i < max; i++)
262 p[i] = s[i];
263
264 p[i] = '\0';
265 return max;
266}
267
268/**
Stefan Reinauer41514392008-09-26 18:42:40 +0000269 * Find a character in a string.
270 *
271 * @param s The string.
272 * @param c The character.
273 * @return A pointer to the first occurence of the character in the
274 * string, or NULL if the character was not encountered within the string.
275 */
Uwe Hermann6a441bf2008-03-20 19:54:59 +0000276char *strchr(const char *s, int c)
Jordan Crousef6145c32008-03-19 23:56:58 +0000277{
Uwe Hermann6a441bf2008-03-20 19:54:59 +0000278 char *p = (char *)s;
Jordan Crousef6145c32008-03-19 23:56:58 +0000279
Uwe Hermann6a441bf2008-03-20 19:54:59 +0000280 for (; *p != 0; p++) {
Jordan Crousef6145c32008-03-19 23:56:58 +0000281 if (*p == c)
282 return p;
283 }
284
285 return NULL;
286}
287
Stefan Reinauer41514392008-09-26 18:42:40 +0000288/**
Stefan Reinauere5d30b72010-03-25 22:15:19 +0000289 * Find a character in a string.
290 *
291 * @param s The string.
292 * @param c The character.
293 * @return A pointer to the last occurence of the character in the
294 * string, or NULL if the character was not encountered within the string.
295 */
296
297char *strrchr(const char *s, int c)
298{
299 char *p = (char *)s + strlen(s);
300
301 for (; p >= s; p--) {
302 if (*p == c)
303 return p;
304 }
305
306 return NULL;
307}
308
309/**
Stefan Reinauer41514392008-09-26 18:42:40 +0000310 * Duplicate a string.
311 *
312 * @param s The string to duplicate.
313 * @return A pointer to the copy of the original string.
314 */
Jordan Crousef6145c32008-03-19 23:56:58 +0000315char *strdup(const char *s)
316{
317 int n = strlen(s);
Jordan Crousec7815842008-04-25 23:07:39 +0000318 char *p = malloc(n + 1);
Jordan Crousef6145c32008-03-19 23:56:58 +0000319
Stefan Reinauerac29d612009-01-26 00:57:54 +0000320 if (p != NULL) {
Jordan Crousef6145c32008-03-19 23:56:58 +0000321 strncpy(p, s, n);
Stefan Reinauerac29d612009-01-26 00:57:54 +0000322 p[n] = 0;
323 }
Jordan Crousef6145c32008-03-19 23:56:58 +0000324 return p;
325}
326
Stefan Reinauer41514392008-09-26 18:42:40 +0000327/**
328 * Find a substring within a string.
329 *
330 * @param h The haystack string.
331 * @param n The needle string (substring).
332 * @return A pointer to the first occurence of the substring in
333 * the string, or NULL if the substring was not encountered within the string.
334 */
Jordan Crousef6145c32008-03-19 23:56:58 +0000335char *strstr(const char *h, const char *n)
336{
337 int hn = strlen(h);
338 int nn = strlen(n);
339 int i;
340
Uwe Hermann6a441bf2008-03-20 19:54:59 +0000341 for (i = 0; i <= hn - nn; i++)
Stefan Reinauer0d348f92009-03-06 17:43:20 +0000342 if (!memcmp(&h[i], n, nn))
Uwe Hermann6a441bf2008-03-20 19:54:59 +0000343 return (char *)&h[i];
Jordan Crousef6145c32008-03-19 23:56:58 +0000344
345 return NULL;
346}
Stefan Reinauer41514392008-09-26 18:42:40 +0000347
348/**
349 * Separate strings.
350 *
351 * @param stringp reference of the string to separate.
352 * @param delim string containing all delimiters.
353 * @return Token string.
354 */
355char *strsep(char **stringp, const char *delim)
356{
357 char *walk, *token;
358
359 if (!stringp || !*stringp || !**stringp)
360 return NULL;
361
362 token = walk = *stringp;
363
364 /* Walk, search for delimiters */
365 while(*walk && !strchr(delim, *walk))
366 walk++;
367
368 if (*walk) {
369 /* NUL terminate */
370 *walk = '\0';
371 walk++;
372 }
373
374 *stringp = walk;
375
376 return token;
377}
378
Jordan Crousec53cdd72008-10-20 17:07:47 +0000379/* Check that a character is in the valid range for the
380 given base
381*/
382
383static int _valid(char ch, int base)
384{
385 char end = (base > 9) ? '9' : '0' + (base - 1);
386
387 /* all bases will be some subset of the 0-9 range */
388
389 if (ch >= '0' && ch <= end)
390 return 1;
391
392 /* Bases > 11 will also have to match in the a-z range */
393
394 if (base > 11) {
395 if (tolower(ch) >= 'a' &&
396 tolower(ch) <= 'a' + (base - 11))
397 return 1;
398 }
399
400 return 0;
401}
402
403/* Return the "value" of the character in the given base */
404
405static int _offset(char ch, int base)
406{
407 if (ch >= '0' && ch <= '9')
408 return ch - '0';
409 else
410 return tolower(ch) - 'a';
411}
412
413/**
Patrick Georgi980a69b2010-06-24 11:16:10 +0000414 * Convert the initial portion of a string into a signed int
415 * @param ptr A pointer to the string to convert
416 * @param endptr A pointer to the unconverted part of the string
417 * @param base The base of the number to convert, or 0 for auto
418 * @return A signed integer representation of the string
419 */
420
421long int strtol(const char *ptr, char **endptr, int base)
422{
423 int ret = 0;
424 int negative = 1;
425
426 if (endptr != NULL)
427 *endptr = (char *) ptr;
428
429 /* Purge whitespace */
430
431 for( ; *ptr && isspace(*ptr); ptr++);
432
433 if (ptr[0] == '-') {
434 negative = -1;
435 ptr++;
436 }
437
438 if (!*ptr)
439 return 0;
440
441 /* Determine the base */
442
443 if (base == 0) {
444 if (ptr[0] == '0' && (ptr[1] == 'x' || ptr[1] == 'X'))
445 base = 16;
446 else if (ptr[0] == '0') {
447 base = 8;
448 ptr++;
449 }
450 else
451 base = 10;
452 }
453
454 /* Base 16 allows the 0x on front - so skip over it */
455
456 if (base == 16) {
457 if (ptr[0] == '0' && (ptr[1] == 'x' || ptr[1] == 'X'))
458 ptr += 2;
459 }
460
461 /* If the first character isn't valid, then don't
462 * bother */
463
464 if (!*ptr || !_valid(*ptr, base))
465 return 0;
466
467 for( ; *ptr && _valid(*ptr, base); ptr++)
468 ret = (ret * base) + _offset(*ptr, base);
469
470 if (endptr != NULL)
471 *endptr = (char *) ptr;
472
473 return ret * negative;
474}
475
476/**
Jordan Crousec53cdd72008-10-20 17:07:47 +0000477 * Convert the initial portion of a string into an unsigned int
478 * @param ptr A pointer to the string to convert
479 * @param endptr A pointer to the unconverted part of the string
480 * @param base The base of the number to convert, or 0 for auto
481 * @return An unsigned integer representation of the string
482 */
483
Patrick Georgi980a69b2010-06-24 11:16:10 +0000484unsigned long int strtoul(const char *ptr, char **endptr, int base)
Jordan Crousec53cdd72008-10-20 17:07:47 +0000485{
486 int ret = 0;
487
488 if (endptr != NULL)
489 *endptr = (char *) ptr;
490
491 /* Purge whitespace */
492
493 for( ; *ptr && isspace(*ptr); ptr++);
494
495 if (!*ptr)
496 return 0;
497
498 /* Determine the base */
499
500 if (base == 0) {
501 if (ptr[0] == '0' && (ptr[1] == 'x' || ptr[1] == 'X'))
502 base = 16;
503 else if (ptr[0] == '0') {
504 base = 8;
505 ptr++;
506 }
507 else
508 base = 10;
509 }
510
511 /* Base 16 allows the 0x on front - so skip over it */
512
513 if (base == 16) {
514 if (ptr[0] == '0' && (ptr[1] == 'x' || ptr[1] == 'X'))
515 ptr += 2;
516 }
517
518 /* If the first character isn't valid, then don't
519 * bother */
520
521 if (!*ptr || !_valid(*ptr, base))
522 return 0;
523
524 for( ; *ptr && _valid(*ptr, base); ptr++)
525 ret = (ret * base) + _offset(*ptr, base);
526
527 if (endptr != NULL)
528 *endptr = (char *) ptr;
529
530 return ret;
531}
532
Patrick Georgi980a69b2010-06-24 11:16:10 +0000533/**
534 * Determine the number of leading characters in s that match characters in a
535 * @param s A pointer to the string to analyse
536 * @param a A pointer to an array of characters that match the prefix
537 * @return The number of matching characters
538 */
Jordan Crousec53cdd72008-10-20 17:07:47 +0000539
Patrick Georgi980a69b2010-06-24 11:16:10 +0000540size_t strspn(const char *s, const char *a)
541{
542 int i, j;
543 int al = strlen(a);
544 for (i = 0; s[i] != 0; i++) {
545 int found = 0;
546 for (j = 0; j < al; j++) {
547 if (s[i] == a[j]) {
548 found = 1;
549 break;
550 }
551 }
552 if (!found)
553 break;
554 }
555 return i;
556}
557
558/**
559 * Determine the number of leading characters in s that do not match characters in a
560 * @param s A pointer to the string to analyse
561 * @param a A pointer to an array of characters that do not match the prefix
562 * @return The number of not matching characters
563 */
564
565size_t strcspn(const char *s, const char *a)
566{
567 int i, j;
568 int al = strlen(a);
569 for (i = 0; s[i] != 0; i++) {
570 int found = 0;
571 for (j = 0; j < al; j++) {
572 if (s[i] == a[j]) {
573 found = 1;
574 break;
575 }
576 }
577 if (found)
578 break;
579 }
580 return i;
581}
582
583/**
584 * Extract first token in string str that is delimited by a character in tokens.
585 * Destroys str and eliminates the token delimiter.
586 * @param str A pointer to the string to tokenize.
587 * @param delim A pointer to an array of characters that delimit the token
588 * @param ptr A pointer to a string pointer to keep state of the tokenizer
589 * @return Pointer to token
590 */
591
592char* strtok_r(char *str, const char *delim, char **ptr)
593{
594 /* start new tokenizing job or continue existing one? */
595 if (str == NULL)
596 str = *ptr;
597
598 /* skip over prefix delimiters */
599 char *start = str + strspn(str, delim);
600
601 /* find first delimiter character */
602 char *end = start + strcspn(start, delim);
603 end[0] = '\0';
604
605 *ptr = end+1;
606 return start;
607}
608
609static char **strtok_global;
610
611/**
612 * Extract first token in string str that is delimited by a character in tokens.
613 * Destroys str, eliminates the token delimiter and uses global state.
614 * @param str A pointer to the string to tokenize.
615 * @param delim A pointer to an array of characters that delimit the token
616 * @return Pointer to token
617 */
618
619char* strtok(char *str, const char *delim)
620{
621 return strtok_r(str, delim, strtok_global);
622}
623
624/**
625 * Print error message and error number
626 * @param s Error message to print
627 */
628void perror(const char *s)
629{
630 printf("%s: %d\n", s?s:"(none)", errno);
631}