Changes in kernel/generic/src/lib/str.c [e535eeb:19f857a] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/lib/str.c
re535eeb r19f857a 110 110 #include <align.h> 111 111 #include <debug.h> 112 #include <macros.h>113 112 114 113 /** Byte mask consisting of lowest @n bits (out of 8) */ … … 538 537 * null-terminated and containing only complete characters. 539 538 * 540 * @param dest Destination buffer.539 * @param dest Destination buffer. 541 540 * @param count Size of the destination buffer (must be > 0). 542 541 * @param src Source string. 543 *544 542 */ 545 543 void str_cpy(char *dest, size_t size, const char *src) 546 544 { 545 wchar_t ch; 546 size_t src_off; 547 size_t dest_off; 548 547 549 /* There must be space for a null terminator in the buffer. */ 548 550 ASSERT(size > 0); 549 551 550 size_t src_off = 0; 551 size_t dest_off = 0; 552 553 wchar_t ch; 552 src_off = 0; 553 dest_off = 0; 554 554 555 while ((ch = str_decode(src, &src_off, STR_NO_LIMIT)) != 0) { 555 556 if (chr_encode(ch, dest, &dest_off, size - 1) != EOK) 556 557 break; 557 558 } 558 559 559 560 dest[dest_off] = '\0'; 560 561 } … … 570 571 * have to be null-terminated. 571 572 * 572 * @param dest Destination buffer.573 * @param dest Destination buffer. 573 574 * @param count Size of the destination buffer (must be > 0). 574 575 * @param src Source string. 575 * @param n Maximum number of bytes to read from @a src. 576 * 576 * @param n Maximum number of bytes to read from @a src. 577 577 */ 578 578 void str_ncpy(char *dest, size_t size, const char *src, size_t n) 579 579 { 580 wchar_t ch; 581 size_t src_off; 582 size_t dest_off; 583 580 584 /* There must be space for a null terminator in the buffer. */ 581 585 ASSERT(size > 0); 582 586 583 size_t src_off = 0; 584 size_t dest_off = 0; 585 586 wchar_t ch; 587 src_off = 0; 588 dest_off = 0; 589 587 590 while ((ch = str_decode(src, &src_off, n)) != 0) { 588 591 if (chr_encode(ch, dest, &dest_off, size - 1) != EOK) 589 592 break; 590 593 } 591 594 592 595 dest[dest_off] = '\0'; 593 }594 595 /** Duplicate string.596 *597 * Allocate a new string and copy characters from the source598 * string into it. The duplicate string is allocated via sleeping599 * malloc(), thus this function can sleep in no memory conditions.600 *601 * The allocation cannot fail and the return value is always602 * a valid pointer. The duplicate string is always a well-formed603 * null-terminated UTF-8 string, but it can differ from the source604 * string on the byte level.605 *606 * @param src Source string.607 *608 * @return Duplicate string.609 *610 */611 char *str_dup(const char *src)612 {613 size_t size = str_size(src) + 1;614 char *dest = malloc(size, 0);615 ASSERT(dest);616 617 str_cpy(dest, size, src);618 return dest;619 }620 621 /** Duplicate string with size limit.622 *623 * Allocate a new string and copy up to @max_size bytes from the source624 * string into it. The duplicate string is allocated via sleeping625 * malloc(), thus this function can sleep in no memory conditions.626 * No more than @max_size + 1 bytes is allocated, but if the size627 * occupied by the source string is smaller than @max_size + 1,628 * less is allocated.629 *630 * The allocation cannot fail and the return value is always631 * a valid pointer. The duplicate string is always a well-formed632 * null-terminated UTF-8 string, but it can differ from the source633 * string on the byte level.634 *635 * @param src Source string.636 * @param n Maximum number of bytes to duplicate.637 *638 * @return Duplicate string.639 *640 */641 char *str_ndup(const char *src, size_t n)642 {643 size_t size = str_size(src);644 if (size > n)645 size = n;646 647 char *dest = malloc(size + 1, 0);648 ASSERT(dest);649 650 str_ncpy(dest, size + 1, src, size);651 return dest;652 596 } 653 597 … … 761 705 } 762 706 763 /** Convert string to uint64_t (internal variant).764 *765 * @param nptr Pointer to string.766 * @param endptr Pointer to the first invalid character is stored here.767 * @param base Zero or number between 2 and 36 inclusive.768 * @param neg Indication of unary minus is stored here.769 * @apram result Result of the conversion.770 *771 * @return EOK if conversion was successful.772 *773 */774 static int str_uint(const char *nptr, char **endptr, unsigned int base,775 bool *neg, uint64_t *result)776 {777 ASSERT(endptr != NULL);778 ASSERT(neg != NULL);779 ASSERT(result != NULL);780 781 *neg = false;782 const char *str = nptr;783 784 /* Ignore leading whitespace */785 while (isspace(*str))786 str++;787 788 if (*str == '-') {789 *neg = true;790 str++;791 } else if (*str == '+')792 str++;793 794 if (base == 0) {795 /* Decode base if not specified */796 base = 10;797 798 if (*str == '0') {799 base = 8;800 str++;801 802 switch (*str) {803 case 'b':804 case 'B':805 base = 2;806 str++;807 break;808 case 'o':809 case 'O':810 base = 8;811 str++;812 break;813 case 'd':814 case 'D':815 case 't':816 case 'T':817 base = 10;818 str++;819 break;820 case 'x':821 case 'X':822 base = 16;823 str++;824 break;825 }826 }827 } else {828 /* Check base range */829 if ((base < 2) || (base > 36)) {830 *endptr = (char *) str;831 return EINVAL;832 }833 }834 835 *result = 0;836 const char *startstr = str;837 838 while (*str != 0) {839 unsigned int digit;840 841 if ((*str >= 'a') && (*str <= 'z'))842 digit = *str - 'a' + 10;843 else if ((*str >= 'A') && (*str <= 'Z'))844 digit = *str - 'A' + 10;845 else if ((*str >= '0') && (*str <= '9'))846 digit = *str - '0';847 else848 break;849 850 if (digit >= base)851 break;852 853 uint64_t prev = *result;854 *result = (*result) * base + digit;855 856 if (*result < prev) {857 /* Overflow */858 *endptr = (char *) str;859 return EOVERFLOW;860 }861 862 str++;863 }864 865 if (str == startstr) {866 /*867 * No digits were decoded => first invalid character is868 * the first character of the string.869 */870 str = nptr;871 }872 873 *endptr = (char *) str;874 875 if (str == nptr)876 return EINVAL;877 878 return EOK;879 }880 881 /** Convert string to uint64_t.882 *883 * @param nptr Pointer to string.884 * @param endptr If not NULL, pointer to the first invalid character885 * is stored here.886 * @param base Zero or number between 2 and 36 inclusive.887 * @param strict Do not allow any trailing characters.888 * @apram result Result of the conversion.889 *890 * @return EOK if conversion was successful.891 *892 */893 int str_uint64(const char *nptr, char **endptr, unsigned int base,894 bool strict, uint64_t *result)895 {896 ASSERT(result != NULL);897 898 bool neg;899 char *lendptr;900 int ret = str_uint(nptr, &lendptr, base, &neg, result);901 902 if (endptr != NULL)903 *endptr = (char *) lendptr;904 905 if (ret != EOK)906 return ret;907 908 /* Do not allow negative values */909 if (neg)910 return EINVAL;911 912 /* Check whether we are at the end of913 the string in strict mode */914 if ((strict) && (*lendptr != 0))915 return EINVAL;916 917 return EOK;918 }919 920 void order_suffix(const uint64_t val, uint64_t *rv, char *suffix)921 {922 if (val > 10000000000000000000ULL) {923 *rv = val / 1000000000000000000ULL;924 *suffix = 'Z';925 } else if (val > 1000000000000000000ULL) {926 *rv = val / 1000000000000000ULL;927 *suffix = 'E';928 } else if (val > 1000000000000000ULL) {929 *rv = val / 1000000000000ULL;930 *suffix = 'T';931 } else if (val > 1000000000000ULL) {932 *rv = val / 1000000000ULL;933 *suffix = 'G';934 } else if (val > 1000000000ULL) {935 *rv = val / 1000000ULL;936 *suffix = 'M';937 } else if (val > 1000000ULL) {938 *rv = val / 1000ULL;939 *suffix = 'k';940 } else {941 *rv = val;942 *suffix = ' ';943 }944 }945 946 707 /** @} 947 708 */
Note:
See TracChangeset
for help on using the changeset viewer.