summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJordan Crouse <jordan.crouse@amd.com>2008-10-20 17:07:47 +0000
committerJordan Crouse <jordan.crouse@amd.com>2008-10-20 17:07:47 +0000
commitc53cdd782a8551ac2e0dcda9cbd5b0d319102b85 (patch)
tree20a57ceaaee1e0491b23641bf17b044dc8790750
parentec6363dc48540db67a5966dc9987b192c26fcae1 (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.h2
-rw-r--r--payloads/libpayload/libc/string.c92
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;
+}
+
+