lexer: sync with upstream scintillua rev bdb74a2f31df
[vis.git] / text-regex.c
blobcff8587616ed18ea74f9d356815d8288b39df3e2
1 #include <stdlib.h>
2 #include <regex.h>
4 #include "text-regex.h"
6 struct Regex {
7 const char *string;
8 regex_t regex;
9 };
11 Regex *text_regex_new(void) {
12 Regex *r = calloc(1, sizeof(Regex));
13 if (!r)
14 return NULL;
15 regcomp(&r->regex, "\0\0", 0); /* this should not match anything */
16 return r;
19 int text_regex_compile(Regex *regex, const char *string, int cflags) {
20 regex->string = string;
21 int r = regcomp(&regex->regex, string, cflags);
22 if (r)
23 regcomp(&regex->regex, "\0\0", 0);
24 return r;
27 void text_regex_free(Regex *r) {
28 if (!r)
29 return;
30 regfree(&r->regex);
31 free(r);
34 int text_search_range_forward(Text *txt, size_t pos, size_t len, Regex *r, size_t nmatch, RegexMatch pmatch[], int eflags) {
35 char *buf = malloc(len + 1);
36 if (!buf)
37 return REG_NOMATCH;
38 len = text_bytes_get(txt, pos, len, buf);
39 buf[len] = '\0';
40 regmatch_t match[nmatch];
41 int ret = regexec(&r->regex, buf, nmatch, match, eflags);
42 if (!ret) {
43 for (size_t i = 0; i < nmatch; i++) {
44 pmatch[i].start = match[i].rm_so == -1 ? EPOS : pos + match[i].rm_so;
45 pmatch[i].end = match[i].rm_eo == -1 ? EPOS : pos + match[i].rm_eo;
48 free(buf);
49 return ret;
52 int text_search_range_backward(Text *txt, size_t pos, size_t len, Regex *r, size_t nmatch, RegexMatch pmatch[], int eflags) {
53 char *buf = malloc(len + 1);
54 if (!buf)
55 return REG_NOMATCH;
56 len = text_bytes_get(txt, pos, len, buf);
57 buf[len] = '\0';
58 regmatch_t match[nmatch];
59 char *cur = buf;
60 int ret = REG_NOMATCH;
61 while (!regexec(&r->regex, cur, nmatch, match, eflags)) {
62 ret = 0;
63 for (size_t i = 0; i < nmatch; i++) {
64 pmatch[i].start = match[i].rm_so == -1 ? EPOS : pos + (size_t)(cur - buf) + match[i].rm_so;
65 pmatch[i].end = match[i].rm_eo == -1 ? EPOS : pos + (size_t)(cur - buf) + match[i].rm_eo;
67 cur += match[0].rm_eo;
69 free(buf);
70 return ret;