Changes in uspace/lib/c/generic/str.c [1c9bf292:d066259] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/str.c
r1c9bf292 rd066259 1471 1471 *end = '\0'; 1472 1472 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 */ 1486 static 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 */ 1607 errno_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 */ 1656 errno_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 */ 1705 errno_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 */ 1754 errno_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 */ 1795 int 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 */ 1842 errno_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; 1473 1877 } 1474 1878
Note:
See TracChangeset
for help on using the changeset viewer.