/* * Extract the next non-wildcard part of a search string, ie, a word bounded * by '_' or '%' meta-characters, non-word characters or string end. * * str: source string, of length lenstr bytes (need not be null-terminated) * buf: where to return the substring (must be long enough) * *bytelen: receives byte length of the found substring * *charlen: receives character length of the found substring * * Returns pointer to end+1 of the found substring in the source string. * Returns NULL if no word found (in which case buf, bytelen, charlen not set) * * If the found word is bounded by non-word characters or string boundaries * then this function will include corresponding padding spaces into buf. */ static const char * get_wildcard_part(const char *str, int lenstr, char *buf, int *bytelen, int *charlen) { const char *beginword = str; const char *endword; char *s = buf; bool in_leading_wildcard_meta = false; bool in_trailing_wildcard_meta = false; bool in_escape = false; int clen; /* * Find the first word character, remembering whether preceding character * was wildcard meta-character. Note that the in_escape state persists * from this loop to the next one, since we may exit at a word character * that is in_escape. */ while (beginword - str < lenstr) { if (in_escape) { if (iswordchr(beginword)) break; in_escape = false; in_leading_wildcard_meta = false; } else { if (ISESCAPECHAR(beginword)) in_escape = true; else if (ISWILDCARDCHAR(beginword)) in_leading_wildcard_meta = true; else if (iswordchr(beginword)) break; else in_leading_wildcard_meta = false; } beginword += pg_mblen(beginword); } /* * Handle string end. */ if (beginword - str >= lenstr) return NULL; /* * Add left padding spaces if preceding character wasn't wildcard * meta-character. */ *charlen = 0; if (!in_leading_wildcard_meta) { if (LPADDING > 0) { *s++ = ' '; (*charlen)++; if (LPADDING > 1) { *s++ = ' '; (*charlen)++; } } } /* * Copy data into buf until wildcard meta-character, non-word character or * string boundary. Strip escapes during copy. */ endword = beginword; while (endword - str < lenstr) { clen = pg_mblen(endword); if (in_escape) { if (iswordchr(endword)) { memcpy(s, endword, clen); (*charlen)++; s += clen; } else { /* * Back up endword to the escape character when stopping at * an escaped char, so that subsequent get_wildcard_part will * restart from the escape character. We assume here that * escape chars are single-byte. */ endword--; break; } in_escape = false; } else { if (ISESCAPECHAR(endword)) in_escape = true; else if (ISWILDCARDCHAR(endword)) { in_trailing_wildcard_meta = true; break; } else if (iswordchr(endword)) { memcpy(s, endword, clen); (*charlen)++; s += clen; } else break; } endword += clen; } /* * Add right padding spaces if next character isn't wildcard * meta-character. */ if (!in_trailing_wildcard_meta) { if (RPADDING > 0) { *s++ = ' '; (*charlen)++; if (RPADDING > 1) { *s++ = ' '; (*charlen)++; } } } *bytelen = s - buf; return endword; }
/* * Extract the next non-wildcard part of a search string, ie, a word bounded * by '_' or '%' meta-characters, non-word characters or string end. * * str: source string, of length lenstr bytes (need not be null-terminated) * buf: where to return the substring (must be long enough) * *bytelen: receives byte length of the found substring * *charlen: receives character length of the found substring * * Returns pointer to end+1 of the found substring in the source string. * Returns NULL if no word found (in which case buf, bytelen, charlen not set) * * If the found word is bounded by non-word characters or string boundaries * then this function will include corresponding padding spaces into buf. */ static const char * get_wildcard_part(const char *str, int lenstr, char *buf, int *bytelen, int *charlen) { const char *beginword = str; const char *endword; char *s = buf; bool in_wildcard_meta = false; bool in_escape = false; int clen; /* * Find the first word character remembering whether last character was * wildcard meta-character. */ while (beginword - str < lenstr) { if (in_escape) { in_escape = false; in_wildcard_meta = false; if (iswordchr(beginword)) break; } else { if (ISESCAPECHAR(beginword)) in_escape = true; else if (ISWILDCARDCHAR(beginword)) in_wildcard_meta = true; else if (iswordchr(beginword)) break; else in_wildcard_meta = false; } beginword += pg_mblen(beginword); } /* * Handle string end. */ if (beginword - str >= lenstr) return NULL; /* * Add left padding spaces if last character wasn't wildcard * meta-character. */ *charlen = 0; if (!in_wildcard_meta) { if (LPADDING > 0) { *s++ = ' '; (*charlen)++; if (LPADDING > 1) { *s++ = ' '; (*charlen)++; } } } /* * Copy data into buf until wildcard meta-character, non-word character or * string boundary. Strip escapes during copy. */ endword = beginword; in_wildcard_meta = false; in_escape = false; while (endword - str < lenstr) { clen = pg_mblen(endword); if (in_escape) { in_escape = false; in_wildcard_meta = false; if (iswordchr(endword)) { memcpy(s, endword, clen); (*charlen)++; s += clen; } else break; } else { if (ISESCAPECHAR(endword)) in_escape = true; else if (ISWILDCARDCHAR(endword)) { in_wildcard_meta = true; break; } else if (iswordchr(endword)) { memcpy(s, endword, clen); (*charlen)++; s += clen; } else { in_wildcard_meta = false; break; } } endword += clen; } /* * Add right padding spaces if last character wasn't wildcard * meta-character. */ if (!in_wildcard_meta) { if (RPADDING > 0) { *s++ = ' '; (*charlen)++; if (RPADDING > 1) { *s++ = ' '; (*charlen)++; } } } *bytelen = s - buf; return endword; }