AmendHub

Download:

jcs

/

detritus

/

amendments

/

67

util: Add strcaseidx

When trying to case-insensitively match a string to a list of char
pointers, having to call into strcasecmp for every list entry and
start the indexing into the string over again every time is quite
expensive.
 
strcaseidx takes a string and a pointer to an array of char pointers
and walks the list and indexes the string only once, advancing
through the list as each next character matches or not. This
requires the list to be sorted.

jcs made amendment 67 about 1 year ago
--- util.c Fri Dec 27 22:17:47 2024 +++ util.c Fri Dec 27 22:20:28 2024 @@ -693,6 +693,41 @@ advance_us: return NULL; } +long +strcaseidx(const char *s, const char **list) +{ + const unsigned char *cm = strcasecmp_charmap; + const unsigned char *us = (const unsigned char *)s; + long sn, ln, n; + + /* + * Entries in list must be sorted. + * + * For first char in s (sn=0), walk list as ln until we get a partial + * match. Once matching fails, advance ln and make sure that next + * list entry matches all characters up to sn. If not, there are no + * possible matches in this sorted list. If everything does match up + * to sn, keep advancing sn until we reach its terminator. + */ + for (sn = 0, ln = 0; ; sn++) { + while (cm[list[ln][sn]] != cm[us[sn]]) { + if (list[++ln] == NULL) + return -1; + + /* make sure each char in next list entry matches up to now */ + for (n = 0; n < sn; n++) { + if (cm[us[n]] != cm[list[ln][n]]) + return -1; + } + } + + if (us[sn] == '\0') + return ln; + } + + return -1; +} + /* * BSD warn(3) functions */ --- util.h Thu Dec 12 12:13:00 2024 +++ util.h Fri Dec 27 16:04:53 2024 @@ -168,6 +168,7 @@ char * OSTypeToString(OSType type); char * strcasestr(const char *s, const char *find); short strcasecmp(const char *s1, const char *s2); short strncasecmp(const char *s1, const char *s2, size_t n); +long strcaseidx(const char *s, const char **list); unsigned long xorshift32(void);