24 expression(expression_),
25 ignore_case(ignore_case_),
33 if (failure)
delete failure;
37 bool RegExpr::compile()
const {
38 if (!comreg && !failure) {
39 delete [] matches; matches =
NULp;
44 failure =
new string(error);
51 void RegExpr::perform_match(
const char *
str,
size_t offset)
const {
61 delete [] matches; matches =
NULp;
64 regmatch_t *possMatch = ARB_alloc<regmatch_t>(subs+1);
65 int eflags = offset ? REG_NOTBOL : 0;
66 int res = regexec(&comreg->
compiled, str+offset, subs+1, possMatch, eflags);
68 if (res != REG_NOMATCH) {
70 for (
size_t s = 0;
s <= subs;
s++) {
71 if (possMatch[
s].rm_so != -1) {
72 matches[
s] =
RegMatch(possMatch[
s].rm_so+offset, possMatch[
s].rm_eo+offset);
83 if (!compile())
return NULp;
85 perform_match(versus.c_str(),
offset);
86 return (matches && matches[0].didMatch()) ? &matches[0] :
NULp;
92 if (!compile())
return 0;
107 if (subnr >= 1 && subnr <= subs) {
108 if (matches[subnr].didMatch()) result = &matches[subnr];
123 const string *expression_failed = exp.
has_failed();
127 if (expression_failed) {
128 const char *expression_failed_msg = expression_failed->c_str();
131 return all().ofgroup(expected);
135 const string *expression_failed = exp.
has_failed();
139 if (expression_failed) {
140 const char *expression_failed_msg = expression_failed->c_str();
143 return all().ofgroup(expected);
147 const string *expression_failed = exp.
has_failed();
150 if (expression_failed) {
151 const char *expression_failed_msg = expression_failed->c_str();
154 return all().ofgroup(expected);
157 #define TEST_REGEX_FAILS_TO_COMPILE(regexpr,error) do{ \
158 RegExpr exp(regexpr, false); \
159 TEST_EXPECTATION(fails_to_compile(exp,error)); \
162 #define TEST_REGEX_MATCHES(str,regexpr,igCase,exp_match) do { \
163 RegExpr exp(regexpr, igCase); \
164 const RegMatch *match = exp.match(str); \
165 TEST_EXPECTATION(got_a_match(exp,match)); \
166 TEST_EXPECT_EQUAL(match->extract(str).c_str(), exp_match); \
169 #define TEST_REGEX_DOESNT_MATCH(str,regexpr,igCase) do { \
170 RegExpr exp(regexpr, igCase); \
171 const RegMatch *match = exp.match(str); \
172 TEST_EXPECTATION(got_no_match(exp,match)); \
175 #define TEST_REGEX_MATCHES_SUB1(str,regexpr,igCase,exp_match,exp_sub1match) do { \
176 RegExpr exp(regexpr, igCase); \
177 const RegMatch *match = exp.match(str); \
178 TEST_EXPECTATION(got_a_match(exp,match)); \
179 TEST_EXPECT_EQUAL(match->extract(str).c_str(), exp_match); \
180 match = exp.subexpr_match(1); \
181 TEST_REJECT_NULL(match); \
182 TEST_EXPECT_EQUAL(match->extract(str).c_str(), exp_sub1match); \
185 void TEST_regexpr() {
186 TEST_REGEX_MATCHES(
"bla",
"^bla$",
false,
"bla");
188 TEST_REGEX_DOESNT_MATCH(
"3;1406",
"^bla$",
true);
192 TEST_REGEX_FAILS_TO_COMPILE(
"*",
"repetition-operator operand invalid");
193 TEST_REGEX_FAILS_TO_COMPILE(
"[[:fantasy:]]*",
"invalid character class");
194 TEST_REGEX_FAILS_TO_COMPILE(
"x{2",
"braces not balanced");
195 TEST_REGEX_FAILS_TO_COMPILE(
"x{2-5}",
"invalid repetition count(s)");
196 TEST_REGEX_FAILS_TO_COMPILE(
"x{5,2}",
"invalid repetition count(s)");
198 TEST_REGEX_FAILS_TO_COMPILE(
"*",
"Invalid preceding regular expression");
199 TEST_REGEX_FAILS_TO_COMPILE(
"[[:fantasy:]]*",
"Invalid character class name");
200 TEST_REGEX_FAILS_TO_COMPILE(
"x{2",
"Unmatched \\{");
201 TEST_REGEX_FAILS_TO_COMPILE(
"x{2-5}",
"Invalid content of \\{\\}");
202 TEST_REGEX_FAILS_TO_COMPILE(
"x{5,2}",
"Invalid content of \\{\\}");
207 TEST_REGEX_FAILS_TO_COMPILE(
"^bla|",
"empty (sub)expression");
209 TEST_REGEX_MATCHES(
"3;1406",
"^bla|",
true,
"");
212 TEST_REGEX_MATCHES_SUB1(
"3;1406",
"^[0-9]+;([0-9]+)$",
true,
"3;1406",
"1406");
213 TEST_REGEX_MATCHES_SUB1(
" Find CAPITAL \t WoRD ",
"[[:space:]]+([A-Z]+)[[:space:]]+",
false,
" CAPITAL \t ",
"CAPITAL");
214 TEST_REGEX_MATCHES_SUB1(
"--ajsd--aksjdh----alsdjkasldja---",
"-+([a-z]{5,8})-+",
true,
"--aksjdh----",
"aksjdh");
const RegMatch * subexpr_match(size_t subnr) const
GBS_regex * GBS_compile_regexpr(const char *regexpr, GB_CASE case_flag, GB_ERROR *error)
return string(buffer, length)
RegExpr(const std::string &expression_, bool ignore_case)
#define TEST_PUBLISH(testfunction)
#define is_equal_to_NULL()
static void error(const char *msg)
const RegMatch * match(const std::string &versus, size_t offset=0) const
#define does_differ_from_NULL()
const std::string * has_failed() const
void GBS_free_regexpr(GBS_regex *toFree)
size_t subexpr_count() const
GB_write_int const char s