[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH v2 1/2] libc: Zentralisieren der strtoxxx-Funktionen



From: Nico Mayer <mayerNico@xxxxxxxxxx>

* Bisher gibt es ein gewisses Durcheinander, was die strtoxxx-Funktionen
  anbelangt. Die Funktionen strtol und strtoll werden in der Datei
  strtol.c implementiert. Die Funktionen strtoul und strtoull werden
  wiederum direkt in string.c implementiert. Dieser Commit zentralisiert
  die Implementierung der verschiedenen strtoxxx-Funktionen. Alle
  strtoxxx-Funktionen jetzt werden durch die Datei strtol.c implementiert.

Signed-off-by: Nico Mayer <mayerNico@xxxxxxxxxx>
---
 src/lib/stdlibc/strtol.c | 128 ++++++++++++++++++++++++++++-----------
 src/lib/string.c         | 104 -------------------------------
 2 files changed, 93 insertions(+), 139 deletions(-)

diff --git a/src/lib/stdlibc/strtol.c b/src/lib/stdlibc/strtol.c
index 0160ebcf..47f03a36 100644
--- a/src/lib/stdlibc/strtol.c
+++ b/src/lib/stdlibc/strtol.c
@@ -31,76 +31,134 @@
 #include "limits.h"
 #include "types.h"
 
-static long long do_strtoll(const char *str, char **endptr, int base,
-                            long long min_val, long long max_val)
+static unsigned long long do_strtoull(const char *str, char **endptr, int base,
+                            unsigned long long max_val,
+                            unsigned long long min_val)
 {
-    long long retval = 0;
-    int overflow = 0;
-    char sign = 0;
+    unsigned long long result = 0;
+    int neg = 0;
     int digit;
+    int overflow = 0;
 
+    // Leerzeichen am Anfang muessen ignoriert werden
     while (isspace(*str)) {
         str++;
     }
 
-    // Moegliches Vorzeichen auswerten
-    if (*str == '+' || *str == '-') {
-        sign = *str;
+    // Vorzeichen
+    if (*str == '+') {
+        str++;
+    } else if (*str == '-') {
+        neg = 1;
         str++;
     }
 
-    // Moegliches 0, 0x und 0X auswerten
-    if (*str == '0')
-    {
-        if (str[1] == 'x' || str[1] == 'X') {
-            if (base == 0) {
-                base = 16;
+    // Basis feststellen
+    // Bei Basis 16 darf der String mit 0x anfangen
+    // Bei Basis 0 ist automatische Erkennung
+    //   Anfang ist 0x: Basis 16
+    //   Anfang ist 0:  Basis 8
+    //   Ansonsten:     Basis 10
+    switch (base) {
+        case 0:
+            base = 10;
+            if (*str == '0') {
+                str++;
+                if (*str == 'x' || *str == 'X') {
+                    if (isxdigit(str[1])) {
+                        base = 16;
+                        str++;
+                    }
+                } else {
+                    base = 8;
+                }
             }
+            break;
 
-            if (base == 16 && isxdigit(str[2])) {
+        case 16:
+            if ((*str == '0') && (str[1] == 'x' || str[1] == 'X')
+                && isxdigit(str[2]))
+            {
                 str += 2;
             }
-        } else if (base == 0) {
-            base = 8;
-        }
+            break;
     }
 
-    while (*str)
-    {
-        if (isdigit(*str) && *str - '0' < base) {
-            digit = *str - '0';
-        } else if(isalpha(*str) && tolower(*str) - 'a' + 10 < base) {
-            digit = tolower(*str) - 'a' + 10;
-        } else {
-            break;
+    // Ergebnis berechnen
+    result = 0;
+    while (*str) {
+        switch (*str) {
+            case '0' ... '9':
+                if (*str - '0' > base - 1) {
+                    goto out;
+                }
+                digit = *str - '0';
+                break;
+            case 'A' ... 'Z':
+                if (*str - 'A' + 10 > base - 1) {
+                    goto out;
+                }
+                digit = *str - 'A' + 10;
+                break;
+            case 'a' ... 'z':
+                if (*str - 'a' + 10 > base - 1) {
+                    goto out;
+                }
+                digit = *str - 'a' + 10;
+                break;
+
+            default:
+                goto out;
         }
 
-        if (retval > (max_val - digit) / base) {
-            overflow = 1;
+        if (neg) {
+            if (result > (min_val - digit) / base) {
+                errno = ERANGE;
+                overflow = 1;
+            }
+        } else {
+            if (result > (max_val - digit) / base) {
+                errno = ERANGE;
+                overflow = 1;
+            }
         }
-        retval = retval * base + digit;
+
+        result = result * base + digit;
 
         str++;
     }
+out:
 
     if (endptr != NULL) {
-        *(const char**)endptr = str;
+        *endptr = (char*) str;
     }
 
     if (overflow) {
-        errno = ERANGE;
-        return (sign == '-') ? min_val : max_val;
+        return neg ? min_val : max_val;
     }
 
-    return (sign == '-') ? -retval : retval;
+    return neg ? - result : result;
 }
 
+
 long long strtoll(const char *str, char **endptr, int base)
 {
-    return do_strtoll(str, endptr, base, LLONG_MIN, LLONG_MAX);
+    return (long long)do_strtoull(str, endptr, base, LLONG_MAX, LLONG_MIN);
 }
 
 long strtol(const char *str, char **endptr, int base)
 {
-    return do_strtoll(str, endptr, base, LONG_MIN, LONG_MAX);
+    return (long)do_strtoull(str, endptr, base, LONG_MAX, LONG_MIN);
+}
+
+unsigned long long strtoull(const char *str, char **endptr, int base)
+{
+    return (unsigned long long)do_strtoull(str, endptr, base,
+                                           ULLONG_MAX, ULLONG_MAX);
 }
+
+unsigned long strtoul(const char *str, char **endptr, int base)
+{
+    return (unsigned long)do_strtoull(str, endptr, base, ULONG_MAX, ULONG_MAX);
+}
+
diff --git a/src/lib/string.c b/src/lib/string.c
index 98861869..630e4f0e 100644
--- a/src/lib/string.c
+++ b/src/lib/string.c
@@ -67,110 +67,6 @@ void itoa(unsigned int n, char *s, unsigned int base)
 	s[y] = '\0';
 }
 
-unsigned long long int strtoull(const char *nptr, char **endptr, int base)
-{
-    unsigned long long int result = 0;
-    int neg = 0;
-    int digit;
-    bool overflow = false;
-
-    // Leerzeichen am Anfang muessen ignoriert werden
-    while (isspace(*nptr)) {
-        nptr++;
-    }
-
-    // Vorzeichen
-    if (*nptr == '+') {
-        nptr++;
-    } else if (*nptr == '-') {
-        neg = 1;
-        nptr++;
-    }
-
-    // Basis feststellen
-    // Bei Basis 16 darf der String mit 0x anfangen
-    // Bei Basis 0 ist automatische Erkennung
-    //   Anfang ist 0x: Basis 16
-    //   Anfang ist 0:  Basis 8
-    //   Ansonsten:     Basis 10
-    switch (base) {
-        case 0:
-            base = 10;
-            if (*nptr == '0') {
-                nptr++;
-                if (*nptr == 'x' || *nptr == 'X') {
-                    if (isxdigit(nptr[1])) {
-                        base = 16;
-                        nptr++;
-                    }
-                } else {
-                    base = 8;
-                }
-            }
-            break;
-
-        case 16:
-            if ((*nptr == '0') && (nptr[1] == 'x' || nptr[1] == 'X')
-                && isxdigit(nptr[2]))
-            {
-                nptr += 2;
-            }
-            break;
-    }
-
-    // Ergebnis berechnen
-    result = 0;
-    while (*nptr) {
-        switch (*nptr) {
-            case '0' ... '9':
-                if (*nptr - '0' > base - 1) {
-                    goto out;
-                }
-                digit = *nptr - '0';
-                break;
-            case 'A' ... 'Z':
-                if (*nptr - 'A' + 10 > base - 1) {
-                    goto out;
-                }
-                digit = *nptr - 'A' + 10;
-                break;
-            case 'a' ... 'z':
-                if (*nptr - 'a' + 10 > base - 1) {
-                    goto out;
-                }
-                digit = *nptr - 'a' + 10;
-                break;
-
-            default:
-                goto out;
-        }
-
-        if (result > (ULLONG_MAX - digit) / base) {
-            overflow = true;
-        }
-        result = result * base + digit;
-
-        nptr++;
-    }
-out:
-
-    if (endptr != NULL) {
-        *endptr = (char*) nptr;
-    }
-
-    if (overflow) {
-        return ULLONG_MAX;
-    }
-
-    return neg ? - result : result;
-}
-
-unsigned long int strtoul(const char *nptr, char **endptr, int base)
-{
-    return (unsigned long int) strtoull(nptr, endptr, base);
-}
-
-
 int atoi(const char *s)
 {
     return (int) strtoull(s, NULL, 10);
-- 
2.29.2