Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset 30a5470 in mainline


Ignore:
Timestamp:
2010-04-18T00:19:51Z (12 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master
Children:
c39a103
Parents:
88dea9d
Message:

string to integer conversion routines

Location:
kernel/generic
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/include/str.h

    r88dea9d r30a5470  
    9797extern bool wstr_remove(wchar_t *str, size_t pos);
    9898
     99extern int str_uint64(const char *, char **, unsigned int, bool, uint64_t *);
     100
    99101#endif
    100102
  • kernel/generic/src/lib/str.c

    r88dea9d r30a5470  
    110110#include <align.h>
    111111#include <debug.h>
     112#include <macros.h>
    112113
    113114/** Byte mask consisting of lowest @n bits (out of 8) */
     
    760761}
    761762
     763/** Convert string to uint64_t (internal variant).
     764 *
     765 * @param nptr   Pointer to string.
     766 * @param endptr Pointer to the first invalid character is stored here.
     767 * @param base   Zero or number between 2 and 36 inclusive.
     768 * @param neg    Indication of unary minus is stored here.
     769 * @apram result Result of the conversion.
     770 *
     771 * @return EOK if conversion was successful.
     772 *
     773 */
     774static int str_uint(const char *nptr, char **endptr, unsigned int base,
     775    bool *neg, uint64_t *result)
     776{
     777        ASSERT(endptr != NULL);
     778        ASSERT(neg != NULL);
     779        ASSERT(result != NULL);
     780       
     781        *neg = false;
     782        const char *str = nptr;
     783       
     784        /* Ignore leading whitespace */
     785        while (isspace(*str))
     786                str++;
     787       
     788        if (*str == '-') {
     789                *neg = true;
     790                str++;
     791        } else if (*str == '+')
     792                str++;
     793       
     794        if (base == 0) {
     795                /* Decode base if not specified */
     796                base = 10;
     797               
     798                if (*str == '0') {
     799                        base = 8;
     800                        str++;
     801                       
     802                        switch (*str) {
     803                        case 'b':
     804                        case 'B':
     805                                base = 2;
     806                                str++;
     807                                break;
     808                        case 'o':
     809                        case 'O':
     810                                base = 8;
     811                                str++;
     812                                break;
     813                        case 'd':
     814                        case 'D':
     815                        case 't':
     816                        case 'T':
     817                                base = 10;
     818                                str++;
     819                                break;
     820                        case 'x':
     821                        case 'X':
     822                                base = 16;
     823                                str++;
     824                                break;
     825                        }
     826                }
     827        } else {
     828                /* Check base range */
     829                if ((base < 2) || (base > 36)) {
     830                        *endptr = (char *) str;
     831                        return EINVAL;
     832                }
     833        }
     834       
     835        *result = 0;
     836        const char *startstr = str;
     837       
     838        while (*str != 0) {
     839                unsigned int digit;
     840               
     841                if ((*str >= 'a') && (*str <= 'z'))
     842                        digit = *str - 'a' + 10;
     843                else if ((*str >= 'A') && (*str <= 'Z'))
     844                        digit = *str - 'A' + 10;
     845                else if ((*str >= '0') && (*str <= '9'))
     846                        digit = *str - '0';
     847                else
     848                        break;
     849               
     850                if (digit >= base)
     851                        break;
     852               
     853                uint64_t prev = *result;
     854                *result = (*result) * base + digit;
     855               
     856                if (*result < prev) {
     857                        /* Overflow */
     858                        *endptr = (char *) str;
     859                        return EOVERFLOW;
     860                }
     861               
     862                str++;
     863        }
     864       
     865        if (str == startstr) {
     866                /*
     867                 * No digits were decoded => first invalid character is
     868                 * the first character of the string.
     869                 */
     870                str = nptr;
     871        }
     872       
     873        *endptr = (char *) str;
     874       
     875        if (str == nptr)
     876                return EINVAL;
     877       
     878        return EOK;
     879}
     880
     881/** Convert string to uint64_t.
     882 *
     883 * @param nptr   Pointer to string.
     884 * @param endptr If not NULL, pointer to the first invalid character
     885 *               is stored here.
     886 * @param base   Zero or number between 2 and 36 inclusive.
     887 * @param strict Do not allow any trailing characters.
     888 * @apram result Result of the conversion.
     889 *
     890 * @return EOK if conversion was successful.
     891 *
     892 */
     893int str_uint64(const char *nptr, char **endptr, unsigned int base,
     894    bool strict, uint64_t *result)
     895{
     896        ASSERT(result != NULL);
     897       
     898        bool neg;
     899        char *lendptr;
     900        int ret = str_uint(nptr, &lendptr, base, &neg, result);
     901       
     902        if (endptr != NULL)
     903                *endptr = (char *) lendptr;
     904       
     905        if (ret != EOK)
     906                return ret;
     907       
     908        /* Do not allow negative values */
     909        if (neg)
     910                return EINVAL;
     911       
     912        /* Check whether we are at the end of
     913           the string in strict mode */
     914        if ((strict) && (*lendptr != 0))
     915                return EINVAL;
     916       
     917        return EOK;
     918}
     919
    762920/** @}
    763921 */
Note: See TracChangeset for help on using the changeset viewer.