vis: normalize selections after pairwise combination
[vis.git] / text-regex-tre.c
blob0ac8b381f4c854b8b6efb5455da24857edfcff7b
1 #include <stdlib.h>
2 #include <string.h>
4 #include "text-regex.h"
5 #include "text-motions.h"
7 struct Regex {
8 regex_t regex;
9 tre_str_source str_source;
10 Text *text;
11 Iterator it;
12 size_t end;
15 size_t text_regex_nsub(Regex *r) {
16 if (!r)
17 return 0;
18 return r->regex.re_nsub;
21 static int str_next_char(tre_char_t *c, unsigned int *pos_add, void *context) {
22 Regex *r = context;
23 *pos_add = 1;
24 if (r->it.pos < r->end && text_iterator_byte_get(&r->it, (char*)c)) {
25 text_iterator_byte_next(&r->it, NULL);
26 return 0;
27 } else {
28 *c = '\0';
29 return 1;
33 static void str_rewind(size_t pos, void *context) {
34 Regex *r = context;
35 r->it = text_iterator_get(r->text, pos);
38 static int str_compare(size_t pos1, size_t pos2, size_t len, void *context) {
39 Regex *r = context;
40 int ret = 1;
41 void *buf1 = malloc(len), *buf2 = malloc(len);
42 if (!buf1 || !buf2)
43 goto err;
44 text_bytes_get(r->text, pos1, len, buf1);
45 text_bytes_get(r->text, pos2, len, buf2);
46 ret = memcmp(buf1, buf2, len);
47 err:
48 free(buf1);
49 free(buf2);
50 return ret;
53 Regex *text_regex_new(void) {
54 Regex *r = calloc(1, sizeof(*r));
55 if (!r)
56 return NULL;
57 r->str_source = (tre_str_source) {
58 .get_next_char = str_next_char,
59 .rewind = str_rewind,
60 .compare = str_compare,
61 .context = r,
63 return r;
66 void text_regex_free(Regex *r) {
67 if (!r)
68 return;
69 tre_regfree(&r->regex);
70 free(r);
73 int text_regex_compile(Regex *regex, const char *string, int cflags) {
74 int r = tre_regcomp(&regex->regex, string, cflags);
75 if (r)
76 tre_regcomp(&regex->regex, "\0\0", 0);
77 return r;
80 int text_regex_match(Regex *r, const char *data, int eflags) {
81 return tre_regexec(&r->regex, data, 0, NULL, eflags);
84 int text_search_range_forward(Text *txt, size_t pos, size_t len, Regex *r, size_t nmatch, RegexMatch pmatch[], int eflags) {
85 r->text = txt;
86 r->it = text_iterator_get(txt, pos);
87 r->end = pos+len;
89 regmatch_t match[nmatch];
90 int ret = tre_reguexec(&r->regex, &r->str_source, nmatch, match, eflags);
91 if (!ret) {
92 for (size_t i = 0; i < nmatch; i++) {
93 pmatch[i].start = match[i].rm_so == -1 ? EPOS : pos + match[i].rm_so;
94 pmatch[i].end = match[i].rm_eo == -1 ? EPOS : pos + match[i].rm_eo;
97 return ret;
100 int text_search_range_backward(Text *txt, size_t pos, size_t len, Regex *r, size_t nmatch, RegexMatch pmatch[], int eflags) {
101 int ret = REG_NOMATCH;
102 size_t end = pos + len;
104 while (pos < end && !text_search_range_forward(txt, pos, len, r, nmatch, pmatch, eflags)) {
105 ret = 0;
106 // FIXME: assumes nmatch >= 1
107 size_t next = pmatch[0].end;
108 if (next == pos) {
109 next = text_line_next(txt, pos);
110 if (next == pos)
111 break;
113 pos = next;
114 len = end - pos;
117 return ret;