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 <malloc.h>
  15#include <linux/ctype.h>
  16
  17/* from lib/kstrtox.c */
  18static const char *_parse_integer_fixup_radix(const char *s, uint *basep)
  19{
  20        /* Look for a 0x prefix */
  21        if (s[0] == '0') {
  22                int ch = tolower(s[1]);
  23
  24                if (ch == 'x') {
  25                        *basep = 16;
  26                        s += 2;
  27                } else if (!*basep) {
  28                        /* Only select octal if we don't have a base */
  29                        *basep = 8;
  30                }
  31        }
  32
  33        /* Use decimal by default */
  34        if (!*basep)
  35                *basep = 10;
  36
  37        return s;
  38}
  39
  40/**
  41 * decode_digit() - Decode a single character into its numeric digit value
  42 *
  43 * This ignore case
  44 *
  45 * @ch: Character to convert (expects '0'..'9', 'a'..'f' or 'A'..'F')
  46 * Return: value of digit (0..0xf) or 255 if the character is invalid
  47 */
  48static uint decode_digit(int ch)
  49{
  50        if (!isxdigit(ch))
  51                return 256;
  52
  53        ch = tolower(ch);
  54
  55        return ch <= '9' ? ch - '0' : ch - 'a' + 0xa;
  56}
  57
  58ulong simple_strtoul(const char *cp, char **endp, uint base)
  59{
  60        ulong result = 0;
  61        uint value;
  62
  63        cp = _parse_integer_fixup_radix(cp, &base);
  64
  65        while (value = decode_digit(*cp), value < base) {
  66                result = result * base + value;
  67                cp++;
  68        }
  69
  70        if (endp)
  71                *endp = (char *)cp;
  72
  73        return result;
  74}
  75
  76ulong hextoul(const char *cp, char **endp)
  77{
  78        return simple_strtoul(cp, endp, 16);
  79}
  80
  81ulong dectoul(const char *cp, char **endp)
  82{
  83        return simple_strtoul(cp, endp, 10);
  84}
  85
  86int strict_strtoul(const char *cp, unsigned int base, unsigned long *res)
  87{
  88        char *tail;
  89        unsigned long val;
  90        size_t len;
  91
  92        *res = 0;
  93        len = strlen(cp);
  94        if (len == 0)
  95                return -EINVAL;
  96
  97        val = simple_strtoul(cp, &tail, base);
  98        if (tail == cp)
  99                return -EINVAL;
 100
 101        if ((*tail == '\0') ||
 102                ((len == (size_t)(tail - cp) + 1) && (*tail == '\n'))) {
 103                *res = val;
 104                return 0;
 105        }
 106
 107        return -EINVAL;
 108}
 109
 110long simple_strtol(const char *cp, char **endp, unsigned int base)
 111{
 112        if (*cp == '-')
 113                return -simple_strtoul(cp + 1, endp, base);
 114
 115        return simple_strtoul(cp, endp, base);
 116}
 117
 118unsigned long ustrtoul(const char *cp, char **endp, unsigned int base)
 119{
 120        unsigned long result = simple_strtoul(cp, endp, base);
 121        switch (tolower(**endp)) {
 122        case 'g':
 123                result *= 1024;
 124                /* fall through */
 125        case 'm':
 126                result *= 1024;
 127                /* fall through */
 128        case 'k':
 129                result *= 1024;
 130                (*endp)++;
 131                if (**endp == 'i')
 132                        (*endp)++;
 133                if (**endp == 'B')
 134                        (*endp)++;
 135        }
 136        return result;
 137}
 138
 139unsigned long long ustrtoull(const char *cp, char **endp, unsigned int base)
 140{
 141        unsigned long long result = simple_strtoull(cp, endp, base);
 142        switch (tolower(**endp)) {
 143        case 'g':
 144                result *= 1024;
 145                /* fall through */
 146        case 'm':
 147                result *= 1024;
 148                /* fall through */
 149        case 'k':
 150                result *= 1024;
 151                (*endp)++;
 152                if (**endp == 'i')
 153                        (*endp)++;
 154                if (**endp == 'B')
 155                        (*endp)++;
 156        }
 157        return result;
 158}
 159
 160unsigned long long simple_strtoull(const char *cp, char **endp,
 161                                        unsigned int base)
 162{
 163        unsigned long long result = 0;
 164        uint value;
 165
 166        cp = _parse_integer_fixup_radix(cp, &base);
 167
 168        while (value = decode_digit(*cp), value < base) {
 169                result = result * base + value;
 170                cp++;
 171        }
 172
 173        if (endp)
 174                *endp = (char *) cp;
 175
 176        return result;
 177}
 178
 179long long simple_strtoll(const char *cp, char **endp, unsigned int base)
 180{
 181        if (*cp == '-')
 182                return -simple_strtoull(cp + 1, endp, base);
 183
 184        return simple_strtoull(cp, endp, base);
 185}
 186
 187long trailing_strtoln_end(const char *str, const char *end, char const **endp)
 188{
 189        const char *p;
 190
 191        if (!end)
 192                end = str + strlen(str);
 193        p = end - 1;
 194        if (p > str && isdigit(*p)) {
 195                do {
 196                        if (!isdigit(p[-1])) {
 197                                if (endp)
 198                                        *endp = p;
 199                                return dectoul(p, NULL);
 200                        }
 201                } while (--p > str);
 202        }
 203        if (endp)
 204                *endp = end;
 205
 206        return -1;
 207}
 208
 209long trailing_strtoln(const char *str, const char *end)
 210{
 211        return trailing_strtoln_end(str, end, NULL);
 212}
 213
 214long trailing_strtol(const char *str)
 215{
 216        return trailing_strtoln(str, NULL);
 217}
 218
 219void str_to_upper(const char *in, char *out, size_t len)
 220{
 221        for (; len > 0 && *in; len--)
 222                *out++ = toupper(*in++);
 223        if (len)
 224                *out = '\0';
 225}
 226
 227const char **str_to_list(const char *instr)
 228{
 229        const char **ptr;
 230        char *str, *p;
 231        int count, i;
 232
 233        /* don't allocate if the string is empty */
 234        str = *instr ? strdup(instr) : (char *)instr;
 235        if (!str)
 236                return NULL;
 237
 238        /* count the number of space-separated strings */
 239        for (count = *str != '\0', p = str; *p; p++) {
 240                if (*p == ' ') {
 241                        count++;
 242                        *p = '\0';
 243                }
 244        }
 245
 246        /* allocate the pointer array, allowing for a NULL terminator */
 247        ptr = calloc(count + 1, sizeof(char *));
 248        if (!ptr) {
 249                if (*str)
 250                        free(str);
 251                return NULL;
 252        }
 253
 254        for (i = 0, p = str; i < count; p += strlen(p) + 1, i++)
 255                ptr[i] = p;
 256
 257        return ptr;
 258}
 259
 260void str_free_list(const char **ptr)
 261{
 262        if (ptr)
 263                free((char *)ptr[0]);
 264        free(ptr);
 265}
 266