aboutsummaryrefslogtreecommitdiff
path: root/text-regex.c
diff options
context:
space:
mode:
Diffstat (limited to 'text-regex.c')
-rw-r--r--text-regex.c71
1 files changed, 71 insertions, 0 deletions
diff --git a/text-regex.c b/text-regex.c
new file mode 100644
index 0000000..cff8587
--- /dev/null
+++ b/text-regex.c
@@ -0,0 +1,71 @@
+#include <stdlib.h>
+#include <regex.h>
+
+#include "text-regex.h"
+
+struct Regex {
+ const char *string;
+ 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) {
+ regex->string = string;
+ 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 = malloc(len + 1);
+ if (!buf)
+ return REG_NOMATCH;
+ len = text_bytes_get(txt, pos, len, buf);
+ buf[len] = '\0';
+ 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 = malloc(len + 1);
+ if (!buf)
+ return REG_NOMATCH;
+ len = text_bytes_get(txt, pos, len, buf);
+ buf[len] = '\0';
+ 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;
+}