Changes in uspace/lib/c/generic/str.c [1c9bf292:09ab0a9a] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/str.c
r1c9bf292 r09ab0a9a 1 1 /* 2 * Copyright (c) 2001-2004 Jakub Jermar3 2 * Copyright (c) 2005 Martin Decky 4 3 * Copyright (c) 2008 Jiri Svoboda … … 34 33 * @{ 35 34 */ 36 37 /** 38 * @file 39 * @brief String functions. 40 * 41 * Strings and characters use the Universal Character Set (UCS). The standard 42 * strings, called just strings are encoded in UTF-8. Wide strings (encoded 43 * in UTF-32) are supported to a limited degree. A single character is 44 * represented as wchar_t.@n 45 * 46 * Overview of the terminology:@n 47 * 48 * Term Meaning 49 * -------------------- ---------------------------------------------------- 50 * byte 8 bits stored in uint8_t (unsigned 8 bit integer) 51 * 52 * character UTF-32 encoded Unicode character, stored in wchar_t 53 * (signed 32 bit integer), code points 0 .. 1114111 54 * are valid 55 * 56 * ASCII character 7 bit encoded ASCII character, stored in char 57 * (usually signed 8 bit integer), code points 0 .. 127 58 * are valid 59 * 60 * string UTF-8 encoded NULL-terminated Unicode string, char * 61 * 62 * wide string UTF-32 encoded NULL-terminated Unicode string, 63 * wchar_t * 64 * 65 * [wide] string size number of BYTES in a [wide] string (excluding 66 * the NULL-terminator), size_t 67 * 68 * [wide] string length number of CHARACTERS in a [wide] string (excluding 69 * the NULL-terminator), size_t 70 * 71 * [wide] string width number of display cells on a monospace display taken 72 * by a [wide] string, size_t 73 * 74 * 75 * Overview of string metrics:@n 76 * 77 * Metric Abbrev. Type Meaning 78 * ------ ------ ------ ------------------------------------------------- 79 * size n size_t number of BYTES in a string (excluding the 80 * NULL-terminator) 81 * 82 * length l size_t number of CHARACTERS in a string (excluding the 83 * null terminator) 84 * 85 * width w size_t number of display cells on a monospace display 86 * taken by a string 87 * 88 * 89 * Function naming prefixes:@n 90 * 91 * chr_ operate on characters 92 * ascii_ operate on ASCII characters 93 * str_ operate on strings 94 * wstr_ operate on wide strings 95 * 96 * [w]str_[n|l|w] operate on a prefix limited by size, length 97 * or width 98 * 99 * 100 * A specific character inside a [wide] string can be referred to by:@n 101 * 102 * pointer (char *, wchar_t *) 103 * byte offset (size_t) 104 * character index (size_t) 105 * 35 /** @file 106 36 */ 107 37 108 38 #include <str.h> 109 39 #include <stddef.h> 40 #include <stdint.h> 41 #include <stdlib.h> 110 42 #include <assert.h> 111 43 #include <ctype.h> 112 44 #include <errno.h> 113 #include <stdbool.h>114 #include <stddef.h>115 #include <stdint.h>116 #include <stdlib.h>117 118 45 #include <align.h> 119 46 #include <mem.h> 47 #include <limits.h> 120 48 121 49 /** Check the condition if wchar_t is signed */ … … 819 747 /* There must be space for a null terminator in the buffer. */ 820 748 assert(size > 0); 821 assert(src != NULL);822 749 823 750 size_t src_off = 0; … … 1384 1311 { 1385 1312 size_t size = str_size(src) + 1; 1386 char *dest = malloc(size);1387 if ( !dest)1388 return NULL;1313 char *dest = (char *) malloc(size); 1314 if (dest == NULL) 1315 return (char *) NULL; 1389 1316 1390 1317 str_cpy(dest, size, src); … … 1418 1345 size = n; 1419 1346 1420 char *dest = malloc(size + 1);1421 if ( !dest)1422 return NULL;1347 char *dest = (char *) malloc(size + 1); 1348 if (dest == NULL) 1349 return (char *) NULL; 1423 1350 1424 1351 str_ncpy(dest, size + 1, src, size); … … 1471 1398 *end = '\0'; 1472 1399 return start; 1400 } 1401 1402 /** Convert string to uint64_t (internal variant). 1403 * 1404 * @param nptr Pointer to string. 1405 * @param endptr Pointer to the first invalid character is stored here. 1406 * @param base Zero or number between 2 and 36 inclusive. 1407 * @param neg Indication of unary minus is stored here. 1408 * @apram result Result of the conversion. 1409 * 1410 * @return EOK if conversion was successful. 1411 * 1412 */ 1413 static errno_t str_uint(const char *nptr, char **endptr, unsigned int base, 1414 bool *neg, uint64_t *result) 1415 { 1416 assert(endptr != NULL); 1417 assert(neg != NULL); 1418 assert(result != NULL); 1419 1420 *neg = false; 1421 const char *str = nptr; 1422 1423 /* Ignore leading whitespace */ 1424 while (isspace(*str)) 1425 str++; 1426 1427 if (*str == '-') { 1428 *neg = true; 1429 str++; 1430 } else if (*str == '+') 1431 str++; 1432 1433 if (base == 0) { 1434 /* Decode base if not specified */ 1435 base = 10; 1436 1437 if (*str == '0') { 1438 base = 8; 1439 str++; 1440 1441 switch (*str) { 1442 case 'b': 1443 case 'B': 1444 base = 2; 1445 str++; 1446 break; 1447 case 'o': 1448 case 'O': 1449 base = 8; 1450 str++; 1451 break; 1452 case 'd': 1453 case 'D': 1454 case 't': 1455 case 'T': 1456 base = 10; 1457 str++; 1458 break; 1459 case 'x': 1460 case 'X': 1461 base = 16; 1462 str++; 1463 break; 1464 default: 1465 str--; 1466 } 1467 } 1468 } else { 1469 /* Check base range */ 1470 if ((base < 2) || (base > 36)) { 1471 *endptr = (char *) str; 1472 return EINVAL; 1473 } 1474 } 1475 1476 *result = 0; 1477 const char *startstr = str; 1478 1479 while (*str != 0) { 1480 unsigned int digit; 1481 1482 if ((*str >= 'a') && (*str <= 'z')) 1483 digit = *str - 'a' + 10; 1484 else if ((*str >= 'A') && (*str <= 'Z')) 1485 digit = *str - 'A' + 10; 1486 else if ((*str >= '0') && (*str <= '9')) 1487 digit = *str - '0'; 1488 else 1489 break; 1490 1491 if (digit >= base) 1492 break; 1493 1494 uint64_t prev = *result; 1495 *result = (*result) * base + digit; 1496 1497 if (*result < prev) { 1498 /* Overflow */ 1499 *endptr = (char *) str; 1500 return EOVERFLOW; 1501 } 1502 1503 str++; 1504 } 1505 1506 if (str == startstr) { 1507 /* 1508 * No digits were decoded => first invalid character is 1509 * the first character of the string. 1510 */ 1511 str = nptr; 1512 } 1513 1514 *endptr = (char *) str; 1515 1516 if (str == nptr) 1517 return EINVAL; 1518 1519 return EOK; 1520 } 1521 1522 /** Convert string to uint8_t. 1523 * 1524 * @param nptr Pointer to string. 1525 * @param endptr If not NULL, pointer to the first invalid character 1526 * is stored here. 1527 * @param base Zero or number between 2 and 36 inclusive. 1528 * @param strict Do not allow any trailing characters. 1529 * @param result Result of the conversion. 1530 * 1531 * @return EOK if conversion was successful. 1532 * 1533 */ 1534 errno_t str_uint8_t(const char *nptr, const char **endptr, unsigned int base, 1535 bool strict, uint8_t *result) 1536 { 1537 assert(result != NULL); 1538 1539 bool neg; 1540 char *lendptr; 1541 uint64_t res; 1542 errno_t ret = str_uint(nptr, &lendptr, base, &neg, &res); 1543 1544 if (endptr != NULL) 1545 *endptr = (char *) lendptr; 1546 1547 if (ret != EOK) 1548 return ret; 1549 1550 /* Do not allow negative values */ 1551 if (neg) 1552 return EINVAL; 1553 1554 /* 1555 * Check whether we are at the end of 1556 * the string in strict mode 1557 */ 1558 if ((strict) && (*lendptr != 0)) 1559 return EINVAL; 1560 1561 /* Check for overflow */ 1562 uint8_t _res = (uint8_t) res; 1563 if (_res != res) 1564 return EOVERFLOW; 1565 1566 *result = _res; 1567 1568 return EOK; 1569 } 1570 1571 /** Convert string to uint16_t. 1572 * 1573 * @param nptr Pointer to string. 1574 * @param endptr If not NULL, pointer to the first invalid character 1575 * is stored here. 1576 * @param base Zero or number between 2 and 36 inclusive. 1577 * @param strict Do not allow any trailing characters. 1578 * @param result Result of the conversion. 1579 * 1580 * @return EOK if conversion was successful. 1581 * 1582 */ 1583 errno_t str_uint16_t(const char *nptr, const char **endptr, unsigned int base, 1584 bool strict, uint16_t *result) 1585 { 1586 assert(result != NULL); 1587 1588 bool neg; 1589 char *lendptr; 1590 uint64_t res; 1591 errno_t ret = str_uint(nptr, &lendptr, base, &neg, &res); 1592 1593 if (endptr != NULL) 1594 *endptr = (char *) lendptr; 1595 1596 if (ret != EOK) 1597 return ret; 1598 1599 /* Do not allow negative values */ 1600 if (neg) 1601 return EINVAL; 1602 1603 /* 1604 * Check whether we are at the end of 1605 * the string in strict mode 1606 */ 1607 if ((strict) && (*lendptr != 0)) 1608 return EINVAL; 1609 1610 /* Check for overflow */ 1611 uint16_t _res = (uint16_t) res; 1612 if (_res != res) 1613 return EOVERFLOW; 1614 1615 *result = _res; 1616 1617 return EOK; 1618 } 1619 1620 /** Convert string to uint32_t. 1621 * 1622 * @param nptr Pointer to string. 1623 * @param endptr If not NULL, pointer to the first invalid character 1624 * is stored here. 1625 * @param base Zero or number between 2 and 36 inclusive. 1626 * @param strict Do not allow any trailing characters. 1627 * @param result Result of the conversion. 1628 * 1629 * @return EOK if conversion was successful. 1630 * 1631 */ 1632 errno_t str_uint32_t(const char *nptr, const char **endptr, unsigned int base, 1633 bool strict, uint32_t *result) 1634 { 1635 assert(result != NULL); 1636 1637 bool neg; 1638 char *lendptr; 1639 uint64_t res; 1640 errno_t ret = str_uint(nptr, &lendptr, base, &neg, &res); 1641 1642 if (endptr != NULL) 1643 *endptr = (char *) lendptr; 1644 1645 if (ret != EOK) 1646 return ret; 1647 1648 /* Do not allow negative values */ 1649 if (neg) 1650 return EINVAL; 1651 1652 /* 1653 * Check whether we are at the end of 1654 * the string in strict mode 1655 */ 1656 if ((strict) && (*lendptr != 0)) 1657 return EINVAL; 1658 1659 /* Check for overflow */ 1660 uint32_t _res = (uint32_t) res; 1661 if (_res != res) 1662 return EOVERFLOW; 1663 1664 *result = _res; 1665 1666 return EOK; 1667 } 1668 1669 /** Convert string to uint64_t. 1670 * 1671 * @param nptr Pointer to string. 1672 * @param endptr If not NULL, pointer to the first invalid character 1673 * is stored here. 1674 * @param base Zero or number between 2 and 36 inclusive. 1675 * @param strict Do not allow any trailing characters. 1676 * @param result Result of the conversion. 1677 * 1678 * @return EOK if conversion was successful. 1679 * 1680 */ 1681 errno_t str_uint64_t(const char *nptr, const char **endptr, unsigned int base, 1682 bool strict, uint64_t *result) 1683 { 1684 assert(result != NULL); 1685 1686 bool neg; 1687 char *lendptr; 1688 errno_t ret = str_uint(nptr, &lendptr, base, &neg, result); 1689 1690 if (endptr != NULL) 1691 *endptr = (char *) lendptr; 1692 1693 if (ret != EOK) 1694 return ret; 1695 1696 /* Do not allow negative values */ 1697 if (neg) 1698 return EINVAL; 1699 1700 /* 1701 * Check whether we are at the end of 1702 * the string in strict mode 1703 */ 1704 if ((strict) && (*lendptr != 0)) 1705 return EINVAL; 1706 1707 return EOK; 1708 } 1709 1710 /** Convert string to int64_t. 1711 * 1712 * @param nptr Pointer to string. 1713 * @param endptr If not NULL, pointer to the first invalid character 1714 * is stored here. 1715 * @param base Zero or number between 2 and 36 inclusive. 1716 * @param strict Do not allow any trailing characters. 1717 * @param result Result of the conversion. 1718 * 1719 * @return EOK if conversion was successful. 1720 * 1721 */ 1722 int str_int64_t(const char *nptr, const char **endptr, unsigned int base, 1723 bool strict, int64_t *result) 1724 { 1725 assert(result != NULL); 1726 1727 bool neg; 1728 char *lendptr; 1729 uint64_t unsigned_result; 1730 int ret = str_uint(nptr, &lendptr, base, &neg, &unsigned_result); 1731 1732 if (endptr != NULL) 1733 *endptr = (char *) lendptr; 1734 1735 if (ret != EOK) 1736 return ret; 1737 1738 /* Do not allow negative values */ 1739 if (neg) { 1740 if (unsigned_result == UINT64_MAX) 1741 return EINVAL; 1742 1743 *result = -(int64_t) unsigned_result; 1744 } else 1745 *result = unsigned_result; 1746 1747 /* 1748 * Check whether we are at the end of 1749 * the string in strict mode 1750 */ 1751 if ((strict) && (*lendptr != 0)) 1752 return EINVAL; 1753 1754 return EOK; 1755 } 1756 1757 /** Convert string to size_t. 1758 * 1759 * @param nptr Pointer to string. 1760 * @param endptr If not NULL, pointer to the first invalid character 1761 * is stored here. 1762 * @param base Zero or number between 2 and 36 inclusive. 1763 * @param strict Do not allow any trailing characters. 1764 * @param result Result of the conversion. 1765 * 1766 * @return EOK if conversion was successful. 1767 * 1768 */ 1769 errno_t str_size_t(const char *nptr, const char **endptr, unsigned int base, 1770 bool strict, size_t *result) 1771 { 1772 assert(result != NULL); 1773 1774 bool neg; 1775 char *lendptr; 1776 uint64_t res; 1777 errno_t ret = str_uint(nptr, &lendptr, base, &neg, &res); 1778 1779 if (endptr != NULL) 1780 *endptr = (char *) lendptr; 1781 1782 if (ret != EOK) 1783 return ret; 1784 1785 /* Do not allow negative values */ 1786 if (neg) 1787 return EINVAL; 1788 1789 /* 1790 * Check whether we are at the end of 1791 * the string in strict mode 1792 */ 1793 if ((strict) && (*lendptr != 0)) 1794 return EINVAL; 1795 1796 /* Check for overflow */ 1797 size_t _res = (size_t) res; 1798 if (_res != res) 1799 return EOVERFLOW; 1800 1801 *result = _res; 1802 1803 return EOK; 1473 1804 } 1474 1805
Note:
See TracChangeset
for help on using the changeset viewer.