blob: a58efde13573b165d00895f4a435feab510579ce [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>
Patrick Georgic643fdd2011-07-26 12:51:59 +020035#include <inttypes.h>
Patrick Georgi980a69b2010-06-24 11:16:10 +000036#include <errno.h>
Jordan Crousef6145c32008-03-19 23:56:58 +000037
38/**
39 * Calculate the length of a fixed-size string.
40 *
41 * @param str The input string.
42 * @param maxlen Return at most maxlen characters as length of the string.
43 * @return The length of the string, not including the final NUL character.
44 * The maximum length returned is maxlen.
45 */
46size_t strnlen(const char *str, size_t maxlen)
47{
48 size_t len = 0;
49
50 /* NULL and empty strings have length 0. */
51 if (!str)
52 return 0;
53
54 /* Loop until we find a NUL character, or maxlen is reached. */
55 while ((*str++ != '\0') && (len < maxlen))
56 len++;
57
58 return len;
59}
60
61/**
62 * Calculate the length of a string.
63 *
64 * @param str The input string.
65 * @return The length of the string, not including the final NUL character.
66 */
67size_t strlen(const char *str)
68{
69 size_t len = 0;
70
71 /* NULL and empty strings have length 0. */
72 if (!str)
73 return 0;
74
75 /* Loop until we find a NUL character. */
76 while (*str++ != '\0')
77 len++;
78
79 return len;
80}
81
82/**
83 * Compare two strings.
84 *
85 * @param s1 The first string.
86 * @param s2 The second string.
87 * @return Returns a value less than zero, if s1 is shorter than s2. Returns
88 * zero, if s1 equals s2. Returns a value greater than zero, if
89 * s1 is longer than s2.
90 */
Patrick Georgi980a69b2010-06-24 11:16:10 +000091int strcasecmp(const char *s1, const char *s2)
Jordan Crousef6145c32008-03-19 23:56:58 +000092{
Liu Taoe914b502010-09-08 10:27:13 +000093 int i, res;
Jordan Crousef6145c32008-03-19 23:56:58 +000094
Liu Taoe914b502010-09-08 10:27:13 +000095 for (i = 0; 1; i++) {
96 res = tolower(s1[i]) - tolower(s2[i]);
97 if (res || (s1[i] == '\0'))
98 break;
Jordan Crousef6145c32008-03-19 23:56:58 +000099 }
100
Liu Taoe914b502010-09-08 10:27:13 +0000101 return res;
Patrick Georgi980a69b2010-06-24 11:16:10 +0000102}
103
104/**
105 * Compare two strings with fixed length.
106 *
107 * @param s1 The first string.
108 * @param s2 The second string.
109 * @param maxlen Return at most maxlen characters as length of the string.
110 * @return A non-zero value if s1 and s2 differ, or zero if s1 equals s2.
111 */
112int strncasecmp(const char *s1, const char *s2, size_t maxlen)
113{
Liu Taoe914b502010-09-08 10:27:13 +0000114 int i, res;
Patrick Georgi980a69b2010-06-24 11:16:10 +0000115
Liu Taoe914b502010-09-08 10:27:13 +0000116 res = 0;
Patrick Georgi980a69b2010-06-24 11:16:10 +0000117 for (i = 0; i < maxlen; i++) {
Liu Taoe914b502010-09-08 10:27:13 +0000118 res = tolower(s1[i]) - tolower(s2[i]);
119 if (res || (s1[i] == '\0'))
120 break;
Patrick Georgi980a69b2010-06-24 11:16:10 +0000121 }
122
Liu Taoe914b502010-09-08 10:27:13 +0000123 return res;
Patrick Georgi980a69b2010-06-24 11:16:10 +0000124}
125
126/**
127 * Compare two strings.
128 *
129 * @param s1 The first string.
130 * @param s2 The second string.
131 * @return Returns a value less than zero, if s1 is shorter than s2. Returns
132 * zero, if s1 equals s2. Returns a value greater than zero, if
133 * s1 is longer than s2.
134 */
135int strcmp(const char *s1, const char *s2)
136{
Liu Taoe914b502010-09-08 10:27:13 +0000137 int i, res;
Patrick Georgi980a69b2010-06-24 11:16:10 +0000138
Liu Taoe914b502010-09-08 10:27:13 +0000139 for (i = 0; 1; i++) {
140 res = s1[i] - s2[i];
141 if (res || (s1[i] == '\0'))
142 break;
Patrick Georgi980a69b2010-06-24 11:16:10 +0000143 }
144
Liu Taoe914b502010-09-08 10:27:13 +0000145 return res;
Jordan Crousef6145c32008-03-19 23:56:58 +0000146}
147
148/**
149 * Compare two strings with fixed length.
150 *
151 * @param s1 The first string.
152 * @param s2 The second string.
153 * @param maxlen Return at most maxlen characters as length of the string.
154 * @return A non-zero value if s1 and s2 differ, or zero if s1 equals s2.
155 */
Stefan Reinauer3b9d1b82008-08-26 21:51:04 +0000156int strncmp(const char *s1, const char *s2, size_t maxlen)
Jordan Crousef6145c32008-03-19 23:56:58 +0000157{
Liu Taoe914b502010-09-08 10:27:13 +0000158 int i, res;
Jordan Crousef6145c32008-03-19 23:56:58 +0000159
Liu Taoe914b502010-09-08 10:27:13 +0000160 res = 0;
Jordan Crousef6145c32008-03-19 23:56:58 +0000161 for (i = 0; i < maxlen; i++) {
Liu Taoe914b502010-09-08 10:27:13 +0000162 res = s1[i] - s2[i];
163 if (res || (s1[i] == '\0'))
164 break;
Jordan Crousef6145c32008-03-19 23:56:58 +0000165 }
166
Liu Taoe914b502010-09-08 10:27:13 +0000167 return res;
Jordan Crousef6145c32008-03-19 23:56:58 +0000168}
169
Stefan Reinauer41514392008-09-26 18:42:40 +0000170/**
171 * Copy a string with a maximum length.
172 *
173 * @param d The destination memory.
174 * @param s The source string.
175 * @param n Copy at most n characters as length of the string.
176 * @return A pointer to the destination memory.
177 */
Stefan Reinauer3b9d1b82008-08-26 21:51:04 +0000178char *strncpy(char *d, const char *s, size_t n)
Jordan Crousef6145c32008-03-19 23:56:58 +0000179{
Uwe Hermann29014052008-03-21 15:47:38 +0000180 /* Use +1 to get the NUL terminator. */
Jordan Crousef6145c32008-03-19 23:56:58 +0000181 int max = n > strlen(s) + 1 ? strlen(s) + 1 : n;
182 int i;
183
Uwe Hermann6a441bf2008-03-20 19:54:59 +0000184 for (i = 0; i < max; i++)
185 d[i] = (char)s[i];
Jordan Crousef6145c32008-03-19 23:56:58 +0000186
187 return d;
188}
189
Stefan Reinauer41514392008-09-26 18:42:40 +0000190/**
191 * Copy a string.
192 *
193 * @param d The destination memory.
194 * @param s The source string.
195 * @return A pointer to the destination memory.
196 */
Jordan Crouse2c7bb9e2008-03-20 01:13:28 +0000197char *strcpy(char *d, const char *s)
198{
Uwe Hermann29014052008-03-21 15:47:38 +0000199 return strncpy(d, s, strlen(s) + 1);
Jordan Crouse2c7bb9e2008-03-20 01:13:28 +0000200}
201
Stefan Reinauer41514392008-09-26 18:42:40 +0000202/**
Patrick Georgi980a69b2010-06-24 11:16:10 +0000203 * Concatenates two strings
204 *
205 * @param d The destination string.
206 * @param s The source string.
207 * @return A pointer to the destination string.
208 */
209char *strcat(char *d, const char *s)
210{
211 char *p = d + strlen(d);
212 int sl = strlen(s);
213 int i;
214
215 for (i = 0; i < sl; i++)
216 p[i] = s[i];
217
218 p[i] = '\0';
219 return d;
220}
221
222/**
Stefan Reinauer41514392008-09-26 18:42:40 +0000223 * Concatenates two strings with a maximum length.
224 *
225 * @param d The destination string.
226 * @param s The source string.
Stefan Reinauer052d5912009-08-05 13:10:38 +0000227 * @param n Not more than n characters from s will be appended to d.
Stefan Reinauer41514392008-09-26 18:42:40 +0000228 * @return A pointer to the destination string.
229 */
Stefan Reinauer3b9d1b82008-08-26 21:51:04 +0000230char *strncat(char *d, const char *s, size_t n)
Jordan Crousef6145c32008-03-19 23:56:58 +0000231{
232 char *p = d + strlen(d);
Stefan Reinauere5d30b72010-03-25 22:15:19 +0000233 int sl = strlen(s);
234 int max = n > sl ? sl : n;
235 // int max = n > strlen(s) ? strlen(s) : n;
Jordan Crousef6145c32008-03-19 23:56:58 +0000236 int i;
237
Uwe Hermann6a441bf2008-03-20 19:54:59 +0000238 for (i = 0; i < max; i++)
Jordan Crousef6145c32008-03-19 23:56:58 +0000239 p[i] = s[i];
240
241 p[i] = '\0';
242 return d;
243}
244
Stefan Reinauer41514392008-09-26 18:42:40 +0000245/**
Stefan Reinauere5d30b72010-03-25 22:15:19 +0000246 * Concatenates two strings with a maximum length.
247 *
248 * @param d The destination string.
249 * @param s The source string.
Patrick Georgi13c16cb2011-03-22 13:40:09 +0000250 * @param n d will have at most n-1 characters (plus NUL) after invocation.
Stefan Reinauere5d30b72010-03-25 22:15:19 +0000251 * @return A pointer to the destination string.
252 */
253size_t strlcat(char *d, const char *s, size_t n)
254{
255 int sl = strlen(s);
256 int dl = strlen(d);
257
258 char *p = d + dl;
259 int max = n > (sl + dl) ? sl : (n - dl - 1);
260 int i;
261
262 for (i = 0; i < max; i++)
263 p[i] = s[i];
264
265 p[i] = '\0';
266 return max;
267}
268
269/**
Stefan Reinauer41514392008-09-26 18:42:40 +0000270 * Find a character in a string.
271 *
272 * @param s The string.
273 * @param c The character.
274 * @return A pointer to the first occurence of the character in the
275 * string, or NULL if the character was not encountered within the string.
276 */
Uwe Hermann6a441bf2008-03-20 19:54:59 +0000277char *strchr(const char *s, int c)
Jordan Crousef6145c32008-03-19 23:56:58 +0000278{
Uwe Hermann6a441bf2008-03-20 19:54:59 +0000279 char *p = (char *)s;
Jordan Crousef6145c32008-03-19 23:56:58 +0000280
Uwe Hermann6a441bf2008-03-20 19:54:59 +0000281 for (; *p != 0; p++) {
Jordan Crousef6145c32008-03-19 23:56:58 +0000282 if (*p == c)
283 return p;
284 }
285
286 return NULL;
287}
288
Stefan Reinauer41514392008-09-26 18:42:40 +0000289/**
Stefan Reinauere5d30b72010-03-25 22:15:19 +0000290 * Find a character in a string.
291 *
292 * @param s The string.
293 * @param c The character.
294 * @return A pointer to the last occurence of the character in the
295 * string, or NULL if the character was not encountered within the string.
296 */
297
298char *strrchr(const char *s, int c)
299{
300 char *p = (char *)s + strlen(s);
301
302 for (; p >= s; p--) {
303 if (*p == c)
304 return p;
305 }
306
307 return NULL;
308}
309
310/**
Stefan Reinauer41514392008-09-26 18:42:40 +0000311 * Duplicate a string.
312 *
313 * @param s The string to duplicate.
314 * @return A pointer to the copy of the original string.
315 */
Jordan Crousef6145c32008-03-19 23:56:58 +0000316char *strdup(const char *s)
317{
318 int n = strlen(s);
Jordan Crousec7815842008-04-25 23:07:39 +0000319 char *p = malloc(n + 1);
Jordan Crousef6145c32008-03-19 23:56:58 +0000320
Stefan Reinauerac29d612009-01-26 00:57:54 +0000321 if (p != NULL) {
Jordan Crousef6145c32008-03-19 23:56:58 +0000322 strncpy(p, s, n);
Stefan Reinauerac29d612009-01-26 00:57:54 +0000323 p[n] = 0;
324 }
Jordan Crousef6145c32008-03-19 23:56:58 +0000325 return p;
326}
327
Stefan Reinauer41514392008-09-26 18:42:40 +0000328/**
329 * Find a substring within a string.
330 *
331 * @param h The haystack string.
332 * @param n The needle string (substring).
333 * @return A pointer to the first occurence of the substring in
334 * the string, or NULL if the substring was not encountered within the string.
335 */
Jordan Crousef6145c32008-03-19 23:56:58 +0000336char *strstr(const char *h, const char *n)
337{
338 int hn = strlen(h);
339 int nn = strlen(n);
340 int i;
341
Uwe Hermann6a441bf2008-03-20 19:54:59 +0000342 for (i = 0; i <= hn - nn; i++)
Stefan Reinauer0d348f92009-03-06 17:43:20 +0000343 if (!memcmp(&h[i], n, nn))
Uwe Hermann6a441bf2008-03-20 19:54:59 +0000344 return (char *)&h[i];
Jordan Crousef6145c32008-03-19 23:56:58 +0000345
346 return NULL;
347}
Stefan Reinauer41514392008-09-26 18:42:40 +0000348
349/**
350 * Separate strings.
351 *
352 * @param stringp reference of the string to separate.
353 * @param delim string containing all delimiters.
354 * @return Token string.
355 */
356char *strsep(char **stringp, const char *delim)
357{
358 char *walk, *token;
359
360 if (!stringp || !*stringp || !**stringp)
361 return NULL;
362
363 token = walk = *stringp;
364
365 /* Walk, search for delimiters */
366 while(*walk && !strchr(delim, *walk))
367 walk++;
368
369 if (*walk) {
370 /* NUL terminate */
371 *walk = '\0';
372 walk++;
373 }
374
375 *stringp = walk;
376
377 return token;
378}
379
Jordan Crousec53cdd72008-10-20 17:07:47 +0000380/* Check that a character is in the valid range for the
381 given base
382*/
383
384static int _valid(char ch, int base)
385{
Stefan Tauner3509ad32013-06-25 19:25:46 +0200386 char end = (base > 9) ? '9' : '0' + (base - 1);
Jordan Crousec53cdd72008-10-20 17:07:47 +0000387
Stefan Tauner3509ad32013-06-25 19:25:46 +0200388 /* all bases will be some subset of the 0-9 range */
Jordan Crousec53cdd72008-10-20 17:07:47 +0000389
Stefan Tauner3509ad32013-06-25 19:25:46 +0200390 if (ch >= '0' && ch <= end)
391 return 1;
Jordan Crousec53cdd72008-10-20 17:07:47 +0000392
Stefan Tauner3509ad32013-06-25 19:25:46 +0200393 /* Bases > 11 will also have to match in the a-z range */
Jordan Crousec53cdd72008-10-20 17:07:47 +0000394
Stefan Tauner3509ad32013-06-25 19:25:46 +0200395 if (base > 11) {
396 if (tolower(ch) >= 'a' &&
397 tolower(ch) <= 'a' + (base - 11))
398 return 1;
399 }
Jordan Crousec53cdd72008-10-20 17:07:47 +0000400
Stefan Tauner3509ad32013-06-25 19:25:46 +0200401 return 0;
Jordan Crousec53cdd72008-10-20 17:07:47 +0000402}
403
404/* Return the "value" of the character in the given base */
405
406static int _offset(char ch, int base)
407{
Stefan Tauner3509ad32013-06-25 19:25:46 +0200408 if (ch >= '0' && ch <= '9')
409 return ch - '0';
410 else
411 return 10 + tolower(ch) - 'a';
Jordan Crousec53cdd72008-10-20 17:07:47 +0000412}
413
414/**
Patrick Georgi980a69b2010-06-24 11:16:10 +0000415 * Convert the initial portion of a string into a signed int
416 * @param ptr A pointer to the string to convert
417 * @param endptr A pointer to the unconverted part of the string
418 * @param base The base of the number to convert, or 0 for auto
419 * @return A signed integer representation of the string
420 */
421
422long int strtol(const char *ptr, char **endptr, int base)
423{
Stefan Tauner3509ad32013-06-25 19:25:46 +0200424 int ret = 0;
Patrick Georgi980a69b2010-06-24 11:16:10 +0000425 int negative = 1;
426
427 if (endptr != NULL)
428 *endptr = (char *) ptr;
429
Stefan Tauner3509ad32013-06-25 19:25:46 +0200430 /* Purge whitespace */
Patrick Georgi980a69b2010-06-24 11:16:10 +0000431
Stefan Tauner3509ad32013-06-25 19:25:46 +0200432 for( ; *ptr && isspace(*ptr); ptr++);
Patrick Georgi980a69b2010-06-24 11:16:10 +0000433
434 if (ptr[0] == '-') {
435 negative = -1;
436 ptr++;
437 }
438
Stefan Tauner3509ad32013-06-25 19:25:46 +0200439 if (!*ptr)
440 return 0;
Patrick Georgi980a69b2010-06-24 11:16:10 +0000441
Stefan Tauner3509ad32013-06-25 19:25:46 +0200442 /* Determine the base */
Patrick Georgi980a69b2010-06-24 11:16:10 +0000443
Stefan Tauner3509ad32013-06-25 19:25:46 +0200444 if (base == 0) {
Patrick Georgi980a69b2010-06-24 11:16:10 +0000445 if (ptr[0] == '0' && (ptr[1] == 'x' || ptr[1] == 'X'))
446 base = 16;
447 else if (ptr[0] == '0') {
448 base = 8;
449 ptr++;
450 }
451 else
452 base = 10;
Stefan Tauner3509ad32013-06-25 19:25:46 +0200453 }
Patrick Georgi980a69b2010-06-24 11:16:10 +0000454
455 /* Base 16 allows the 0x on front - so skip over it */
456
457 if (base == 16) {
458 if (ptr[0] == '0' && (ptr[1] == 'x' || ptr[1] == 'X'))
459 ptr += 2;
460 }
461
462 /* If the first character isn't valid, then don't
Stefan Tauner3509ad32013-06-25 19:25:46 +0200463 * bother */
Patrick Georgi980a69b2010-06-24 11:16:10 +0000464
Stefan Tauner3509ad32013-06-25 19:25:46 +0200465 if (!*ptr || !_valid(*ptr, base))
466 return 0;
Patrick Georgi980a69b2010-06-24 11:16:10 +0000467
Stefan Tauner3509ad32013-06-25 19:25:46 +0200468 for( ; *ptr && _valid(*ptr, base); ptr++)
469 ret = (ret * base) + _offset(*ptr, base);
Patrick Georgi980a69b2010-06-24 11:16:10 +0000470
471 if (endptr != NULL)
472 *endptr = (char *) ptr;
473
Stefan Tauner3509ad32013-06-25 19:25:46 +0200474 return ret * negative;
Patrick Georgi980a69b2010-06-24 11:16:10 +0000475}
476
Patrick Georgic3c827c2011-05-27 15:31:52 +0200477long atol(const char *nptr)
478{
479 return strtol(nptr, NULL, 10);
480}
481
Patrick Georgi980a69b2010-06-24 11:16:10 +0000482/**
Jordan Crousec53cdd72008-10-20 17:07:47 +0000483 * Convert the initial portion of a string into an unsigned int
484 * @param ptr A pointer to the string to convert
485 * @param endptr A pointer to the unconverted part of the string
486 * @param base The base of the number to convert, or 0 for auto
487 * @return An unsigned integer representation of the string
488 */
489
Patrick Georgic643fdd2011-07-26 12:51:59 +0200490unsigned long long int strtoull(const char *ptr, char **endptr, int base)
Jordan Crousec53cdd72008-10-20 17:07:47 +0000491{
Stefan Tauner3509ad32013-06-25 19:25:46 +0200492 unsigned long long int ret = 0;
Jordan Crousec53cdd72008-10-20 17:07:47 +0000493
494 if (endptr != NULL)
495 *endptr = (char *) ptr;
496
Stefan Tauner3509ad32013-06-25 19:25:46 +0200497 /* Purge whitespace */
Jordan Crousec53cdd72008-10-20 17:07:47 +0000498
Stefan Tauner3509ad32013-06-25 19:25:46 +0200499 for( ; *ptr && isspace(*ptr); ptr++);
Jordan Crousec53cdd72008-10-20 17:07:47 +0000500
Stefan Tauner3509ad32013-06-25 19:25:46 +0200501 if (!*ptr)
502 return 0;
Jordan Crousec53cdd72008-10-20 17:07:47 +0000503
Stefan Tauner3509ad32013-06-25 19:25:46 +0200504 /* Determine the base */
Jordan Crousec53cdd72008-10-20 17:07:47 +0000505
Stefan Tauner3509ad32013-06-25 19:25:46 +0200506 if (base == 0) {
Jordan Crousec53cdd72008-10-20 17:07:47 +0000507 if (ptr[0] == '0' && (ptr[1] == 'x' || ptr[1] == 'X'))
508 base = 16;
509 else if (ptr[0] == '0') {
510 base = 8;
511 ptr++;
512 }
513 else
514 base = 10;
Stefan Tauner3509ad32013-06-25 19:25:46 +0200515 }
Jordan Crousec53cdd72008-10-20 17:07:47 +0000516
517 /* Base 16 allows the 0x on front - so skip over it */
518
519 if (base == 16) {
520 if (ptr[0] == '0' && (ptr[1] == 'x' || ptr[1] == 'X'))
521 ptr += 2;
522 }
523
524 /* If the first character isn't valid, then don't
Stefan Tauner3509ad32013-06-25 19:25:46 +0200525 * bother */
Jordan Crousec53cdd72008-10-20 17:07:47 +0000526
Stefan Tauner3509ad32013-06-25 19:25:46 +0200527 if (!*ptr || !_valid(*ptr, base))
528 return 0;
Jordan Crousec53cdd72008-10-20 17:07:47 +0000529
Stefan Tauner3509ad32013-06-25 19:25:46 +0200530 for( ; *ptr && _valid(*ptr, base); ptr++)
531 ret = (ret * base) + _offset(*ptr, base);
Jordan Crousec53cdd72008-10-20 17:07:47 +0000532
533 if (endptr != NULL)
534 *endptr = (char *) ptr;
535
Stefan Tauner3509ad32013-06-25 19:25:46 +0200536 return ret;
Jordan Crousec53cdd72008-10-20 17:07:47 +0000537}
538
Patrick Georgic643fdd2011-07-26 12:51:59 +0200539unsigned long int strtoul(const char *ptr, char **endptr, int base)
540{
541 unsigned long long val = strtoull(ptr, endptr, base);
542 if (val > UINT32_MAX) return UINT32_MAX;
543 return val;
544}
545
546
Patrick Georgi980a69b2010-06-24 11:16:10 +0000547/**
548 * Determine the number of leading characters in s that match characters in a
549 * @param s A pointer to the string to analyse
550 * @param a A pointer to an array of characters that match the prefix
551 * @return The number of matching characters
552 */
Patrick Georgi980a69b2010-06-24 11:16:10 +0000553size_t strspn(const char *s, const char *a)
554{
555 int i, j;
556 int al = strlen(a);
557 for (i = 0; s[i] != 0; i++) {
558 int found = 0;
559 for (j = 0; j < al; j++) {
560 if (s[i] == a[j]) {
561 found = 1;
562 break;
563 }
564 }
565 if (!found)
566 break;
567 }
568 return i;
569}
570
571/**
572 * Determine the number of leading characters in s that do not match characters in a
573 * @param s A pointer to the string to analyse
574 * @param a A pointer to an array of characters that do not match the prefix
575 * @return The number of not matching characters
576 */
Patrick Georgi980a69b2010-06-24 11:16:10 +0000577size_t strcspn(const char *s, const char *a)
578{
579 int i, j;
580 int al = strlen(a);
581 for (i = 0; s[i] != 0; i++) {
582 int found = 0;
583 for (j = 0; j < al; j++) {
584 if (s[i] == a[j]) {
585 found = 1;
586 break;
587 }
588 }
589 if (found)
590 break;
591 }
592 return i;
593}
594
595/**
596 * Extract first token in string str that is delimited by a character in tokens.
597 * Destroys str and eliminates the token delimiter.
598 * @param str A pointer to the string to tokenize.
599 * @param delim A pointer to an array of characters that delimit the token
600 * @param ptr A pointer to a string pointer to keep state of the tokenizer
601 * @return Pointer to token
602 */
Patrick Georgi980a69b2010-06-24 11:16:10 +0000603char* strtok_r(char *str, const char *delim, char **ptr)
604{
605 /* start new tokenizing job or continue existing one? */
606 if (str == NULL)
607 str = *ptr;
608
609 /* skip over prefix delimiters */
610 char *start = str + strspn(str, delim);
611
Jeremy Compostella3ab8ce52016-09-07 14:09:34 +0200612 if (start[0] == '\0')
613 return NULL;
614
Patrick Georgi980a69b2010-06-24 11:16:10 +0000615 /* find first delimiter character */
616 char *end = start + strcspn(start, delim);
Jeremy Compostella3ab8ce52016-09-07 14:09:34 +0200617 *ptr = end;
618 if (end[0] != '\0')
619 *(*ptr)++ = '\0';
Patrick Georgi980a69b2010-06-24 11:16:10 +0000620
Patrick Georgi980a69b2010-06-24 11:16:10 +0000621 return start;
622}
623
624static char **strtok_global;
625
626/**
627 * Extract first token in string str that is delimited by a character in tokens.
628 * Destroys str, eliminates the token delimiter and uses global state.
629 * @param str A pointer to the string to tokenize.
630 * @param delim A pointer to an array of characters that delimit the token
631 * @return Pointer to token
632 */
Patrick Georgi980a69b2010-06-24 11:16:10 +0000633char* strtok(char *str, const char *delim)
634{
635 return strtok_r(str, delim, strtok_global);
636}
637
638/**
639 * Print error message and error number
640 * @param s Error message to print
641 */
642void perror(const char *s)
643{
644 printf("%s: %d\n", s?s:"(none)", errno);
645}
Stefan Taunerc9246da2013-06-27 17:06:27 +0200646
647/**
648 * Get a message string describing the given error number.
649 *
650 * @param errnum The error number to be interpreted
651 * @return A pointer to a string describing the given error number
652 */
653char *strerror(int errnum)
654{
655 /* Reserve enough space for the string below + INT64_MIN in decimal + \0 */
656 static char errstr[35];
657 snprintf(errstr, sizeof(errstr), "Unknown error %d", errnum);
658 return errstr;
659}
Dan Ehrenberg7aebf322014-11-21 15:50:27 -0800660
661/*
662 * Simple routine to convert UTF-16 to ASCII, giving up with ? if too high.
663 * A single code point may convert to ?? if not in the BMP.
664 * @param utf16_string A string encoded in UTF-16LE
665 * @param maxlen Maximum possible length of the string in code points
666 * @return Newly allocated ASCII string
667 */
668char *utf16le_to_ascii(uint16_t *utf16_string, int maxlen)
669{
670 char *ascii_string = xmalloc(maxlen + 1); /* +1 for trailing \0 */
671 ascii_string[maxlen] = '\0';
672 int i;
673 for (i = 0; i < maxlen; i++) {
674 uint16_t wchar = utf16_string[i];
675 ascii_string[i] = wchar > 0x7f ? '?' : (char)wchar;
676 }
677 return ascii_string;
678}