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