]> git.ipfire.org Git - thirdparty/u-boot.git/blobdiff - lib/strto.c
net: hifemac_mdio: use log_msg_ret() correctly, report error by dev_err()
[thirdparty/u-boot.git] / lib / strto.c
index 7f6076909ab7401e802eac798671b79c0515a0b7..5157332d6c1d7966e783455d57f8bc1115c29f40 100644 (file)
@@ -9,38 +9,61 @@
  * Wirzenius wrote this portably, Torvalds fucked it up :-)
  */
 
-#include <common.h>
 #include <errno.h>
+#include <malloc.h>
+#include <vsprintf.h>
 #include <linux/ctype.h>
 
 /* from lib/kstrtox.c */
-static const char *_parse_integer_fixup_radix(const char *s, unsigned int *base)
-{
-       if (*base == 0) {
-               if (s[0] == '0') {
-                       if (tolower(s[1]) == 'x' && isxdigit(s[2]))
-                               *base = 16;
-                       else
-                               *base = 8;
-               } else
-                       *base = 10;
+static const char *_parse_integer_fixup_radix(const char *s, uint *basep)
+{
+       /* Look for a 0x prefix */
+       if (s[0] == '0') {
+               int ch = tolower(s[1]);
+
+               if (ch == 'x') {
+                       *basep = 16;
+                       s += 2;
+               } else if (!*basep) {
+                       /* Only select octal if we don't have a base */
+                       *basep = 8;
+               }
        }
-       if (*base == 16 && s[0] == '0' && tolower(s[1]) == 'x')
-               s += 2;
+
+       /* Use decimal by default */
+       if (!*basep)
+               *basep = 10;
+
        return s;
 }
 
-unsigned long simple_strtoul(const char *cp, char **endp,
-                               unsigned int base)
+/**
+ * decode_digit() - Decode a single character into its numeric digit value
+ *
+ * This ignore case
+ *
+ * @ch: Character to convert (expects '0'..'9', 'a'..'f' or 'A'..'F')
+ * Return: value of digit (0..0xf) or 255 if the character is invalid
+ */
+static uint decode_digit(int ch)
+{
+       if (!isxdigit(ch))
+               return 256;
+
+       ch = tolower(ch);
+
+       return ch <= '9' ? ch - '0' : ch - 'a' + 0xa;
+}
+
+ulong simple_strtoul(const char *cp, char **endp, uint base)
 {
-       unsigned long result = 0;
-       unsigned long value;
+       ulong result = 0;
+       uint value;
 
        cp = _parse_integer_fixup_radix(cp, &base);
 
-       while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp)
-           ? toupper(*cp) : *cp)-'A'+10) < base) {
-               result = result*base + value;
+       while (value = decode_digit(*cp), value < base) {
+               result = result * base + value;
                cp++;
        }
 
@@ -50,6 +73,16 @@ unsigned long simple_strtoul(const char *cp, char **endp,
        return result;
 }
 
+ulong hextoul(const char *cp, char **endp)
+{
+       return simple_strtoul(cp, endp, 16);
+}
+
+ulong dectoul(const char *cp, char **endp)
+{
+       return simple_strtoul(cp, endp, 10);
+}
+
 int strict_strtoul(const char *cp, unsigned int base, unsigned long *res)
 {
        char *tail;
@@ -85,22 +118,20 @@ long simple_strtol(const char *cp, char **endp, unsigned int base)
 unsigned long ustrtoul(const char *cp, char **endp, unsigned int base)
 {
        unsigned long result = simple_strtoul(cp, endp, base);
-       switch (**endp) {
-       case 'G':
+       switch (tolower(**endp)) {
+       case 'g':
                result *= 1024;
                /* fall through */
-       case 'M':
+       case 'm':
                result *= 1024;
                /* fall through */
-       case 'K':
        case 'k':
                result *= 1024;
-               if ((*endp)[1] == 'i') {
-                       if ((*endp)[2] == 'B')
-                               (*endp) += 3;
-                       else
-                               (*endp) += 2;
-               }
+               (*endp)++;
+               if (**endp == 'i')
+                       (*endp)++;
+               if (**endp == 'B')
+                       (*endp)++;
        }
        return result;
 }
@@ -108,22 +139,20 @@ unsigned long ustrtoul(const char *cp, char **endp, unsigned int base)
 unsigned long long ustrtoull(const char *cp, char **endp, unsigned int base)
 {
        unsigned long long result = simple_strtoull(cp, endp, base);
-       switch (**endp) {
-       case 'G':
+       switch (tolower(**endp)) {
+       case 'g':
                result *= 1024;
                /* fall through */
-       case 'M':
+       case 'm':
                result *= 1024;
                /* fall through */
-       case 'K':
        case 'k':
                result *= 1024;
-               if ((*endp)[1] == 'i') {
-                       if ((*endp)[2] == 'B')
-                               (*endp) += 3;
-                       else
-                               (*endp) += 2;
-               }
+               (*endp)++;
+               if (**endp == 'i')
+                       (*endp)++;
+               if (**endp == 'B')
+                       (*endp)++;
        }
        return result;
 }
@@ -131,12 +160,12 @@ unsigned long long ustrtoull(const char *cp, char **endp, unsigned int base)
 unsigned long long simple_strtoull(const char *cp, char **endp,
                                        unsigned int base)
 {
-       unsigned long long result = 0, value;
+       unsigned long long result = 0;
+       uint value;
 
        cp = _parse_integer_fixup_radix(cp, &base);
 
-       while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp - '0'
-               : (islower(*cp) ? toupper(*cp) : *cp) - 'A' + 10) < base) {
+       while (value = decode_digit(*cp), value < base) {
                result = result * base + value;
                cp++;
        }
@@ -147,23 +176,90 @@ unsigned long long simple_strtoull(const char *cp, char **endp,
        return result;
 }
 
-long trailing_strtoln(const char *str, const char *end)
+long long simple_strtoll(const char *cp, char **endp, unsigned int base)
+{
+       if (*cp == '-')
+               return -simple_strtoull(cp + 1, endp, base);
+
+       return simple_strtoull(cp, endp, base);
+}
+
+long trailing_strtoln_end(const char *str, const char *end, char const **endp)
 {
        const char *p;
 
        if (!end)
                end = str + strlen(str);
-       if (isdigit(end[-1])) {
-               for (p = end - 1; p > str; p--) {
-                       if (!isdigit(*p))
-                               return simple_strtoul(p + 1, NULL, 10);
-               }
+       p = end - 1;
+       if (p > str && isdigit(*p)) {
+               do {
+                       if (!isdigit(p[-1])) {
+                               if (endp)
+                                       *endp = p;
+                               return dectoul(p, NULL);
+                       }
+               } while (--p > str);
        }
+       if (endp)
+               *endp = end;
 
        return -1;
 }
 
+long trailing_strtoln(const char *str, const char *end)
+{
+       return trailing_strtoln_end(str, end, NULL);
+}
+
 long trailing_strtol(const char *str)
 {
        return trailing_strtoln(str, NULL);
 }
+
+void str_to_upper(const char *in, char *out, size_t len)
+{
+       for (; len > 0 && *in; len--)
+               *out++ = toupper(*in++);
+       if (len)
+               *out = '\0';
+}
+
+const char **str_to_list(const char *instr)
+{
+       const char **ptr;
+       char *str, *p;
+       int count, i;
+
+       /* don't allocate if the string is empty */
+       str = *instr ? strdup(instr) : (char *)instr;
+       if (!str)
+               return NULL;
+
+       /* count the number of space-separated strings */
+       for (count = *str != '\0', p = str; *p; p++) {
+               if (*p == ' ') {
+                       count++;
+                       *p = '\0';
+               }
+       }
+
+       /* allocate the pointer array, allowing for a NULL terminator */
+       ptr = calloc(count + 1, sizeof(char *));
+       if (!ptr) {
+               if (*str)
+                       free(str);
+               return NULL;
+       }
+
+       for (i = 0, p = str; i < count; p += strlen(p) + 1, i++)
+               ptr[i] = p;
+
+       return ptr;
+}
+
+void str_free_list(const char **ptr)
+{
+       if (ptr)
+               free((char *)ptr[0]);
+       free(ptr);
+}