-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmatcher.c
More file actions
118 lines (95 loc) · 2.75 KB
/
matcher.c
File metadata and controls
118 lines (95 loc) · 2.75 KB
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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#include <regex.h>
#include <stdlib.h>
#include <string.h>
#include "common.h"
#include "matcher.h"
/* helper that compiles a regex from a pattern */
static regex_t *regex_make(const char *regex, int cflags) {
regex_t *matcher = (regex_t *)xmalloc(sizeof(regex_t));
/* Compile regular expression */
int err = regcomp(matcher, regex, cflags);
if (err) {
panic("Could not compile regex");
}
return matcher;
}
struct matcher_t {
size_t mcap;
match_t *matches;
char *line;
regex_t *regex;
regmatch_t *groups;
};
/* required for opaque type */
matcher_t *matcher_new() { return (matcher_t *)xmalloc(sizeof(matcher_t)); }
void matcher_make(matcher_t *self, char *pattern, int cflags) {
self->regex = regex_make(pattern, REG_EXTENDED | cflags);
/* number of groups detected, plus one for entire match */
size_t nsub = self->regex->re_nsub;
if(!nsub){
panic("No groups found.");
}
self->groups = (regmatch_t *)xmalloc((nsub + 1) * sizeof(regmatch_t));
self->mcap = nsub;
self->matches = (match_t *)xmalloc(sizeof(match_t) * (self->mcap));
}
void matcher_match_reset(matcher_t *self) {
if(self->line){
free(self->line);
}
self->line = NULL;
int i;
for (i = 0; i < self->mcap; i++) {
self->matches[i].start = NULL;
self->matches[i].len = 0;
}
}
/* free allocated internal structure */
void matcher_free(matcher_t *self) {
free(self->groups);
/* Free memory allocated to the pattern buffer by regcomp() */
regfree(self->regex);
free(self->regex);
matcher_match_reset(self);
free(self->matches);
}
void matcher_match_line(matcher_t *self, const char *slice, const int len,
int eflags) {
/* copy line and add terminator */
self->line = (char *)xmalloc(len + 1);
memcpy(self->line, slice, len);
char *start = self->line;
/* Execute regular expression */
int err = regexec(self->regex, start, self->mcap + 1, self->groups, eflags);
while (err == 0) {
/* store matched groups */
int i;
for (i = 1; i <= self->mcap; i++) {
regoff_t so = self->groups[i].rm_so;
regoff_t eo = self->groups[i].rm_eo;
if (so < 0 || eo < 0) {
continue;
}
self->matches[i - 1].start = &start[so];
self->matches[i - 1].len = eo - so;
}
/* look for next match */
start += self->groups[0].rm_eo;
/* search next match on same line */
// err = regexec(regex, start, groupsc, groups, eflags);
err = REG_NOMATCH;
}
/* check for error */
if (err != REG_NOMATCH) {
char msgbuf[100];
regerror(err, self->regex, msgbuf, sizeof(msgbuf));
panic(msgbuf);
}
}
match_t *matcher_match_get(matcher_t *self, size_t idx) {
/* out of bounds? */
if (self->mcap <= idx) {
return NULL;
}
return &(self->matches[idx]);
}