Merge tag 'clk-2022.01-rc3' of https://source.denx.de/u-boot/custodians/u-boot-clk
[platform/kernel/u-boot.git] / lib / strto.c
index c00bb58..7bba1e3 100644 (file)
 #include <linux/ctype.h>
 
 /* from lib/kstrtox.c */
-static const char *_parse_integer_fixup_radix(const char *s, unsigned int *base)
+static const char *_parse_integer_fixup_radix(const char *s, uint *basep)
 {
-       if (*base == 0) {
-               if (s[0] == '0') {
-                       if (tolower(s[1]) == 'x' && isxdigit(s[2]))
-                               *base = 16;
-                       else
-                               *base = 8;
-               } else
-                       *base = 10;
+       /* 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 +72,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;
@@ -127,12 +159,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++;
        }
@@ -143,6 +175,14 @@ unsigned long long simple_strtoull(const char *cp, char **endp,
        return result;
 }
 
+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(const char *str, const char *end)
 {
        const char *p;
@@ -152,7 +192,7 @@ long trailing_strtoln(const char *str, const char *end)
        if (isdigit(end[-1])) {
                for (p = end - 1; p > str; p--) {
                        if (!isdigit(*p))
-                               return simple_strtoul(p + 1, NULL, 10);
+                               return dectoul(p + 1, NULL);
                }
        }