source src/regexp.c
Line | Flow | Count | Block(s) | Source |
---|---|---|---|---|
1 | - | /* | ||
2 | - | * Copyright (C) the libgit2 contributors. All rights reserved. | ||
3 | - | * | ||
4 | - | * This file is part of libgit2, distributed under the GNU GPL v2 with | ||
5 | - | * a Linking Exception. For full terms see the included COPYING file. | ||
6 | - | */ | ||
7 | - | |||
8 | - | #include "regexp.h" | ||
9 | - | |||
10 | - | #if defined(GIT_REGEX_BUILTIN) || defined(GIT_REGEX_PCRE) | ||
11 | - | |||
12 | 1830 | 2 | int git_regexp_compile(git_regexp *r, const char *pattern, int flags) | |
13 | - | { | ||
14 | 1830 | 2 | int erroffset, cflags = 0; | |
15 | - | const char *error; | ||
16 | - | |||
17 | 1830 | 2 | if (flags & GIT_REGEXP_ICASE) | |
18 | 3 | 3 | cflags |= PCRE_CASELESS; | |
19 | - | |||
20 | 1830 | 4,5 | if ((*r = pcre_compile(pattern, cflags, &error, &erroffset, NULL)) == NULL) { | |
21 | 2 | 6 | git_error_set_str(GIT_ERROR_REGEX, error); | |
22 | 2 | 7 | return GIT_EINVALIDSPEC; | |
23 | - | } | ||
24 | - | |||
25 | 1828 | 8 | return 0; | |
26 | - | } | ||
27 | - | |||
28 | 1849 | 2 | void git_regexp_dispose(git_regexp *r) | |
29 | - | { | ||
30 | 1849 | 2 | pcre_free(*r); | |
31 | 1849 | 3 | *r = NULL; | |
32 | 1849 | 3 | } | |
33 | - | |||
34 | 10644 | 2 | int git_regexp_match(const git_regexp *r, const char *string) | |
35 | - | { | ||
36 | - | int error; | ||
37 | 10644 | 2,3 | if ((error = pcre_exec(*r, NULL, string, (int) strlen(string), 0, 0, NULL, 0)) < 0) | |
38 | 8506 | 4-7 | return (error == PCRE_ERROR_NOMATCH) ? GIT_ENOTFOUND : GIT_EINVALIDSPEC; | |
39 | 2138 | 8 | return 0; | |
40 | - | } | ||
41 | - | |||
42 | 146 | 2 | int git_regexp_search(const git_regexp *r, const char *string, size_t nmatches, git_regmatch *matches) | |
43 | - | { | ||
44 | - | int static_ovec[9], *ovec; | ||
45 | - | int error; | ||
46 | - | size_t i; | ||
47 | - | |||
48 | - | /* The ovec array always needs to be a mutiple of three */ | ||
49 | 146 | 2 | if (nmatches <= ARRAY_SIZE(static_ovec) / 3) | |
50 | 145 | 3 | ovec = static_ovec; | |
51 | - | else | ||
52 | 1 | 4 | ovec = git__calloc(nmatches * 3, sizeof(*ovec)); | |
53 | 146 | 5,6 | GIT_ERROR_CHECK_ALLOC(ovec); | |
54 | - | |||
55 | 146 | 7,8 | if ((error = pcre_exec(*r, NULL, string, (int) strlen(string), 0, 0, ovec, (int) nmatches * 3)) < 0) | |
56 | 106 | 9 | goto out; | |
57 | - | |||
58 | 40 | 10 | if (error == 0) | |
59 | 9 | 11 | error = (int) nmatches; | |
60 | - | |||
61 | 115 | 12-14 | for (i = 0; i < (unsigned int) error; i++) { | |
62 | 75 | 13 | matches[i].start = (ovec[i * 2] < 0) ? -1 : ovec[i * 2]; | |
63 | 75 | 13 | matches[i].end = (ovec[i * 2 + 1] < 0) ? -1 : ovec[i * 2 + 1]; | |
64 | - | } | ||
65 | 45 | 15-17 | for (i = (unsigned int) error; i < nmatches; i++) | |
66 | 5 | 16 | matches[i].start = matches[i].end = -1; | |
67 | - | |||
68 | - | out: | ||
69 | 146 | 18 | if (nmatches > ARRAY_SIZE(static_ovec) / 3) | |
70 | 1 | 19 | git__free(ovec); | |
71 | 146 | 20 | if (error < 0) | |
72 | 106 | 21-24 | return (error == PCRE_ERROR_NOMATCH) ? GIT_ENOTFOUND : GIT_EINVALIDSPEC; | |
73 | 40 | 25 | return 0; | |
74 | - | } | ||
75 | - | |||
76 | - | #elif defined(GIT_REGEX_PCRE2) | ||
77 | - | |||
78 | - | int git_regexp_compile(git_regexp *r, const char *pattern, int flags) | ||
79 | - | { | ||
80 | - | unsigned char errmsg[1024]; | ||
81 | - | PCRE2_SIZE erroff; | ||
82 | - | int error, cflags = 0; | ||
83 | - | |||
84 | - | if (flags & GIT_REGEXP_ICASE) | ||
85 | - | cflags |= PCRE2_CASELESS; | ||
86 | - | |||
87 | - | if ((*r = pcre2_compile((const unsigned char *) pattern, PCRE2_ZERO_TERMINATED, | ||
88 | - | cflags, &error, &erroff, NULL)) == NULL) { | ||
89 | - | pcre2_get_error_message(error, errmsg, sizeof(errmsg)); | ||
90 | - | git_error_set_str(GIT_ERROR_REGEX, (char *) errmsg); | ||
91 | - | return GIT_EINVALIDSPEC; | ||
92 | - | } | ||
93 | - | |||
94 | - | return 0; | ||
95 | - | } | ||
96 | - | |||
97 | - | void git_regexp_dispose(git_regexp *r) | ||
98 | - | { | ||
99 | - | pcre2_code_free(*r); | ||
100 | - | *r = NULL; | ||
101 | - | } | ||
102 | - | |||
103 | - | int git_regexp_match(const git_regexp *r, const char *string) | ||
104 | - | { | ||
105 | - | pcre2_match_data *data; | ||
106 | - | int error; | ||
107 | - | |||
108 | - | data = pcre2_match_data_create(1, NULL); | ||
109 | - | GIT_ERROR_CHECK_ALLOC(data); | ||
110 | - | |||
111 | - | if ((error = pcre2_match(*r, (const unsigned char *) string, strlen(string), | ||
112 | - | 0, 0, data, NULL)) < 0) | ||
113 | - | return (error == PCRE2_ERROR_NOMATCH) ? GIT_ENOTFOUND : GIT_EINVALIDSPEC; | ||
114 | - | |||
115 | - | pcre2_match_data_free(data); | ||
116 | - | return 0; | ||
117 | - | } | ||
118 | - | |||
119 | - | int git_regexp_search(const git_regexp *r, const char *string, size_t nmatches, git_regmatch *matches) | ||
120 | - | { | ||
121 | - | pcre2_match_data *data = NULL; | ||
122 | - | PCRE2_SIZE *ovec; | ||
123 | - | int error; | ||
124 | - | size_t i; | ||
125 | - | |||
126 | - | if ((data = pcre2_match_data_create(nmatches, NULL)) == NULL) { | ||
127 | - | git_error_set_oom(); | ||
128 | - | goto out; | ||
129 | - | } | ||
130 | - | |||
131 | - | if ((error = pcre2_match(*r, (const unsigned char *) string, strlen(string), | ||
132 | - | 0, 0, data, NULL)) < 0) | ||
133 | - | goto out; | ||
134 | - | |||
135 | - | if (error == 0 || (unsigned int) error > nmatches) | ||
136 | - | error = nmatches; | ||
137 | - | ovec = pcre2_get_ovector_pointer(data); | ||
138 | - | |||
139 | - | for (i = 0; i < (unsigned int) error; i++) { | ||
140 | - | matches[i].start = (ovec[i * 2] == PCRE2_UNSET) ? -1 : (ssize_t) ovec[i * 2]; | ||
141 | - | matches[i].end = (ovec[i * 2 + 1] == PCRE2_UNSET) ? -1 : (ssize_t) ovec[i * 2 + 1]; | ||
142 | - | } | ||
143 | - | for (i = (unsigned int) error; i < nmatches; i++) | ||
144 | - | matches[i].start = matches[i].end = -1; | ||
145 | - | |||
146 | - | out: | ||
147 | - | pcre2_match_data_free(data); | ||
148 | - | if (error < 0) | ||
149 | - | return (error == PCRE2_ERROR_NOMATCH) ? GIT_ENOTFOUND : GIT_EINVALIDSPEC; | ||
150 | - | return 0; | ||
151 | - | } | ||
152 | - | |||
153 | - | #elif defined(GIT_REGEX_REGCOMP) || defined(GIT_REGEX_REGCOMP_L) | ||
154 | - | |||
155 | - | #if defined(GIT_REGEX_REGCOMP_L) | ||
156 | - | # include <xlocale.h> | ||
157 | - | #endif | ||
158 | - | |||
159 | - | int git_regexp_compile(git_regexp *r, const char *pattern, int flags) | ||
160 | - | { | ||
161 | - | int cflags = REG_EXTENDED, error; | ||
162 | - | char errmsg[1024]; | ||
163 | - | |||
164 | - | if (flags & GIT_REGEXP_ICASE) | ||
165 | - | cflags |= REG_ICASE; | ||
166 | - | |||
167 | - | # if defined(GIT_REGEX_REGCOMP) | ||
168 | - | if ((error = regcomp(r, pattern, cflags)) != 0) | ||
169 | - | # else | ||
170 | - | if ((error = regcomp_l(r, pattern, cflags, (locale_t) 0)) != 0) | ||
171 | - | # endif | ||
172 | - | { | ||
173 | - | regerror(error, r, errmsg, sizeof(errmsg)); | ||
174 | - | git_error_set_str(GIT_ERROR_REGEX, errmsg); | ||
175 | - | return GIT_EINVALIDSPEC; | ||
176 | - | } | ||
177 | - | |||
178 | - | return 0; | ||
179 | - | } | ||
180 | - | |||
181 | - | void git_regexp_dispose(git_regexp *r) | ||
182 | - | { | ||
183 | - | regfree(r); | ||
184 | - | } | ||
185 | - | |||
186 | - | int git_regexp_match(const git_regexp *r, const char *string) | ||
187 | - | { | ||
188 | - | int error; | ||
189 | - | if ((error = regexec(r, string, 0, NULL, 0)) != 0) | ||
190 | - | return (error == REG_NOMATCH) ? GIT_ENOTFOUND : GIT_EINVALIDSPEC; | ||
191 | - | return 0; | ||
192 | - | } | ||
193 | - | |||
194 | - | int git_regexp_search(const git_regexp *r, const char *string, size_t nmatches, git_regmatch *matches) | ||
195 | - | { | ||
196 | - | regmatch_t static_m[3], *m; | ||
197 | - | int error; | ||
198 | - | size_t i; | ||
199 | - | |||
200 | - | if (nmatches <= ARRAY_SIZE(static_m)) | ||
201 | - | m = static_m; | ||
202 | - | else | ||
203 | - | m = git__calloc(nmatches, sizeof(*m)); | ||
204 | - | |||
205 | - | if ((error = regexec(r, string, nmatches, m, 0)) != 0) | ||
206 | - | goto out; | ||
207 | - | |||
208 | - | for (i = 0; i < nmatches; i++) { | ||
209 | - | matches[i].start = (m[i].rm_so < 0) ? -1 : m[i].rm_so; | ||
210 | - | matches[i].end = (m[i].rm_eo < 0) ? -1 : m[i].rm_eo; | ||
211 | - | } | ||
212 | - | |||
213 | - | out: | ||
214 | - | if (nmatches > ARRAY_SIZE(static_m)) | ||
215 | - | git__free(m); | ||
216 | - | if (error) | ||
217 | - | return (error == REG_NOMATCH) ? GIT_ENOTFOUND : GIT_EINVALIDSPEC; | ||
218 | - | return 0; | ||
219 | - | } | ||
220 | - | |||
221 | - | #endif |