case-insensitive substring search */
| 737 | #ifndef STRSTRI |
| 738 | /* case-insensitive substring search */ |
| 739 | char * |
| 740 | strstri(const char *str, const char *sub) |
| 741 | { |
| 742 | const char *s1, *s2; |
| 743 | int i, k; |
| 744 | #define TABSIZ 0x20 /* 0x40 would be case-sensitive */ |
| 745 | char tstr[TABSIZ], tsub[TABSIZ]; /* nibble count tables */ |
| 746 | #if 0 |
| 747 | assert( (TABSIZ & ~(TABSIZ-1)) == TABSIZ ); /* must be exact power of 2 */ |
| 748 | assert( &lowc != 0 ); /* can't be unsafe macro */ |
| 749 | #endif |
| 750 | |
| 751 | /* special case: empty substring */ |
| 752 | if (!*sub) |
| 753 | return (char *) str; |
| 754 | |
| 755 | /* do some useful work while determining relative lengths */ |
| 756 | for (i = 0; i < TABSIZ; i++) |
| 757 | tstr[i] = tsub[i] = 0; /* init */ |
| 758 | for (k = 0, s1 = str; *s1; k++) |
| 759 | tstr[*s1++ & (TABSIZ - 1)]++; |
| 760 | for (s2 = sub; *s2; --k) |
| 761 | tsub[*s2++ & (TABSIZ - 1)]++; |
| 762 | |
| 763 | /* evaluate the info we've collected */ |
| 764 | if (k < 0) |
| 765 | return (char *) 0; /* sub longer than str, so can't match */ |
| 766 | for (i = 0; i < TABSIZ; i++) /* does sub have more 'x's than str? */ |
| 767 | if (tsub[i] > tstr[i]) |
| 768 | return (char *) 0; /* match not possible */ |
| 769 | |
| 770 | /* now actually compare the substring repeatedly to parts of the string */ |
| 771 | for (i = 0; i <= k; i++) { |
| 772 | s1 = &str[i]; |
| 773 | s2 = sub; |
| 774 | while (lowc(*s1++) == lowc(*s2++)) |
| 775 | if (!*s2) |
| 776 | return (char *) &str[i]; /* full match */ |
| 777 | } |
| 778 | return (char *) 0; /* not found */ |
| 779 | } |
| 780 | #endif /* STRSTRI */ |
| 781 | |
| 782 | /* compare two strings for equality, ignoring the presence of specified |
no test coverage detected