Changeset b401b33 in mainline for uspace/lib/c/generic/str.c
- Timestamp:
- 2019-06-06T12:15:29Z (5 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 2a103b5, e28175d
- Parents:
- 83b64a59 (diff), 42e91ae (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - git-author:
- Jiří Zárevúcky <zarevucky.jiri@…> (2019-06-06 12:15:29)
- git-committer:
- GitHub <noreply@…> (2019-06-06 12:15:29)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/str.c
r83b64a59 rb401b33 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 else1562 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 is1582 * 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 character1599 * 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 of1629 * the string in strict mode1630 */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 character1648 * 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 of1678 * the string in strict mode1679 */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 character1697 * 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 of1727 * the string in strict mode1728 */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 character1746 * 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 of1775 * the string in strict mode1776 */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 character1787 * 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 } else1818 *result = unsigned_result;1819 1820 /*1821 * Check whether we are at the end of1822 * the string in strict mode1823 */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 character1834 * 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 of1864 * the string in strict mode1865 */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;1877 1473 } 1878 1474
Note:
See TracChangeset
for help on using the changeset viewer.