vis: use marks instead of registers to store selections
[vis.git] / text-regex.c
blobb0549b63d99172eb29d7ce930dd9967e88aa15a3
1 #include <stdlib.h>
2 #include <string.h>
4 #include "text-regex.h"
6 struct Regex {
7 regex_t regex;
8 };
10 Regex *text_regex_new(void) {
11 Regex *r = calloc(1, sizeof(Regex));
12 if (!r)
13 return NULL;
14 regcomp(&r->regex, "\0\0", 0); /* this should not match anything */
15 return r;
18 int text_regex_compile(Regex *regex, const char *string, int cflags) {
19 int r = regcomp(&regex->regex, string, cflags);
20 if (r)
21 regcomp(&regex->regex, "\0\0", 0);
22 return r;
25 size_t text_regex_nsub(Regex *r) {
26 if (!r)
27 return 0;
28 return r->regex.re_nsub;
31 void text_regex_free(Regex *r) {
32 if (!r)
33 return;
34 regfree(&r->regex);
35 free(r);
38 int text_regex_match(Regex *r, const char *data, int eflags) {
39 return regexec(&r->regex, data, 0, NULL, eflags);
42 int text_search_range_forward(Text *txt, size_t pos, size_t len, Regex *r, size_t nmatch, RegexMatch pmatch[], int eflags) {
43 char *buf = text_bytes_alloc0(txt, pos, len);
44 if (!buf)
45 return REG_NOMATCH;
46 char *cur = buf, *end = buf + len;
47 int ret = REG_NOMATCH;
48 regmatch_t match[nmatch];
49 for (size_t junk = len; len > 0; len -= junk, pos += junk) {
50 ret = regexec(&r->regex, cur, nmatch, match, eflags);
51 if (!ret) {
52 for (size_t i = 0; i < nmatch; i++) {
53 pmatch[i].start = match[i].rm_so == -1 ? EPOS : pos + match[i].rm_so;
54 pmatch[i].end = match[i].rm_eo == -1 ? EPOS : pos + match[i].rm_eo;
56 break;
58 char *next = memchr(cur, 0, len);
59 if (!next)
60 break;
61 while (!*next && next != end)
62 next++;
63 junk = next - cur;
64 cur = next;
66 free(buf);
67 return ret;
70 int text_search_range_backward(Text *txt, size_t pos, size_t len, Regex *r, size_t nmatch, RegexMatch pmatch[], int eflags) {
71 char *buf = text_bytes_alloc0(txt, pos, len);
72 if (!buf)
73 return REG_NOMATCH;
74 char *cur = buf, *end = buf + len;
75 int ret = REG_NOMATCH;
76 regmatch_t match[nmatch];
77 for (size_t junk = len; len > 0; len -= junk, pos += junk) {
78 char *next;
79 if (!regexec(&r->regex, cur, nmatch, match, eflags)) {
80 ret = 0;
81 for (size_t i = 0; i < nmatch; i++) {
82 pmatch[i].start = match[i].rm_so == -1 ? EPOS : pos + match[i].rm_so;
83 pmatch[i].end = match[i].rm_eo == -1 ? EPOS : pos + match[i].rm_eo;
86 if (match[0].rm_so == 0 && match[0].rm_eo == 0) {
87 /* empty match at the beginning of cur, advance to next line */
88 next = strchr(cur, '\n');
89 if (!next)
90 break;
91 next++;
92 } else {
93 next = cur + match[0].rm_eo;
95 } else {
96 next = memchr(cur, 0, len);
97 if (!next)
98 break;
99 while (!*next && next != end)
100 next++;
102 junk = next - cur;
103 cur = next;
105 free(buf);
106 return ret;