Changeset b401b33 in mainline
- Timestamp:
- 2019-06-06T12:15:29Z (6 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)
- Files:
-
- 1 added
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/Makefile
r83b64a59 rb401b33 207 207 generic/src/lib/gsort.c \ 208 208 generic/src/lib/str.c \ 209 generic/src/lib/strtol.c \ 209 210 generic/src/lib/str_error.c \ 210 211 generic/src/lib/elf.c \ -
kernel/generic/src/lib/str.c
r83b64a59 rb401b33 789 789 str_ncpy(dest, size + 1, src, size); 790 790 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 */804 static 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 else880 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 is900 * 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 character917 * 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 */925 errno_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 of946 * the string in strict mode947 */948 if ((strict) && (*lendptr != 0))949 return EINVAL;950 951 return EOK;952 791 } 953 792 -
uspace/lib/c/generic/ctype.c
r83b64a59 rb401b33 90 90 case '\v': 91 91 return 1; 92 break;93 92 default: 94 93 return 0; -
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 -
uspace/lib/c/generic/strtol.c
r83b64a59 rb401b33 44 44 #include <stdbool.h> 45 45 #include <stdlib.h> 46 47 // TODO: unit tests 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 48 53 49 54 static inline int _digit_value(int c) … … 69 74 } 70 75 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 71 121 static inline uintmax_t _strtoumax( 72 122 const char *restrict nptr, char **restrict endptr, int base, 73 bool *restrict sgn )123 bool *restrict sgn, errno_t *err, bool nonstd) 74 124 { 75 125 assert(nptr != NULL); 76 126 assert(sgn != NULL); 127 128 const char *first = nptr; 77 129 78 130 /* Skip leading whitespace. */ … … 96 148 /* Figure out the base. */ 97 149 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') { 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) 115 164 nptr += 2; 116 } 117 } else if (base < 0 || base == 1 || base > 36) { 118 errno = EINVAL; 165 } 166 167 if (base < 2 || base > 36) { 168 *err = EINVAL; 119 169 return 0; 120 170 } 121 171 122 /* Read the value. */ 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. */ 123 182 124 183 uintmax_t result = 0; … … 127 186 128 187 while (digit = _digit_value(*nptr), digit < base) { 129 130 188 if (result > max || 131 189 __builtin_add_overflow(result * base, digit, &result)) { 132 190 133 errno =ERANGE;191 *err = nonstd ? EOVERFLOW : ERANGE; 134 192 result = UINTMAX_MAX; 135 193 break; … … 145 203 * Move the pointer to the end of the number, 146 204 * 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. 147 207 */ 148 208 while (_digit_value(*nptr) < base) { … … 157 217 158 218 static inline intmax_t _strtosigned(const char *nptr, char **endptr, int base, 159 intmax_t min, intmax_t max )219 intmax_t min, intmax_t max, errno_t *err, bool nonstd) 160 220 { 161 221 bool sgn = false; 162 uintmax_t number = _strtoumax(nptr, endptr, base, &sgn );222 uintmax_t number = _strtoumax(nptr, endptr, base, &sgn, err, nonstd); 163 223 164 224 if (number > (uintmax_t) max) { … … 167 227 } 168 228 169 errno =ERANGE;229 *err = nonstd ? EOVERFLOW : ERANGE; 170 230 return (sgn ? min : max); 171 231 } … … 175 235 176 236 static inline uintmax_t _strtounsigned(const char *nptr, char **endptr, int base, 177 uintmax_t max )237 uintmax_t max, errno_t *err, bool nonstd) 178 238 { 179 239 bool sgn = false; 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 } 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; 189 246 } 190 247 191 248 if (number > max) { 192 errno =ERANGE;249 *err = nonstd ? EOVERFLOW : ERANGE; 193 250 return max; 194 251 } 195 252 196 return number;253 return (sgn ? -number : number); 197 254 } 198 255 … … 212 269 long strtol(const char *nptr, char **endptr, int base) 213 270 { 214 return _strtosigned(nptr, endptr, base, LONG_MIN, LONG_MAX );271 return _strtosigned(nptr, endptr, base, LONG_MIN, LONG_MAX, &errno, false); 215 272 } 216 273 … … 230 287 unsigned long strtoul(const char *nptr, char **endptr, int base) 231 288 { 232 return _strtounsigned(nptr, endptr, base, ULONG_MAX );289 return _strtounsigned(nptr, endptr, base, ULONG_MAX, &errno, false); 233 290 } 234 291 235 292 long long strtoll(const char *nptr, char **endptr, int base) 236 293 { 237 return _strtosigned(nptr, endptr, base, LLONG_MIN, LLONG_MAX );294 return _strtosigned(nptr, endptr, base, LLONG_MIN, LLONG_MAX, &errno, false); 238 295 } 239 296 240 297 unsigned long long strtoull(const char *nptr, char **endptr, int base) 241 298 { 242 return _strtounsigned(nptr, endptr, base, ULLONG_MAX );299 return _strtounsigned(nptr, endptr, base, ULLONG_MAX, &errno, false); 243 300 } 244 301 245 302 intmax_t strtoimax(const char *nptr, char **endptr, int base) 246 303 { 247 return _strtosigned(nptr, endptr, base, INTMAX_MIN, INTMAX_MAX );304 return _strtosigned(nptr, endptr, base, INTMAX_MIN, INTMAX_MAX, &errno, false); 248 305 } 249 306 250 307 uintmax_t strtoumax(const char *nptr, char **endptr, int base) 251 308 { 252 return _strtounsigned(nptr, endptr, base, UINTMAX_MAX );309 return _strtounsigned(nptr, endptr, base, UINTMAX_MAX, &errno, false); 253 310 } 254 311 … … 268 325 } 269 326 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 270 537 /** @} 271 538 */ -
uspace/lib/c/include/str.h
r83b64a59 rb401b33 137 137 extern errno_t str_size_t(const char *, const char **, unsigned int, bool, 138 138 size_t *); 139 extern int str_int64_t(const char *, const char **, unsigned int, bool,139 extern errno_t str_int64_t(const char *, const char **, unsigned int, bool, 140 140 int64_t *); 141 141 -
uspace/lib/c/test/strtol.c
r83b64a59 rb401b33 38 38 #include <stdlib.h> 39 39 #include <str.h> 40 #include <limits.h> 40 41 41 42 PCUT_INIT; … … 217 218 /* Correct result. */ 218 219 PCUT_ASSERT_INT_EQUALS(EOVERFLOW, rc); 219 PCUT_ASSERT_UINT_EQUALS(UINT64_MAX, result);220 220 #endif 221 221 … … 245 245 /* Correct result. */ 246 246 PCUT_ASSERT_INT_EQUALS(EOVERFLOW, rc); 247 PCUT_ASSERT_UINT_EQUALS(UINT64_MAX, result);248 247 #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); 249 272 } 250 273 … … 404 427 endp = endp_unchanged; 405 428 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; 406 436 output = strtol(input = " 0x1", &endp, base = 0); 407 437 PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno); … … 418 448 endp = endp_unchanged; 419 449 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; 420 464 output = strtol(input = " 0x1", &endp, base = 16); 421 465 PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno); 422 466 PCUT_ASSERT_PTR_EQUALS(input + 7, endp); 423 467 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); 424 524 } 425 525
Note:
See TracChangeset
for help on using the changeset viewer.