Changes in kernel/generic/src/lib/str.c [19f857a:e535eeb] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/lib/str.c
r19f857a re535eeb 110 110 #include <align.h> 111 111 #include <debug.h> 112 #include <macros.h> 112 113 113 114 /** Byte mask consisting of lowest @n bits (out of 8) */ … … 537 538 * null-terminated and containing only complete characters. 538 539 * 539 * @param dest 540 * @param dest Destination buffer. 540 541 * @param count Size of the destination buffer (must be > 0). 541 542 * @param src Source string. 543 * 542 544 */ 543 545 void str_cpy(char *dest, size_t size, const char *src) 544 546 { 545 wchar_t ch;546 size_t src_off;547 size_t dest_off;548 549 547 /* There must be space for a null terminator in the buffer. */ 550 548 ASSERT(size > 0); 551 549 552 src_off = 0; 553 dest_off = 0; 554 550 size_t src_off = 0; 551 size_t dest_off = 0; 552 553 wchar_t ch; 555 554 while ((ch = str_decode(src, &src_off, STR_NO_LIMIT)) != 0) { 556 555 if (chr_encode(ch, dest, &dest_off, size - 1) != EOK) 557 556 break; 558 557 } 559 558 560 559 dest[dest_off] = '\0'; 561 560 } … … 571 570 * have to be null-terminated. 572 571 * 573 * @param dest 572 * @param dest Destination buffer. 574 573 * @param count Size of the destination buffer (must be > 0). 575 574 * @param src Source string. 576 * @param n Maximum number of bytes to read from @a src. 575 * @param n Maximum number of bytes to read from @a src. 576 * 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 584 580 /* There must be space for a null terminator in the buffer. */ 585 581 ASSERT(size > 0); 586 582 587 src_off = 0; 588 dest_off = 0; 589 583 size_t src_off = 0; 584 size_t dest_off = 0; 585 586 wchar_t ch; 590 587 while ((ch = str_decode(src, &src_off, n)) != 0) { 591 588 if (chr_encode(ch, dest, &dest_off, size - 1) != EOK) 592 589 break; 593 590 } 594 591 595 592 dest[dest_off] = '\0'; 593 } 594 595 /** Duplicate string. 596 * 597 * Allocate a new string and copy characters from the source 598 * string into it. The duplicate string is allocated via sleeping 599 * malloc(), thus this function can sleep in no memory conditions. 600 * 601 * The allocation cannot fail and the return value is always 602 * a valid pointer. The duplicate string is always a well-formed 603 * null-terminated UTF-8 string, but it can differ from the source 604 * 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 source 624 * string into it. The duplicate string is allocated via sleeping 625 * malloc(), thus this function can sleep in no memory conditions. 626 * No more than @max_size + 1 bytes is allocated, but if the size 627 * 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 always 631 * a valid pointer. The duplicate string is always a well-formed 632 * null-terminated UTF-8 string, but it can differ from the source 633 * 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; 596 652 } 597 653 … … 705 761 } 706 762 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 else 848 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 is 868 * 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 character 885 * 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 of 913 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 707 946 /** @} 708 947 */
Note:
See TracChangeset
for help on using the changeset viewer.