diff options
author | Jordan Crouse <jordan.crouse@amd.com> | 2008-10-20 17:07:47 +0000 |
---|---|---|
committer | Jordan Crouse <jordan.crouse@amd.com> | 2008-10-20 17:07:47 +0000 |
commit | c53cdd782a8551ac2e0dcda9cbd5b0d319102b85 (patch) | |
tree | 20a57ceaaee1e0491b23641bf17b044dc8790750 | |
parent | ec6363dc48540db67a5966dc9987b192c26fcae1 (diff) |
[PATCH] libpayload: Add a strtoul() function
Signed-off-by: Jordan Crouse <jordan.crouse@amd.com>
Acked-by: Patrick Georgi <patrick.georgi@coresystems.de>
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@3676 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
-rw-r--r-- | payloads/libpayload/include/libpayload.h | 2 | ||||
-rw-r--r-- | payloads/libpayload/libc/string.c | 92 |
2 files changed, 94 insertions, 0 deletions
diff --git a/payloads/libpayload/include/libpayload.h b/payloads/libpayload/include/libpayload.h index dd7fe9a29c..a098f0cc21 100644 --- a/payloads/libpayload/include/libpayload.h +++ b/payloads/libpayload/include/libpayload.h @@ -327,6 +327,8 @@ char *strchr(const char *s, int c); char *strdup(const char *s); char *strstr(const char *h, const char *n); char *strsep(char **stringp, const char *delim); +unsigned int strtoul(const char *s, char **nptr, int base); + /** @} */ /** diff --git a/payloads/libpayload/libc/string.c b/payloads/libpayload/libc/string.c index 9d196f2e09..9502acfa6e 100644 --- a/payloads/libpayload/libc/string.c +++ b/payloads/libpayload/libc/string.c @@ -271,3 +271,95 @@ char *strsep(char **stringp, const char *delim) return token; } +/* Check that a character is in the valid range for the + given base +*/ + +static int _valid(char ch, int base) +{ + char end = (base > 9) ? '9' : '0' + (base - 1); + + /* all bases will be some subset of the 0-9 range */ + + if (ch >= '0' && ch <= end) + return 1; + + /* Bases > 11 will also have to match in the a-z range */ + + if (base > 11) { + if (tolower(ch) >= 'a' && + tolower(ch) <= 'a' + (base - 11)) + return 1; + } + + return 0; +} + +/* Return the "value" of the character in the given base */ + +static int _offset(char ch, int base) +{ + if (ch >= '0' && ch <= '9') + return ch - '0'; + else + return tolower(ch) - 'a'; +} + +/** + * Convert the initial portion of a string into an unsigned int + * @param ptr A pointer to the string to convert + * @param endptr A pointer to the unconverted part of the string + * @param base The base of the number to convert, or 0 for auto + * @return An unsigned integer representation of the string + */ + +unsigned int strtoul(const char *ptr, char **endptr, int base) +{ + int ret = 0; + + if (endptr != NULL) + *endptr = (char *) ptr; + + /* Purge whitespace */ + + for( ; *ptr && isspace(*ptr); ptr++); + + if (!*ptr) + return 0; + + /* Determine the base */ + + if (base == 0) { + if (ptr[0] == '0' && (ptr[1] == 'x' || ptr[1] == 'X')) + base = 16; + else if (ptr[0] == '0') { + base = 8; + ptr++; + } + else + base = 10; + } + + /* Base 16 allows the 0x on front - so skip over it */ + + if (base == 16) { + if (ptr[0] == '0' && (ptr[1] == 'x' || ptr[1] == 'X')) + ptr += 2; + } + + /* If the first character isn't valid, then don't + * bother */ + + if (!*ptr || !_valid(*ptr, base)) + return 0; + + for( ; *ptr && _valid(*ptr, base); ptr++) + ret = (ret * base) + _offset(*ptr, base); + + if (endptr != NULL) + *endptr = (char *) ptr; + + return ret; +} + + |