aboutsummaryrefslogtreecommitdiff
path: root/text-regex.c
blob: c4134aa24257a496a3f64c504bb1505377a21b26 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include <stdlib.h>
#include <regex.h>

#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(&regex->regex, string, cflags);
	if (r)
		regcomp(&regex->regex, "\0\0", 0);
	return r;
}

void text_regex_free(Regex *r) {
	if (!r)
		return;
	regfree(&r->regex);
	free(r);
}

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;
	regmatch_t match[nmatch];
	int ret = regexec(&r->regex, buf, 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;
		}
	}
	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;
	regmatch_t match[nmatch];
	char *cur = buf;
	int ret = REG_NOMATCH;
	while (!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 + (size_t)(cur - buf) + match[i].rm_so;
			pmatch[i].end = match[i].rm_eo == -1 ? EPOS : pos + (size_t)(cur - buf) + match[i].rm_eo;
		}
		cur += match[0].rm_eo;
	}
	free(buf);
	return ret;
}