#include #include #include "text-regex.h" struct Regex { regex_t regex; }; Regex *text_regex_new(void) { Regex *r = calloc(1, sizeof(Regex)); if (!r) return NULL; regcomp(&r->regex, "\0\0", 0); /* this should not match anything */ return r; } int text_regex_compile(Regex *regex, const char *string, int cflags) { int r = regcomp(®ex->regex, string, cflags); if (r) regcomp(®ex->regex, "\0\0", 0); return r; } size_t text_regex_nsub(Regex *r) { if (!r) return 0; return r->regex.re_nsub; } void text_regex_free(Regex *r) { if (!r) return; regfree(&r->regex); free(r); } int text_regex_match(Regex *r, const char *data, int eflags) { return regexec(&r->regex, data, 0, NULL, eflags); } int text_search_range_forward(Text *txt, size_t pos, size_t len, Regex *r, size_t nmatch, RegexMatch pmatch[], int eflags) { char *buf = text_bytes_alloc0(txt, pos, len); if (!buf) return REG_NOMATCH; char *cur = buf, *end = buf + len; int ret = REG_NOMATCH; regmatch_t match[nmatch]; for (size_t junk = len; len > 0; len -= junk, pos += junk) { ret = regexec(&r->regex, cur, nmatch, match, eflags); if (!ret) { for (size_t i = 0; i < nmatch; i++) { pmatch[i].start = match[i].rm_so == -1 ? EPOS : pos + match[i].rm_so; pmatch[i].end = match[i].rm_eo == -1 ? EPOS : pos + match[i].rm_eo; } break; } char *next = memchr(cur, 0, len); if (!next) break; while (!*next && next != end) next++; junk = next - cur; cur = next; } free(buf); return ret; } int text_search_range_backward(Text *txt, size_t pos, size_t len, Regex *r, size_t nmatch, RegexMatch pmatch[], int eflags) { char *buf = text_bytes_alloc0(txt, pos, len); if (!buf) return REG_NOMATCH; char *cur = buf, *end = buf + len; int ret = REG_NOMATCH; regmatch_t match[nmatch]; for (size_t junk = len; len > 0; len -= junk, pos += junk) { char *next; if (!regexec(&r->regex, cur, nmatch, match, eflags)) { ret = 0; for (size_t i = 0; i < nmatch; i++) { pmatch[i].start = match[i].rm_so == -1 ? EPOS : pos + match[i].rm_so; pmatch[i].end = match[i].rm_eo == -1 ? EPOS : pos + match[i].rm_eo; } if (match[0].rm_so == 0 && match[0].rm_eo == 0) { /* empty match at the beginning of cur, advance to next line */ next = strchr(cur, '\n'); if (!next) break; next++; } else { next = cur + match[0].rm_eo; } } else { next = memchr(cur, 0, len); if (!next) break; while (!*next && next != end) next++; } junk = next - cur; cur = next; } free(buf); return ret; }