Rev 4263 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 4263 | Rev 4327 | ||
---|---|---|---|
Line 33... | Line 33... | ||
33 | /** @file |
33 | /** @file |
34 | */ |
34 | */ |
35 | 35 | ||
36 | #include <string.h> |
36 | #include <string.h> |
37 | #include <stdlib.h> |
37 | #include <stdlib.h> |
- | 38 | #include <assert.h> |
|
38 | #include <limits.h> |
39 | #include <limits.h> |
39 | #include <ctype.h> |
40 | #include <ctype.h> |
40 | #include <malloc.h> |
41 | #include <malloc.h> |
41 | #include <errno.h> |
42 | #include <errno.h> |
42 | #include <align.h> |
43 | #include <align.h> |
- | 44 | #include <mem.h> |
|
43 | #include <string.h> |
45 | #include <string.h> |
44 | 46 | ||
45 | /** Byte mask consisting of lowest @n bits (out of 8) */ |
47 | /** Byte mask consisting of lowest @n bits (out of 8) */ |
46 | #define LO_MASK_8(n) ((uint8_t) ((1 << (n)) - 1)) |
48 | #define LO_MASK_8(n) ((uint8_t) ((1 << (n)) - 1)) |
47 | 49 | ||
Line 459... | Line 461... | ||
459 | 461 | ||
460 | return 0; |
462 | return 0; |
461 | 463 | ||
462 | } |
464 | } |
463 | 465 | ||
464 | /** Copy NULL-terminated string. |
466 | /** Copy string. |
465 | * |
467 | * |
466 | * Copy source string @a src to destination buffer @a dst. |
468 | * Copy source string @a src to destination buffer @a dest. |
467 | * No more than @a size bytes are written. NULL-terminator is always |
469 | * No more than @a size bytes are written. If the size of the output buffer |
468 | * written after the last succesfully copied character (i.e. if the |
470 | * is at least one byte, the output string will always be well-formed, i.e. |
469 | * destination buffer is has at least 1 byte, it will be always |
471 | * null-terminated and containing only complete characters. |
470 | * NULL-terminated). |
- | |
471 | * |
472 | * |
472 | * @param src Source string. |
- | |
473 | * @param dst Destination buffer. |
473 | * @param dst Destination buffer. |
474 | * @param count Size of the destination buffer. |
474 | * @param count Size of the destination buffer (must be > 0). |
475 | * |
475 | * @param src Source string. |
476 | */ |
476 | */ |
477 | void str_ncpy(char *dst, const char *src, size_t size) |
477 | void str_cpy(char *dest, size_t size, const char *src) |
478 | { |
478 | { |
479 | /* No space for the NULL-terminator in the buffer */ |
- | |
480 | if (size == 0) |
- | |
481 | return; |
- | |
482 | - | ||
483 | wchar_t ch; |
479 | wchar_t ch; |
484 | size_t str_off = 0; |
480 | size_t src_off; |
485 | size_t dst_off = 0; |
481 | size_t dest_off; |
- | 482 | ||
- | 483 | /* There must be space for a null terminator in the buffer. */ |
|
- | 484 | assert(size > 0); |
|
486 | 485 | ||
- | 486 | src_off = 0; |
|
- | 487 | dest_off = 0; |
|
- | 488 | ||
487 | while ((ch = str_decode(src, &str_off, STR_NO_LIMIT)) != 0) { |
489 | while ((ch = str_decode(src, &src_off, STR_NO_LIMIT)) != 0) { |
488 | if (chr_encode(ch, dst, &dst_off, size) != EOK) |
490 | if (chr_encode(ch, dest, &dest_off, size - 1) != EOK) |
489 | break; |
491 | break; |
490 | } |
492 | } |
- | 493 | ||
- | 494 | dest[dest_off] = '\0'; |
|
- | 495 | } |
|
- | 496 | ||
- | 497 | /** Copy size-limited substring. |
|
- | 498 | * |
|
- | 499 | * Copy prefix of string @a src of max. size @a size to destination buffer |
|
- | 500 | * @a dest. No more than @a size bytes are written. The output string will |
|
- | 501 | * always be well-formed, i.e. null-terminated and containing only complete |
|
- | 502 | * characters. |
|
- | 503 | * |
|
- | 504 | * No more than @a n bytes are read from the input string, so it does not |
|
- | 505 | * have to be null-terminated. |
|
- | 506 | * |
|
- | 507 | * @param dst Destination buffer. |
|
- | 508 | * @param count Size of the destination buffer (must be > 0). |
|
- | 509 | * @param src Source string. |
|
- | 510 | * @param n Maximum number of bytes to read from @a src. |
|
- | 511 | */ |
|
- | 512 | void str_ncpy(char *dest, size_t size, const char *src, size_t n) |
|
- | 513 | { |
|
- | 514 | wchar_t ch; |
|
- | 515 | size_t src_off; |
|
- | 516 | size_t dest_off; |
|
- | 517 | ||
- | 518 | /* There must be space for a null terminator in the buffer. */ |
|
- | 519 | assert(size > 0); |
|
491 | 520 | ||
492 | if (dst_off >= size) |
521 | src_off = 0; |
493 | dst[size - 1] = 0; |
522 | dest_off = 0; |
- | 523 | ||
- | 524 | while ((ch = str_decode(src, &src_off, n)) != 0) { |
|
- | 525 | if (chr_encode(ch, dest, &dest_off, size - 1) != EOK) |
|
- | 526 | break; |
|
494 | else |
527 | } |
- | 528 | ||
495 | dst[dst_off] = 0; |
529 | dest[dest_off] = '\0'; |
- | 530 | } |
|
- | 531 | ||
- | 532 | /** Append one string to another. |
|
- | 533 | * |
|
- | 534 | * Append source string @a src to string in destination buffer @a dest. |
|
- | 535 | * Size of the destination buffer is @a dest. If the size of the output buffer |
|
- | 536 | * is at least one byte, the output string will always be well-formed, i.e. |
|
- | 537 | * null-terminated and containing only complete characters. |
|
- | 538 | * |
|
- | 539 | * @param dst Destination buffer. |
|
- | 540 | * @param count Size of the destination buffer. |
|
- | 541 | * @param src Source string. |
|
- | 542 | */ |
|
- | 543 | void str_append(char *dest, size_t size, const char *src) |
|
- | 544 | { |
|
- | 545 | size_t dstr_size; |
|
- | 546 | ||
- | 547 | dstr_size = str_size(dest); |
|
- | 548 | str_cpy(dest + dstr_size, size - dstr_size, src); |
|
496 | } |
549 | } |
497 | 550 | ||
498 | /** Copy NULL-terminated wide string to string |
551 | /** Copy NULL-terminated wide string to string |
499 | * |
552 | * |
500 | * Copy source wide string @a src to destination buffer @a dst. |
553 | * Copy source wide string @a src to destination buffer @a dst. |
Line 533... | Line 586... | ||
533 | * |
586 | * |
534 | * @param str String to search. |
587 | * @param str String to search. |
535 | * @param ch Character to look for. |
588 | * @param ch Character to look for. |
536 | * |
589 | * |
537 | * @return Pointer to character in @a str or NULL if not found. |
590 | * @return Pointer to character in @a str or NULL if not found. |
538 | * |
- | |
539 | */ |
591 | */ |
540 | const char *str_chr(const char *str, wchar_t ch) |
592 | const char *str_chr(const char *str, wchar_t ch) |
541 | { |
593 | { |
542 | wchar_t acc; |
594 | wchar_t acc; |
543 | size_t off = 0; |
595 | size_t off = 0; |
- | 596 | size_t last = 0; |
|
544 | 597 | ||
545 | while ((acc = str_decode(str, &off, STR_NO_LIMIT)) != 0) { |
598 | while ((acc = str_decode(str, &off, STR_NO_LIMIT)) != 0) { |
546 | if (acc == ch) |
599 | if (acc == ch) |
547 | return (str + off); |
600 | return (str + last); |
- | 601 | last = off; |
|
548 | } |
602 | } |
549 | 603 | ||
550 | return NULL; |
604 | return NULL; |
551 | } |
605 | } |
552 | 606 | ||
- | 607 | /** Find last occurence of character in string. |
|
- | 608 | * |
|
- | 609 | * @param str String to search. |
|
- | 610 | * @param ch Character to look for. |
|
- | 611 | * |
|
- | 612 | * @return Pointer to character in @a str or NULL if not found. |
|
- | 613 | */ |
|
- | 614 | const char *str_rchr(const char *str, wchar_t ch) |
|
- | 615 | { |
|
- | 616 | wchar_t acc; |
|
- | 617 | size_t off = 0; |
|
- | 618 | size_t last = 0; |
|
- | 619 | char *res = NULL; |
|
- | 620 | ||
- | 621 | while ((acc = str_decode(str, &off, STR_NO_LIMIT)) != 0) { |
|
- | 622 | if (acc == ch) |
|
- | 623 | res = (str + last); |
|
- | 624 | last = off; |
|
- | 625 | } |
|
- | 626 | ||
- | 627 | return res; |
|
- | 628 | } |
|
- | 629 | ||
553 | /** Insert a wide character into a wide string. |
630 | /** Insert a wide character into a wide string. |
554 | * |
631 | * |
555 | * Insert a wide character into a wide string at position |
632 | * Insert a wide character into a wide string at position |
556 | * @a pos. The characters after the position are shifted. |
633 | * @a pos. The characters after the position are shifted. |
557 | * |
634 | * |
Line 604... | Line 681... | ||
604 | str[i - 1] = str[i]; |
681 | str[i - 1] = str[i]; |
605 | 682 | ||
606 | return true; |
683 | return true; |
607 | } |
684 | } |
608 | 685 | ||
609 | /** Count the number of characters in the string, not including terminating 0. |
- | |
610 | * |
- | |
611 | * @param str String. |
- | |
612 | * @return Number of characters in string. |
- | |
613 | */ |
- | |
614 | size_t strlen(const char *str) |
- | |
615 | { |
- | |
616 | size_t counter = 0; |
- | |
617 | - | ||
618 | while (str[counter] != 0) |
- | |
619 | counter++; |
- | |
620 | - | ||
621 | return counter; |
- | |
622 | } |
- | |
623 | - | ||
624 | int strcmp(const char *a, const char *b) |
- | |
625 | { |
- | |
626 | int c = 0; |
- | |
627 | - | ||
628 | while (a[c] && b[c] && (!(a[c] - b[c]))) |
- | |
629 | c++; |
- | |
630 | - | ||
631 | return (a[c] - b[c]); |
- | |
632 | } |
- | |
633 | - | ||
634 | int strncmp(const char *a, const char *b, size_t n) |
- | |
635 | { |
- | |
636 | size_t c = 0; |
- | |
637 | - | ||
638 | while (c < n && a[c] && b[c] && (!(a[c] - b[c]))) |
- | |
639 | c++; |
- | |
640 | - | ||
641 | return ( c < n ? a[c] - b[c] : 0); |
- | |
642 | - | ||
643 | } |
- | |
644 | - | ||
645 | int stricmp(const char *a, const char *b) |
686 | int stricmp(const char *a, const char *b) |
646 | { |
687 | { |
647 | int c = 0; |
688 | int c = 0; |
648 | 689 | ||
649 | while (a[c] && b[c] && (!(tolower(a[c]) - tolower(b[c])))) |
690 | while (a[c] && b[c] && (!(tolower(a[c]) - tolower(b[c])))) |
650 | c++; |
691 | c++; |
651 | 692 | ||
652 | return (tolower(a[c]) - tolower(b[c])); |
693 | return (tolower(a[c]) - tolower(b[c])); |
653 | } |
694 | } |
654 | 695 | ||
655 | /** Return pointer to the first occurence of character c in string. |
- | |
656 | * |
- | |
657 | * @param str Scanned string. |
- | |
658 | * @param c Searched character (taken as one byte). |
- | |
659 | * @return Pointer to the matched character or NULL if it is not |
- | |
660 | * found in given string. |
- | |
661 | */ |
- | |
662 | char *strchr(const char *str, int c) |
- | |
663 | { |
- | |
664 | while (*str != '\0') { |
- | |
665 | if (*str == (char) c) |
- | |
666 | return (char *) str; |
- | |
667 | str++; |
- | |
668 | } |
- | |
669 | - | ||
670 | return NULL; |
- | |
671 | } |
- | |
672 | - | ||
673 | /** Return pointer to the last occurence of character c in string. |
- | |
674 | * |
- | |
675 | * @param str Scanned string. |
- | |
676 | * @param c Searched character (taken as one byte). |
- | |
677 | * @return Pointer to the matched character or NULL if it is not |
- | |
678 | * found in given string. |
- | |
679 | */ |
- | |
680 | char *strrchr(const char *str, int c) |
- | |
681 | { |
- | |
682 | char *retval = NULL; |
- | |
683 | - | ||
684 | while (*str != '\0') { |
- | |
685 | if (*str == (char) c) |
- | |
686 | retval = (char *) str; |
- | |
687 | str++; |
- | |
688 | } |
- | |
689 | - | ||
690 | return (char *) retval; |
- | |
691 | } |
- | |
692 | - | ||
693 | /** Convert string to a number. |
696 | /** Convert string to a number. |
694 | * Core of strtol and strtoul functions. |
697 | * Core of strtol and strtoul functions. |
695 | * |
698 | * |
696 | * @param nptr Pointer to string. |
699 | * @param nptr Pointer to string. |
697 | * @param endptr If not NULL, function stores here pointer to the first |
700 | * @param endptr If not NULL, function stores here pointer to the first |
Line 837... | Line 840... | ||
837 | number = _strtoul(nptr, endptr, base, &sgn); |
840 | number = _strtoul(nptr, endptr, base, &sgn); |
838 | 841 | ||
839 | return (sgn ? -number : number); |
842 | return (sgn ? -number : number); |
840 | } |
843 | } |
841 | 844 | ||
842 | char *strcpy(char *dest, const char *src) |
- | |
843 | { |
- | |
844 | char *orig = dest; |
- | |
845 | - | ||
846 | while ((*(dest++) = *(src++))) |
- | |
847 | ; |
- | |
848 | return orig; |
- | |
849 | } |
- | |
850 | - | ||
851 | char *strncpy(char *dest, const char *src, size_t n) |
- | |
852 | { |
- | |
853 | char *orig = dest; |
- | |
854 | - | ||
855 | while ((*(dest++) = *(src++)) && --n) |
- | |
856 | ; |
- | |
857 | return orig; |
- | |
858 | } |
- | |
859 | - | ||
860 | char *strcat(char *dest, const char *src) |
- | |
861 | { |
- | |
862 | char *orig = dest; |
- | |
863 | while (*dest++) |
- | |
864 | ; |
- | |
865 | --dest; |
- | |
866 | while ((*dest++ = *src++)) |
- | |
867 | ; |
- | |
868 | return orig; |
- | |
869 | } |
- | |
870 | - | ||
871 | char * strdup(const char *s1) |
845 | char *str_dup(const char *src) |
872 | { |
846 | { |
873 | size_t len = strlen(s1) + 1; |
847 | size_t size = str_size(src); |
874 | void *ret = malloc(len); |
848 | void *dest = malloc(size + 1); |
875 | 849 | ||
876 | if (ret == NULL) |
850 | if (dest == NULL) |
877 | return (char *) NULL; |
851 | return (char *) NULL; |
878 | 852 | ||
879 | return (char *) memcpy(ret, s1, len); |
853 | return (char *) memcpy(dest, src, size + 1); |
880 | } |
854 | } |
881 | 855 | ||
882 | char *strtok(char *s, const char *delim) |
856 | char *strtok(char *s, const char *delim) |
883 | { |
857 | { |
884 | static char *next; |
858 | static char *next; |
Line 892... | Line 866... | ||
892 | 866 | ||
893 | if (s == NULL) |
867 | if (s == NULL) |
894 | s = *next; |
868 | s = *next; |
895 | 869 | ||
896 | /* Skip over leading delimiters. */ |
870 | /* Skip over leading delimiters. */ |
897 | while (*s && (strchr(delim, *s) != NULL)) ++s; |
871 | while (*s && (str_chr(delim, *s) != NULL)) ++s; |
898 | start = s; |
872 | start = s; |
899 | 873 | ||
900 | /* Skip over token characters. */ |
874 | /* Skip over token characters. */ |
901 | while (*s && (strchr(delim, *s) == NULL)) ++s; |
875 | while (*s && (str_chr(delim, *s) == NULL)) ++s; |
902 | end = s; |
876 | end = s; |
903 | *next = (*s ? s + 1 : s); |
877 | *next = (*s ? s + 1 : s); |
904 | 878 | ||
905 | if (start == end) { |
879 | if (start == end) { |
906 | return NULL; /* No more tokens. */ |
880 | return NULL; /* No more tokens. */ |