Changes in / [b401b33:83b64a59] in mainline


Ignore:
Files:
1 deleted
7 edited

Legend:

Unmodified
Added
Removed
  • kernel/Makefile

    rb401b33 r83b64a59  
    207207        generic/src/lib/gsort.c \
    208208        generic/src/lib/str.c \
    209         generic/src/lib/strtol.c \
    210209        generic/src/lib/str_error.c \
    211210        generic/src/lib/elf.c \
  • kernel/generic/src/lib/str.c

    rb401b33 r83b64a59  
    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
  • uspace/lib/c/generic/ctype.c

    rb401b33 r83b64a59  
    9090        case '\v':
    9191                return 1;
     92                break;
    9293        default:
    9394                return 0;
  • uspace/lib/c/generic/str.c

    rb401b33 r83b64a59  
    14711471        *end = '\0';
    14721472        return start;
     1473}
     1474
     1475/** Convert string to uint64_t (internal variant).
     1476 *
     1477 * @param nptr   Pointer to string.
     1478 * @param endptr Pointer to the first invalid character is stored here.
     1479 * @param base   Zero or number between 2 and 36 inclusive.
     1480 * @param neg    Indication of unary minus is stored here.
     1481 * @apram result Result of the conversion.
     1482 *
     1483 * @return EOK if conversion was successful.
     1484 *
     1485 */
     1486static errno_t str_uint(const char *nptr, char **endptr, unsigned int base,
     1487    bool *neg, uint64_t *result)
     1488{
     1489        assert(endptr != NULL);
     1490        assert(neg != NULL);
     1491        assert(result != NULL);
     1492
     1493        *neg = false;
     1494        const char *str = nptr;
     1495
     1496        /* Ignore leading whitespace */
     1497        while (isspace(*str))
     1498                str++;
     1499
     1500        if (*str == '-') {
     1501                *neg = true;
     1502                str++;
     1503        } else if (*str == '+')
     1504                str++;
     1505
     1506        if (base == 0) {
     1507                /* Decode base if not specified */
     1508                base = 10;
     1509
     1510                if (*str == '0') {
     1511                        base = 8;
     1512                        str++;
     1513
     1514                        switch (*str) {
     1515                        case 'b':
     1516                        case 'B':
     1517                                base = 2;
     1518                                str++;
     1519                                break;
     1520                        case 'o':
     1521                        case 'O':
     1522                                base = 8;
     1523                                str++;
     1524                                break;
     1525                        case 'd':
     1526                        case 'D':
     1527                        case 't':
     1528                        case 'T':
     1529                                base = 10;
     1530                                str++;
     1531                                break;
     1532                        case 'x':
     1533                        case 'X':
     1534                                base = 16;
     1535                                str++;
     1536                                break;
     1537                        default:
     1538                                str--;
     1539                        }
     1540                }
     1541        } else {
     1542                /* Check base range */
     1543                if ((base < 2) || (base > 36)) {
     1544                        *endptr = (char *) str;
     1545                        return EINVAL;
     1546                }
     1547        }
     1548
     1549        *result = 0;
     1550        const char *startstr = str;
     1551
     1552        while (*str != 0) {
     1553                unsigned int digit;
     1554
     1555                if ((*str >= 'a') && (*str <= 'z'))
     1556                        digit = *str - 'a' + 10;
     1557                else if ((*str >= 'A') && (*str <= 'Z'))
     1558                        digit = *str - 'A' + 10;
     1559                else if ((*str >= '0') && (*str <= '9'))
     1560                        digit = *str - '0';
     1561                else
     1562                        break;
     1563
     1564                if (digit >= base)
     1565                        break;
     1566
     1567                uint64_t prev = *result;
     1568                *result = (*result) * base + digit;
     1569
     1570                if (*result < prev) {
     1571                        /* Overflow */
     1572                        *endptr = (char *) str;
     1573                        return EOVERFLOW;
     1574                }
     1575
     1576                str++;
     1577        }
     1578
     1579        if (str == startstr) {
     1580                /*
     1581                 * No digits were decoded => first invalid character is
     1582                 * the first character of the string.
     1583                 */
     1584                str = nptr;
     1585        }
     1586
     1587        *endptr = (char *) str;
     1588
     1589        if (str == nptr)
     1590                return EINVAL;
     1591
     1592        return EOK;
     1593}
     1594
     1595/** Convert string to uint8_t.
     1596 *
     1597 * @param nptr   Pointer to string.
     1598 * @param endptr If not NULL, pointer to the first invalid character
     1599 *               is stored here.
     1600 * @param base   Zero or number between 2 and 36 inclusive.
     1601 * @param strict Do not allow any trailing characters.
     1602 * @param result Result of the conversion.
     1603 *
     1604 * @return EOK if conversion was successful.
     1605 *
     1606 */
     1607errno_t str_uint8_t(const char *nptr, const char **endptr, unsigned int base,
     1608    bool strict, uint8_t *result)
     1609{
     1610        assert(result != NULL);
     1611
     1612        bool neg;
     1613        char *lendptr;
     1614        uint64_t res;
     1615        errno_t ret = str_uint(nptr, &lendptr, base, &neg, &res);
     1616
     1617        if (endptr != NULL)
     1618                *endptr = (char *) lendptr;
     1619
     1620        if (ret != EOK)
     1621                return ret;
     1622
     1623        /* Do not allow negative values */
     1624        if (neg)
     1625                return EINVAL;
     1626
     1627        /*
     1628         * Check whether we are at the end of
     1629         * the string in strict mode
     1630         */
     1631        if ((strict) && (*lendptr != 0))
     1632                return EINVAL;
     1633
     1634        /* Check for overflow */
     1635        uint8_t _res = (uint8_t) res;
     1636        if (_res != res)
     1637                return EOVERFLOW;
     1638
     1639        *result = _res;
     1640
     1641        return EOK;
     1642}
     1643
     1644/** Convert string to uint16_t.
     1645 *
     1646 * @param nptr   Pointer to string.
     1647 * @param endptr If not NULL, pointer to the first invalid character
     1648 *               is stored here.
     1649 * @param base   Zero or number between 2 and 36 inclusive.
     1650 * @param strict Do not allow any trailing characters.
     1651 * @param result Result of the conversion.
     1652 *
     1653 * @return EOK if conversion was successful.
     1654 *
     1655 */
     1656errno_t str_uint16_t(const char *nptr, const char **endptr, unsigned int base,
     1657    bool strict, uint16_t *result)
     1658{
     1659        assert(result != NULL);
     1660
     1661        bool neg;
     1662        char *lendptr;
     1663        uint64_t res;
     1664        errno_t ret = str_uint(nptr, &lendptr, base, &neg, &res);
     1665
     1666        if (endptr != NULL)
     1667                *endptr = (char *) lendptr;
     1668
     1669        if (ret != EOK)
     1670                return ret;
     1671
     1672        /* Do not allow negative values */
     1673        if (neg)
     1674                return EINVAL;
     1675
     1676        /*
     1677         * Check whether we are at the end of
     1678         * the string in strict mode
     1679         */
     1680        if ((strict) && (*lendptr != 0))
     1681                return EINVAL;
     1682
     1683        /* Check for overflow */
     1684        uint16_t _res = (uint16_t) res;
     1685        if (_res != res)
     1686                return EOVERFLOW;
     1687
     1688        *result = _res;
     1689
     1690        return EOK;
     1691}
     1692
     1693/** Convert string to uint32_t.
     1694 *
     1695 * @param nptr   Pointer to string.
     1696 * @param endptr If not NULL, pointer to the first invalid character
     1697 *               is stored here.
     1698 * @param base   Zero or number between 2 and 36 inclusive.
     1699 * @param strict Do not allow any trailing characters.
     1700 * @param result Result of the conversion.
     1701 *
     1702 * @return EOK if conversion was successful.
     1703 *
     1704 */
     1705errno_t str_uint32_t(const char *nptr, const char **endptr, unsigned int base,
     1706    bool strict, uint32_t *result)
     1707{
     1708        assert(result != NULL);
     1709
     1710        bool neg;
     1711        char *lendptr;
     1712        uint64_t res;
     1713        errno_t ret = str_uint(nptr, &lendptr, base, &neg, &res);
     1714
     1715        if (endptr != NULL)
     1716                *endptr = (char *) lendptr;
     1717
     1718        if (ret != EOK)
     1719                return ret;
     1720
     1721        /* Do not allow negative values */
     1722        if (neg)
     1723                return EINVAL;
     1724
     1725        /*
     1726         * Check whether we are at the end of
     1727         * the string in strict mode
     1728         */
     1729        if ((strict) && (*lendptr != 0))
     1730                return EINVAL;
     1731
     1732        /* Check for overflow */
     1733        uint32_t _res = (uint32_t) res;
     1734        if (_res != res)
     1735                return EOVERFLOW;
     1736
     1737        *result = _res;
     1738
     1739        return EOK;
     1740}
     1741
     1742/** Convert string to uint64_t.
     1743 *
     1744 * @param nptr   Pointer to string.
     1745 * @param endptr If not NULL, pointer to the first invalid character
     1746 *               is stored here.
     1747 * @param base   Zero or number between 2 and 36 inclusive.
     1748 * @param strict Do not allow any trailing characters.
     1749 * @param result Result of the conversion.
     1750 *
     1751 * @return EOK if conversion was successful.
     1752 *
     1753 */
     1754errno_t str_uint64_t(const char *nptr, const char **endptr, unsigned int base,
     1755    bool strict, uint64_t *result)
     1756{
     1757        assert(result != NULL);
     1758
     1759        bool neg;
     1760        char *lendptr;
     1761        errno_t ret = str_uint(nptr, &lendptr, base, &neg, result);
     1762
     1763        if (endptr != NULL)
     1764                *endptr = (char *) lendptr;
     1765
     1766        if (ret != EOK)
     1767                return ret;
     1768
     1769        /* Do not allow negative values */
     1770        if (neg)
     1771                return EINVAL;
     1772
     1773        /*
     1774         * Check whether we are at the end of
     1775         * the string in strict mode
     1776         */
     1777        if ((strict) && (*lendptr != 0))
     1778                return EINVAL;
     1779
     1780        return EOK;
     1781}
     1782
     1783/** Convert string to int64_t.
     1784 *
     1785 * @param nptr   Pointer to string.
     1786 * @param endptr If not NULL, pointer to the first invalid character
     1787 *               is stored here.
     1788 * @param base   Zero or number between 2 and 36 inclusive.
     1789 * @param strict Do not allow any trailing characters.
     1790 * @param result Result of the conversion.
     1791 *
     1792 * @return EOK if conversion was successful.
     1793 *
     1794 */
     1795int str_int64_t(const char *nptr, const char **endptr, unsigned int base,
     1796    bool strict, int64_t *result)
     1797{
     1798        assert(result != NULL);
     1799
     1800        bool neg;
     1801        char *lendptr;
     1802        uint64_t unsigned_result;
     1803        int ret = str_uint(nptr, &lendptr, base, &neg, &unsigned_result);
     1804
     1805        if (endptr != NULL)
     1806                *endptr = (char *) lendptr;
     1807
     1808        if (ret != EOK)
     1809                return ret;
     1810
     1811        /* Do not allow negative values */
     1812        if (neg) {
     1813                if (unsigned_result == UINT64_MAX)
     1814                        return EINVAL;
     1815
     1816                *result = -(int64_t) unsigned_result;
     1817        } else
     1818                *result = unsigned_result;
     1819
     1820        /*
     1821         * Check whether we are at the end of
     1822         * the string in strict mode
     1823         */
     1824        if ((strict) && (*lendptr != 0))
     1825                return EINVAL;
     1826
     1827        return EOK;
     1828}
     1829
     1830/** Convert string to size_t.
     1831 *
     1832 * @param nptr   Pointer to string.
     1833 * @param endptr If not NULL, pointer to the first invalid character
     1834 *               is stored here.
     1835 * @param base   Zero or number between 2 and 36 inclusive.
     1836 * @param strict Do not allow any trailing characters.
     1837 * @param result Result of the conversion.
     1838 *
     1839 * @return EOK if conversion was successful.
     1840 *
     1841 */
     1842errno_t str_size_t(const char *nptr, const char **endptr, unsigned int base,
     1843    bool strict, size_t *result)
     1844{
     1845        assert(result != NULL);
     1846
     1847        bool neg;
     1848        char *lendptr;
     1849        uint64_t res;
     1850        errno_t ret = str_uint(nptr, &lendptr, base, &neg, &res);
     1851
     1852        if (endptr != NULL)
     1853                *endptr = (char *) lendptr;
     1854
     1855        if (ret != EOK)
     1856                return ret;
     1857
     1858        /* Do not allow negative values */
     1859        if (neg)
     1860                return EINVAL;
     1861
     1862        /*
     1863         * Check whether we are at the end of
     1864         * the string in strict mode
     1865         */
     1866        if ((strict) && (*lendptr != 0))
     1867                return EINVAL;
     1868
     1869        /* Check for overflow */
     1870        size_t _res = (size_t) res;
     1871        if (_res != res)
     1872                return EOVERFLOW;
     1873
     1874        *result = _res;
     1875
     1876        return EOK;
    14731877}
    14741878
  • uspace/lib/c/generic/strtol.c

    rb401b33 r83b64a59  
    4444#include <stdbool.h>
    4545#include <stdlib.h>
    46 #include <str.h>
    47 
    48 // FIXME: The original HelenOS functions return EOVERFLOW instead
    49 //        of ERANGE. It's a pointless distinction from standard functions,
    50 //        so we should change that. Beware the callers though.
    51 
    52 // TODO: more unit tests
     46
     47// TODO: unit tests
    5348
    5449static inline int _digit_value(int c)
     
    7469}
    7570
    76 static inline int _prefixbase(const char *restrict *nptrptr, bool nonstd)
    77 {
    78         const char *nptr = *nptrptr;
    79 
    80         if (nptr[0] != '0')
    81                 return 10;
    82 
    83         if (nptr[1] == 'x' || nptr[1] == 'X') {
    84                 if (_digit_value(nptr[2]) < 16) {
    85                         *nptrptr += 2;
    86                         return 16;
    87                 }
    88         }
    89 
    90         if (nonstd) {
    91                 switch (nptr[1]) {
    92                 case 'b':
    93                 case 'B':
    94                         if (_digit_value(nptr[2]) < 2) {
    95                                 *nptrptr += 2;
    96                                 return 2;
    97                         }
    98                         break;
    99                 case 'o':
    100                 case 'O':
    101                         if (_digit_value(nptr[2]) < 8) {
    102                                 *nptrptr += 2;
    103                                 return 8;
    104                         }
    105                         break;
    106                 case 'd':
    107                 case 'D':
    108                 case 't':
    109                 case 'T':
    110                         if (_digit_value(nptr[2]) < 10) {
    111                                 *nptrptr += 2;
    112                                 return 10;
    113                         }
    114                         break;
    115                 }
    116         }
    117 
    118         return 8;
    119 }
    120 
    12171static inline uintmax_t _strtoumax(
    12272    const char *restrict nptr, char **restrict endptr, int base,
    123     bool *restrict sgn, errno_t *err, bool nonstd)
     73    bool *restrict sgn)
    12474{
    12575        assert(nptr != NULL);
    12676        assert(sgn != NULL);
    127 
    128         const char *first = nptr;
    12977
    13078        /* Skip leading whitespace. */
     
    14896        /* Figure out the base. */
    14997
    150         if (base == 0)
    151                 base = _prefixbase(&nptr, nonstd);
    152 
    153         if (base == 16 && !nonstd) {
    154                 /*
    155                  * Standard strto* functions allow hexadecimal prefix to be
    156                  * present when base is explicitly set to 16.
    157                  * Our nonstandard str_* functions don't allow it.
    158                  * I don't know if that is intended, just matching the original
    159                  * functionality here.
    160                  */
    161 
    162                 if (nptr[0] == '0' && (nptr[1] == 'x' || nptr[1] == 'X') &&
    163                     _digit_value(nptr[2]) < base)
     98        if (base == 0) {
     99                if (*nptr == '0') {
     100                        if (tolower(nptr[1]) == 'x') {
     101                                /* 0x... is hex. */
     102                                base = 16;
     103                                nptr += 2;
     104                        } else {
     105                                /* 0... is octal. */
     106                                base = 8;
     107                        }
     108                } else {
     109                        /* Anything else is decimal by default. */
     110                        base = 10;
     111                }
     112        } else if (base == 16) {
     113                /* Allow hex number to be prefixed with "0x". */
     114                if (nptr[0] == '0' && tolower(nptr[1]) == 'x') {
    164115                        nptr += 2;
    165         }
    166 
    167         if (base < 2 || base > 36) {
    168                 *err = EINVAL;
     116                }
     117        } else if (base < 0 || base == 1 || base > 36) {
     118                errno = EINVAL;
    169119                return 0;
    170120        }
    171121
    172         /* Must be at least one digit. */
    173 
    174         if (_digit_value(*nptr) >= base) {
    175                 /* No digits on input. */
    176                 if (endptr != NULL)
    177                         *endptr = (char *) first;
    178                 return 0;
    179         }
    180 
    181         /* Read the value.  */
     122        /* Read the value. */
    182123
    183124        uintmax_t result = 0;
     
    186127
    187128        while (digit = _digit_value(*nptr), digit < base) {
     129
    188130                if (result > max ||
    189131                    __builtin_add_overflow(result * base, digit, &result)) {
    190132
    191                         *err = nonstd ? EOVERFLOW : ERANGE;
     133                        errno = ERANGE;
    192134                        result = UINTMAX_MAX;
    193135                        break;
     
    203145                 * Move the pointer to the end of the number,
    204146                 * in case it isn't there already.
    205                  * This can happen when the number has legal formatting,
    206                  * but is out of range of the target type.
    207147                 */
    208148                while (_digit_value(*nptr) < base) {
     
    217157
    218158static inline intmax_t _strtosigned(const char *nptr, char **endptr, int base,
    219     intmax_t min, intmax_t max, errno_t *err, bool nonstd)
     159    intmax_t min, intmax_t max)
    220160{
    221161        bool sgn = false;
    222         uintmax_t number = _strtoumax(nptr, endptr, base, &sgn, err, nonstd);
     162        uintmax_t number = _strtoumax(nptr, endptr, base, &sgn);
    223163
    224164        if (number > (uintmax_t) max) {
     
    227167                }
    228168
    229                 *err = nonstd ? EOVERFLOW : ERANGE;
     169                errno = ERANGE;
    230170                return (sgn ? min : max);
    231171        }
     
    235175
    236176static inline uintmax_t _strtounsigned(const char *nptr, char **endptr, int base,
    237     uintmax_t max, errno_t *err, bool nonstd)
     177    uintmax_t max)
    238178{
    239179        bool sgn = false;
    240         uintmax_t number = _strtoumax(nptr, endptr, base, &sgn, err, nonstd);
    241 
    242         if (nonstd && sgn) {
    243                 /* Do not allow negative values */
    244                 *err = EINVAL;
    245                 return 0;
     180        uintmax_t number = _strtoumax(nptr, endptr, base, &sgn);
     181
     182        if (sgn) {
     183                if (number == 0) {
     184                        return 0;
     185                } else {
     186                        errno = ERANGE;
     187                        return max;
     188                }
    246189        }
    247190
    248191        if (number > max) {
    249                 *err = nonstd ? EOVERFLOW : ERANGE;
     192                errno = ERANGE;
    250193                return max;
    251194        }
    252195
    253         return (sgn ? -number : number);
     196        return number;
    254197}
    255198
     
    269212long strtol(const char *nptr, char **endptr, int base)
    270213{
    271         return _strtosigned(nptr, endptr, base, LONG_MIN, LONG_MAX, &errno, false);
     214        return _strtosigned(nptr, endptr, base, LONG_MIN, LONG_MAX);
    272215}
    273216
     
    287230unsigned long strtoul(const char *nptr, char **endptr, int base)
    288231{
    289         return _strtounsigned(nptr, endptr, base, ULONG_MAX, &errno, false);
     232        return _strtounsigned(nptr, endptr, base, ULONG_MAX);
    290233}
    291234
    292235long long strtoll(const char *nptr, char **endptr, int base)
    293236{
    294         return _strtosigned(nptr, endptr, base, LLONG_MIN, LLONG_MAX, &errno, false);
     237        return _strtosigned(nptr, endptr, base, LLONG_MIN, LLONG_MAX);
    295238}
    296239
    297240unsigned long long strtoull(const char *nptr, char **endptr, int base)
    298241{
    299         return _strtounsigned(nptr, endptr, base, ULLONG_MAX, &errno, false);
     242        return _strtounsigned(nptr, endptr, base, ULLONG_MAX);
    300243}
    301244
    302245intmax_t strtoimax(const char *nptr, char **endptr, int base)
    303246{
    304         return _strtosigned(nptr, endptr, base, INTMAX_MIN, INTMAX_MAX, &errno, false);
     247        return _strtosigned(nptr, endptr, base, INTMAX_MIN, INTMAX_MAX);
    305248}
    306249
    307250uintmax_t strtoumax(const char *nptr, char **endptr, int base)
    308251{
    309         return _strtounsigned(nptr, endptr, base, UINTMAX_MAX, &errno, false);
     252        return _strtounsigned(nptr, endptr, base, UINTMAX_MAX);
    310253}
    311254
     
    325268}
    326269
    327 /** Convert string to uint8_t.
    328  *
    329  * @param nptr   Pointer to string.
    330  * @param endptr If not NULL, pointer to the first invalid character
    331  *               is stored here.
    332  * @param base   Zero or number between 2 and 36 inclusive.
    333  * @param strict Do not allow any trailing characters.
    334  * @param result Result of the conversion.
    335  *
    336  * @return EOK if conversion was successful.
    337  *
    338  */
    339 errno_t str_uint8_t(const char *nptr, const char **endptr, unsigned int base,
    340     bool strict, uint8_t *result)
    341 {
    342         assert(result != NULL);
    343 
    344         errno_t rc = EOK;
    345         char *lendptr = (char *) nptr;
    346 
    347         uintmax_t r = _strtounsigned(nptr, &lendptr, base, UINT8_MAX, &rc, true);
    348 
    349         if (endptr)
    350                 *endptr = lendptr;
    351 
    352         if (rc != EOK)
    353                 return rc;
    354 
    355         if (strict && *lendptr != '\0')
    356                 return EINVAL;
    357 
    358         *result = r;
    359         return EOK;
    360 }
    361 
    362 /** Convert string to uint16_t.
    363  *
    364  * @param nptr   Pointer to string.
    365  * @param endptr If not NULL, pointer to the first invalid character
    366  *               is stored here.
    367  * @param base   Zero or number between 2 and 36 inclusive.
    368  * @param strict Do not allow any trailing characters.
    369  * @param result Result of the conversion.
    370  *
    371  * @return EOK if conversion was successful.
    372  *
    373  */
    374 errno_t str_uint16_t(const char *nptr, const char **endptr, unsigned int base,
    375     bool strict, uint16_t *result)
    376 {
    377         assert(result != NULL);
    378 
    379         errno_t rc = EOK;
    380         char *lendptr = (char *) nptr;
    381 
    382         uintmax_t r = _strtounsigned(nptr, &lendptr, base, UINT16_MAX, &rc, true);
    383 
    384         if (endptr)
    385                 *endptr = lendptr;
    386 
    387         if (rc != EOK)
    388                 return rc;
    389 
    390         if (strict && *lendptr != '\0')
    391                 return EINVAL;
    392 
    393         *result = r;
    394         return EOK;
    395 }
    396 
    397 /** Convert string to uint32_t.
    398  *
    399  * @param nptr   Pointer to string.
    400  * @param endptr If not NULL, pointer to the first invalid character
    401  *               is stored here.
    402  * @param base   Zero or number between 2 and 36 inclusive.
    403  * @param strict Do not allow any trailing characters.
    404  * @param result Result of the conversion.
    405  *
    406  * @return EOK if conversion was successful.
    407  *
    408  */
    409 errno_t str_uint32_t(const char *nptr, const char **endptr, unsigned int base,
    410     bool strict, uint32_t *result)
    411 {
    412         assert(result != NULL);
    413 
    414         errno_t rc = EOK;
    415         char *lendptr = (char *) nptr;
    416 
    417         uintmax_t r = _strtounsigned(nptr, &lendptr, base, UINT32_MAX, &rc, true);
    418 
    419         if (endptr)
    420                 *endptr = lendptr;
    421 
    422         if (rc != EOK)
    423                 return rc;
    424 
    425         if (strict && *lendptr != '\0')
    426                 return EINVAL;
    427 
    428         *result = r;
    429         return EOK;
    430 }
    431 
    432 /** Convert string to uint64_t.
    433  *
    434  * @param nptr   Pointer to string.
    435  * @param endptr If not NULL, pointer to the first invalid character
    436  *               is stored here.
    437  * @param base   Zero or number between 2 and 36 inclusive.
    438  * @param strict Do not allow any trailing characters.
    439  * @param result Result of the conversion.
    440  *
    441  * @return EOK if conversion was successful.
    442  *
    443  */
    444 errno_t str_uint64_t(const char *nptr, const char **endptr, unsigned int base,
    445     bool strict, uint64_t *result)
    446 {
    447         assert(result != NULL);
    448 
    449         errno_t rc = EOK;
    450         char *lendptr = (char *) nptr;
    451 
    452         uintmax_t r = _strtounsigned(nptr, &lendptr, base, UINT64_MAX, &rc, true);
    453 
    454         if (endptr)
    455                 *endptr = lendptr;
    456 
    457         if (rc != EOK)
    458                 return rc;
    459 
    460         if (strict && *lendptr != '\0')
    461                 return EINVAL;
    462 
    463         *result = r;
    464         return EOK;
    465 }
    466 
    467 /** Convert string to int64_t.
    468  *
    469  * @param nptr   Pointer to string.
    470  * @param endptr If not NULL, pointer to the first invalid character
    471  *               is stored here.
    472  * @param base   Zero or number between 2 and 36 inclusive.
    473  * @param strict Do not allow any trailing characters.
    474  * @param result Result of the conversion.
    475  *
    476  * @return EOK if conversion was successful.
    477  *
    478  */
    479 errno_t str_int64_t(const char *nptr, const char **endptr, unsigned int base,
    480     bool strict, int64_t *result)
    481 {
    482         assert(result != NULL);
    483 
    484         errno_t rc = EOK;
    485         char *lendptr = (char *) nptr;
    486 
    487         intmax_t r = _strtosigned(nptr, &lendptr, base, INT64_MIN, INT64_MAX, &rc, true);
    488 
    489         if (endptr)
    490                 *endptr = lendptr;
    491 
    492         if (rc != EOK)
    493                 return rc;
    494 
    495         if (strict && *lendptr != '\0')
    496                 return EINVAL;
    497 
    498         *result = r;
    499         return EOK;
    500 }
    501 
    502 /** Convert string to size_t.
    503  *
    504  * @param nptr   Pointer to string.
    505  * @param endptr If not NULL, pointer to the first invalid character
    506  *               is stored here.
    507  * @param base   Zero or number between 2 and 36 inclusive.
    508  * @param strict Do not allow any trailing characters.
    509  * @param result Result of the conversion.
    510  *
    511  * @return EOK if conversion was successful.
    512  *
    513  */
    514 errno_t str_size_t(const char *nptr, const char **endptr, unsigned int base,
    515     bool strict, size_t *result)
    516 {
    517         assert(result != NULL);
    518 
    519         errno_t rc = EOK;
    520         char *lendptr = (char *) nptr;
    521 
    522         uintmax_t r = _strtounsigned(nptr, &lendptr, base, SIZE_MAX, &rc, true);
    523 
    524         if (endptr)
    525                 *endptr = lendptr;
    526 
    527         if (rc != EOK)
    528                 return rc;
    529 
    530         if (strict && *lendptr != '\0')
    531                 return EINVAL;
    532 
    533         *result = r;
    534         return EOK;
    535 }
    536 
    537270/** @}
    538271 */
  • uspace/lib/c/include/str.h

    rb401b33 r83b64a59  
    137137extern errno_t str_size_t(const char *, const char **, unsigned int, bool,
    138138    size_t *);
    139 extern errno_t str_int64_t(const char *, const char **, unsigned int, bool,
     139extern int str_int64_t(const char *, const char **, unsigned int, bool,
    140140    int64_t *);
    141141
  • uspace/lib/c/test/strtol.c

    rb401b33 r83b64a59  
    3838#include <stdlib.h>
    3939#include <str.h>
    40 #include <limits.h>
    4140
    4241PCUT_INIT;
     
    218217        /* Correct result. */
    219218        PCUT_ASSERT_INT_EQUALS(EOVERFLOW, rc);
     219        PCUT_ASSERT_UINT_EQUALS(UINT64_MAX, result);
    220220#endif
    221221
     
    245245        /* Correct result. */
    246246        PCUT_ASSERT_INT_EQUALS(EOVERFLOW, rc);
     247        PCUT_ASSERT_UINT_EQUALS(UINT64_MAX, result);
    247248#endif
    248 }
    249 
    250 PCUT_TEST(strtoul_negative_wraparound)
    251 {
    252         long output;
    253         char *endp;
    254         char *endp_unchanged = (char *) "endp_unchanged unique pointer";
    255         int errno_unchanged = -1;
    256         const char *input;
    257         int base;
    258 
    259         /*
    260          * N2176 7.22.1.4 The strtol, strtoll, strtoul, and strtoull functions
    261          *
    262          * "If the subject sequence begins with a minus sign, the value
    263          * resulting from the conversion is negated (in the return type)."
    264          */
    265 
    266         endp = endp_unchanged;
    267         errno = errno_unchanged;
    268         output = strtoul(input = "-10", &endp, base = 0);
    269         PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno);
    270         PCUT_ASSERT_PTR_EQUALS(input + 3, endp);
    271         PCUT_ASSERT_UINT_EQUALS(-(10ul), output);
    272249}
    273250
     
    427404        endp = endp_unchanged;
    428405        errno = errno_unchanged;
    429         output = strtol(input = "    0xg", &endp, base = 0);
    430         PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno);
    431         PCUT_ASSERT_PTR_EQUALS(input + 5, endp);
    432         PCUT_ASSERT_INT_EQUALS(0, output);
    433 
    434         endp = endp_unchanged;
    435         errno = errno_unchanged;
    436406        output = strtol(input = "    0x1", &endp, base = 0);
    437407        PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno);
     
    448418        endp = endp_unchanged;
    449419        errno = errno_unchanged;
    450         output = strtol(input = "    0xg", &endp, base = 16);
    451         PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno);
    452         PCUT_ASSERT_PTR_EQUALS(input + 5, endp);
    453         PCUT_ASSERT_INT_EQUALS(0, output);
    454 
    455         endp = endp_unchanged;
    456         errno = errno_unchanged;
    457         output = strtol(input = "    g", &endp, base = 16);
    458         PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno);
    459         PCUT_ASSERT_PTR_EQUALS(input, endp);
    460         PCUT_ASSERT_INT_EQUALS(0, output);
    461 
    462         endp = endp_unchanged;
    463         errno = errno_unchanged;
    464420        output = strtol(input = "    0x1", &endp, base = 16);
    465421        PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno);
    466422        PCUT_ASSERT_PTR_EQUALS(input + 7, endp);
    467423        PCUT_ASSERT_INT_EQUALS(1, output);
    468 
    469         endp = endp_unchanged;
    470         errno = errno_unchanged;
    471         output = strtol(input = "    +", &endp, base = 0);
    472         PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno);
    473         PCUT_ASSERT_PTR_EQUALS(input, endp);
    474         PCUT_ASSERT_INT_EQUALS(0, output);
    475 
    476         endp = endp_unchanged;
    477         errno = errno_unchanged;
    478         output = strtol(input = "    -", &endp, base = 0);
    479         PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno);
    480         PCUT_ASSERT_PTR_EQUALS(input, endp);
    481         PCUT_ASSERT_INT_EQUALS(0, output);
    482 
    483         endp = endp_unchanged;
    484         errno = errno_unchanged;
    485         output = strtol(input = "    +", &endp, base = 10);
    486         PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno);
    487         PCUT_ASSERT_PTR_EQUALS(input, endp);
    488         PCUT_ASSERT_INT_EQUALS(0, output);
    489 
    490         endp = endp_unchanged;
    491         errno = errno_unchanged;
    492         output = strtol(input = "    -", &endp, base = 10);
    493         PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno);
    494         PCUT_ASSERT_PTR_EQUALS(input, endp);
    495         PCUT_ASSERT_INT_EQUALS(0, output);
    496 
    497         endp = endp_unchanged;
    498         errno = errno_unchanged;
    499         output = strtol(input = "+", &endp, base = 0);
    500         PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno);
    501         PCUT_ASSERT_PTR_EQUALS(input, endp);
    502         PCUT_ASSERT_INT_EQUALS(0, output);
    503 
    504         endp = endp_unchanged;
    505         errno = errno_unchanged;
    506         output = strtol(input = "-", &endp, base = 0);
    507         PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno);
    508         PCUT_ASSERT_PTR_EQUALS(input, endp);
    509         PCUT_ASSERT_INT_EQUALS(0, output);
    510 
    511         endp = endp_unchanged;
    512         errno = errno_unchanged;
    513         output = strtol(input = "+", &endp, base = 10);
    514         PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno);
    515         PCUT_ASSERT_PTR_EQUALS(input, endp);
    516         PCUT_ASSERT_INT_EQUALS(0, output);
    517 
    518         endp = endp_unchanged;
    519         errno = errno_unchanged;
    520         output = strtol(input = "-", &endp, base = 10);
    521         PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno);
    522         PCUT_ASSERT_PTR_EQUALS(input, endp);
    523         PCUT_ASSERT_INT_EQUALS(0, output);
    524424}
    525425
Note: See TracChangeset for help on using the changeset viewer.