Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/c/generic/str.c

    r1c9bf292 rd066259  
    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
Note: See TracChangeset for help on using the changeset viewer.