Changes in uspace/lib/c/generic/str.c [09ab0a9a:1c9bf292] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/str.c
r09ab0a9a r1c9bf292 1 1 /* 2 * Copyright (c) 2001-2004 Jakub Jermar 2 3 * Copyright (c) 2005 Martin Decky 3 4 * Copyright (c) 2008 Jiri Svoboda … … 33 34 * @{ 34 35 */ 35 /** @file 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 * 36 106 */ 37 107 38 108 #include <str.h> 109 110 #include <assert.h> 111 #include <ctype.h> 112 #include <errno.h> 113 #include <stdbool.h> 39 114 #include <stddef.h> 40 115 #include <stdint.h> 41 116 #include <stdlib.h> 42 #include <assert.h> 43 #include <ctype.h> 44 #include <errno.h> 117 45 118 #include <align.h> 46 119 #include <mem.h> 47 #include <limits.h>48 120 49 121 /** Check the condition if wchar_t is signed */ … … 747 819 /* There must be space for a null terminator in the buffer. */ 748 820 assert(size > 0); 821 assert(src != NULL); 749 822 750 823 size_t src_off = 0; … … 1311 1384 { 1312 1385 size_t size = str_size(src) + 1; 1313 char *dest = (char *)malloc(size);1314 if ( dest == NULL)1315 return (char *)NULL;1386 char *dest = malloc(size); 1387 if (!dest) 1388 return NULL; 1316 1389 1317 1390 str_cpy(dest, size, src); … … 1345 1418 size = n; 1346 1419 1347 char *dest = (char *)malloc(size + 1);1348 if ( dest == NULL)1349 return (char *)NULL;1420 char *dest = malloc(size + 1); 1421 if (!dest) 1422 return NULL; 1350 1423 1351 1424 str_ncpy(dest, size + 1, src, size); … … 1398 1471 *end = '\0'; 1399 1472 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 else1489 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 is1509 * 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 character1526 * 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 of1556 * the string in strict mode1557 */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 character1575 * 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 of1605 * the string in strict mode1606 */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 character1624 * 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 of1654 * the string in strict mode1655 */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 character1673 * 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 of1702 * the string in strict mode1703 */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 character1714 * 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 } else1745 *result = unsigned_result;1746 1747 /*1748 * Check whether we are at the end of1749 * the string in strict mode1750 */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 character1761 * 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 of1791 * the string in strict mode1792 */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;1804 1473 } 1805 1474
Note:
See TracChangeset
for help on using the changeset viewer.