Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/src/lib/str.c

    r42e91ae rd066259  
    789789        str_ncpy(dest, size + 1, src, size);
    790790        return dest;
     791}
     792
     793/** Convert string to uint64_t (internal variant).
     794 *
     795 * @param nptr   Pointer to string.
     796 * @param endptr Pointer to the first invalid character is stored here.
     797 * @param base   Zero or number between 2 and 36 inclusive.
     798 * @param neg    Indication of unary minus is stored here.
     799 * @apram result Result of the conversion.
     800 *
     801 * @return EOK if conversion was successful.
     802 *
     803 */
     804static errno_t str_uint(const char *nptr, char **endptr, unsigned int base,
     805    bool *neg, uint64_t *result)
     806{
     807        assert(endptr != NULL);
     808        assert(neg != NULL);
     809        assert(result != NULL);
     810
     811        *neg = false;
     812        const char *str = nptr;
     813
     814        /* Ignore leading whitespace */
     815        while (isspace(*str))
     816                str++;
     817
     818        if (*str == '-') {
     819                *neg = true;
     820                str++;
     821        } else if (*str == '+')
     822                str++;
     823
     824        if (base == 0) {
     825                /* Decode base if not specified */
     826                base = 10;
     827
     828                if (*str == '0') {
     829                        base = 8;
     830                        str++;
     831
     832                        switch (*str) {
     833                        case 'b':
     834                        case 'B':
     835                                base = 2;
     836                                str++;
     837                                break;
     838                        case 'o':
     839                        case 'O':
     840                                base = 8;
     841                                str++;
     842                                break;
     843                        case 'd':
     844                        case 'D':
     845                        case 't':
     846                        case 'T':
     847                                base = 10;
     848                                str++;
     849                                break;
     850                        case 'x':
     851                        case 'X':
     852                                base = 16;
     853                                str++;
     854                                break;
     855                        default:
     856                                str--;
     857                        }
     858                }
     859        } else {
     860                /* Check base range */
     861                if ((base < 2) || (base > 36)) {
     862                        *endptr = (char *) str;
     863                        return EINVAL;
     864                }
     865        }
     866
     867        *result = 0;
     868        const char *startstr = str;
     869
     870        while (*str != 0) {
     871                unsigned int digit;
     872
     873                if ((*str >= 'a') && (*str <= 'z'))
     874                        digit = *str - 'a' + 10;
     875                else if ((*str >= 'A') && (*str <= 'Z'))
     876                        digit = *str - 'A' + 10;
     877                else if ((*str >= '0') && (*str <= '9'))
     878                        digit = *str - '0';
     879                else
     880                        break;
     881
     882                if (digit >= base)
     883                        break;
     884
     885                uint64_t prev = *result;
     886                *result = (*result) * base + digit;
     887
     888                if (*result < prev) {
     889                        /* Overflow */
     890                        *endptr = (char *) str;
     891                        return EOVERFLOW;
     892                }
     893
     894                str++;
     895        }
     896
     897        if (str == startstr) {
     898                /*
     899                 * No digits were decoded => first invalid character is
     900                 * the first character of the string.
     901                 */
     902                str = nptr;
     903        }
     904
     905        *endptr = (char *) str;
     906
     907        if (str == nptr)
     908                return EINVAL;
     909
     910        return EOK;
     911}
     912
     913/** Convert string to uint64_t.
     914 *
     915 * @param nptr   Pointer to string.
     916 * @param endptr If not NULL, pointer to the first invalid character
     917 *               is stored here.
     918 * @param base   Zero or number between 2 and 36 inclusive.
     919 * @param strict Do not allow any trailing characters.
     920 * @param result Result of the conversion.
     921 *
     922 * @return EOK if conversion was successful.
     923 *
     924 */
     925errno_t str_uint64_t(const char *nptr, char **endptr, unsigned int base,
     926    bool strict, uint64_t *result)
     927{
     928        assert(result != NULL);
     929
     930        bool neg;
     931        char *lendptr;
     932        errno_t ret = str_uint(nptr, &lendptr, base, &neg, result);
     933
     934        if (endptr != NULL)
     935                *endptr = (char *) lendptr;
     936
     937        if (ret != EOK)
     938                return ret;
     939
     940        /* Do not allow negative values */
     941        if (neg)
     942                return EINVAL;
     943
     944        /*
     945         * Check whether we are at the end of
     946         * the string in strict mode
     947         */
     948        if ((strict) && (*lendptr != 0))
     949                return EINVAL;
     950
     951        return EOK;
    791952}
    792953
Note: See TracChangeset for help on using the changeset viewer.