uboot/lib/strto.c
<<
>>
Prefs
   1/*
   2 *  linux/lib/vsprintf.c
   3 *
   4 *  Copyright (C) 1991, 1992  Linus Torvalds
   5 */
   6
   7/* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
   8/*
   9 * Wirzenius wrote this portably, Torvalds fucked it up :-)
  10 */
  11
  12#include <common.h>
  13#include <errno.h>
  14#include <linux/ctype.h>
  15
  16/* from lib/kstrtox.c */
  17static const char *_parse_integer_fixup_radix(const char *s, uint *basep)
  18{
  19        /* Look for a 0x prefix */
  20        if (s[0] == '0') {
  21                int ch = tolower(s[1]);
  22
  23                if (ch == 'x') {
  24                        *basep = 16;
  25                        s += 2;
  26                } else if (!*basep) {
  27                        /* Only select octal if we don't have a base */
  28                        *basep = 8;
  29                }
  30        }
  31
  32        /* Use decimal by default */
  33        if (!*basep)
  34                *basep = 10;
  35
  36        return s;
  37}
  38
  39/**
  40 * decode_digit() - Decode a single character into its numeric digit value
  41 *
  42 * This ignore case
  43 *
  44 * @ch: Character to convert (expects '0'..'9', 'a'..'f' or 'A'..'F')
  45 * @return value of digit (0..0xf) or 255 if the character is invalid
  46 */
  47static uint decode_digit(int ch)
  48{
  49        if (!isxdigit(ch))
  50                return 256;
  51
  52        ch = tolower(ch);
  53
  54        return ch <= '9' ? ch - '0' : ch - 'a' + 0xa;
  55}
  56
  57ulong simple_strtoul(const char *cp, char **endp, uint base)
  58{
  59        ulong result = 0;
  60        uint value;
  61
  62        cp = _parse_integer_fixup_radix(cp, &base);
  63
  64        while (value = decode_digit(*cp), value < base) {
  65                result = result * base + value;
  66                cp++;
  67        }
  68
  69        if (endp)
  70                *endp = (char *)cp;
  71
  72        return result;
  73}
  74
  75ulong hextoul(const char *cp, char **endp)
  76{
  77        return simple_strtoul(cp, endp, 16);
  78}
  79
  80ulong dectoul(const char *cp, char **endp)
  81{
  82        return simple_strtoul(cp, endp, 10);
  83}
  84
  85int strict_strtoul(const char *cp, unsigned int base, unsigned long *res)
  86{
  87        char *tail;
  88        unsigned long val;
  89        size_t len;
  90
  91        *res = 0;
  92        len = strlen(cp);
  93        if (len == 0)
  94                return -EINVAL;
  95
  96        val = simple_strtoul(cp, &tail, base);
  97        if (tail == cp)
  98                return -EINVAL;
  99
 100        if ((*tail == '\0') ||
 101                ((len == (size_t)(tail - cp) + 1) && (*tail == '\n'))) {
 102                *res = val;
 103                return 0;
 104        }
 105
 106        return -EINVAL;
 107}
 108
 109long simple_strtol(const char *cp, char **endp, unsigned int base)
 110{
 111        if (*cp == '-')
 112                return -simple_strtoul(cp + 1, endp, base);
 113
 114        return simple_strtoul(cp, endp, base);
 115}
 116
 117unsigned long ustrtoul(const char *cp, char **endp, unsigned int base)
 118{
 119        unsigned long result = simple_strtoul(cp, endp, base);
 120        switch (tolower(**endp)) {
 121        case 'g':
 122                result *= 1024;
 123                /* fall through */
 124        case 'm':
 125                result *= 1024;
 126                /* fall through */
 127        case 'k':
 128                result *= 1024;
 129                (*endp)++;
 130                if (**endp == 'i')
 131                        (*endp)++;
 132                if (**endp == 'B')
 133                        (*endp)++;
 134        }
 135        return result;
 136}
 137
 138unsigned long long ustrtoull(const char *cp, char **endp, unsigned int base)
 139{
 140        unsigned long long result = simple_strtoull(cp, endp, base);
 141        switch (tolower(**endp)) {
 142        case 'g':
 143                result *= 1024;
 144                /* fall through */
 145        case 'm':
 146                result *= 1024;
 147                /* fall through */
 148        case 'k':
 149                result *= 1024;
 150                (*endp)++;
 151                if (**endp == 'i')
 152                        (*endp)++;
 153                if (**endp == 'B')
 154                        (*endp)++;
 155        }
 156        return result;
 157}
 158
 159unsigned long long simple_strtoull(const char *cp, char **endp,
 160                                        unsigned int base)
 161{
 162        unsigned long long result = 0;
 163        uint value;
 164
 165        cp = _parse_integer_fixup_radix(cp, &base);
 166
 167        while (value = decode_digit(*cp), value < base) {
 168                result = result * base + value;
 169                cp++;
 170        }
 171
 172        if (endp)
 173                *endp = (char *) cp;
 174
 175        return result;
 176}
 177
 178long long simple_strtoll(const char *cp, char **endp, unsigned int base)
 179{
 180        if (*cp == '-')
 181                return -simple_strtoull(cp + 1, endp, base);
 182
 183        return simple_strtoull(cp, endp, base);
 184}
 185
 186long trailing_strtoln(const char *str, const char *end)
 187{
 188        const char *p;
 189
 190        if (!end)
 191                end = str + strlen(str);
 192        if (isdigit(end[-1])) {
 193                for (p = end - 1; p > str; p--) {
 194                        if (!isdigit(*p))
 195                                return dectoul(p + 1, NULL);
 196                }
 197        }
 198
 199        return -1;
 200}
 201
 202long trailing_strtol(const char *str)
 203{
 204        return trailing_strtoln(str, NULL);
 205}
 206
 207void str_to_upper(const char *in, char *out, size_t len)
 208{
 209        for (; len > 0 && *in; len--)
 210                *out++ = toupper(*in++);
 211        if (len)
 212                *out = '\0';
 213}
 214