/* strdup but trim whitespaces at head and tail */ char * strdup_trim(const char *str) { size_t len; if (str == NULL) return NULL; while (IsSpace(str[0])) { str++; } len = strlen(str); while (len > 0 && IsSpace(str[len - 1])) { len--; } return strdup_with_len(str, len); }
static int MatchText(const char *t, size_t tlen, const char *p, size_t plen, List **params) { while (tlen > 0 && plen > 0) { if (plen < 2 || *p != '%') { /* non-wildcard pattern char fails to match text char */ if (*p != *t) return LIKE_FALSE; } else if (p[1] == '%') { /* %% is % */ NextByte(p, plen); if (*p != *t) return LIKE_FALSE; } else { const char *begin = p; const char *w = t; char firstpat; /* Skip until the type specifer */ p = strpbrk(begin + 1, "diouxXeEfFgGaAcspm"); if (p == NULL) return LIKE_FALSE; /* bad format */ p++; plen -= p - begin; if (plen <= 0) { if (params) *params = lcons(strdup_with_len(t, tlen), *params); return LIKE_TRUE; /* matches everything. */ } /* * Otherwise, scan for a text position at which we can match the * rest of the pattern. */ firstpat = *p; while (tlen > 0) { /* * Optimization to prevent most recursion: don't recurse * unless first pattern byte matches first text byte. */ if (*t == firstpat) { int matched = MatchText(t, tlen, p, plen, params); if (matched == LIKE_TRUE && params) *params = lcons(strdup_with_len(w, t - w), *params); if (matched != LIKE_FALSE) return matched; /* TRUE or ABORT */ } NextChar(t, tlen); } /* * End of text with no match, so no point in trying later places * to start matching this pattern. */ return LIKE_ABORT; } NextByte(t, tlen); NextByte(p, plen); } if (tlen > 0) return LIKE_FALSE; /* end of pattern, but not of text */ /* End of text string. Do we have matching pattern remaining? */ while (plen > 0 && *p == '%') { const char *begin = p; p = strpbrk(begin + 1, "diouxXeEfFgGaAcspm"); if (p == NULL) return LIKE_FALSE; /* bad format */ p++; plen -= p - begin; } if (plen <= 0) return LIKE_TRUE; /* * End of text with no match, so no point in trying later places to start * matching this pattern. */ return LIKE_ABORT; }