source: tags/arb_5.2/SL/REGEXPR/RegExpr.cxx

Last change on this file was 5810, checked in by westram, 15 years ago
  • free→delete[]
File size: 3.5 KB
Line 
1// ============================================================= //
2//                                                               //
3//   File      : RegExpr.cxx                                     //
4//   Purpose   : Wrapper for ARBDB regular expressions           //
5//                                                               //
6//   Coded by Ralf Westram (coder@reallysoft.de) in April 2009   //
7//   Institute of Microbiology (Technical University Munich)     //
8//   http://www.arb-home.de/                                     //
9//                                                               //
10// ============================================================= //
11
12#include "RegExpr.hxx"
13#include <arbdbt.h>
14#include <regex.h>
15
16using namespace std;
17
18struct GBS_regex { regex_t compiled; }; // definition exists twice (see ../../ARBDB/admatch.c)
19
20
21RegExpr::RegExpr(const std::string& expression_, bool ignore_case_)
22    : expression(expression_)
23    , ignore_case(ignore_case_)
24    , comreg(0)
25    , matches(0)
26{
27}
28
29RegExpr::~RegExpr() {
30    if (comreg) GBS_free_regexpr(comreg);
31    free(matches);
32}
33
34void RegExpr::compile() const {
35    if (!comreg) {
36        delete [] matches; matches = NULL;
37       
38        GB_ERROR error = 0;
39        comreg = GBS_compile_regexpr(expression.c_str(), ignore_case ? GB_IGNORE_CASE : GB_MIND_CASE, &error);
40        if (error) throw string(error);
41        re_assert(comreg);
42    }
43}
44
45void RegExpr::perform_match(const char *str, size_t offset) const {
46    /* Searches for first match (and submatches) in 'str'
47     *
48     * sets member 'matches' to array of match + subexpression matches (heap-copy)
49     * or to NULL if nothing matched
50     *
51     * If 'offset' > 0, then str is searched from position 'offset'.
52     * In this case it is assumed, that we are not at line start!
53     */
54
55    delete [] matches; matches = NULL;
56
57    size_t      subs      = subexpr_count();
58    regmatch_t *possMatch = (regmatch_t*)malloc((subs+1) * sizeof(regmatch_t));
59    int         eflags    = offset ? REG_NOTBOL : 0;
60    int         res       = regexec(&comreg->compiled, str+offset, subs+1, possMatch, eflags);
61
62    if (res != REG_NOMATCH) {
63        matches  = new RegMatch[subs+1];
64        for (size_t s = 0; s <= subs; s++) {
65            if (possMatch[s].rm_so != -1) { // real match
66                matches[s] = RegMatch(possMatch[s].rm_so+offset, possMatch[s].rm_eo+offset);
67            }
68        }
69        re_assert(matches[0].didMatch()); // complete match has to be found
70    }
71    free(possMatch);
72}
73
74void RegExpr::test() const {
75    compile();
76}
77
78const RegMatch *RegExpr::match(const std::string& versus, size_t offset) const {
79    if (!comreg) compile();                         // lazy compilation
80    perform_match(versus.c_str(), offset);
81    return matches ? &matches[0] : NULL;
82}
83
84size_t RegExpr::subexpr_count() const {
85    if (!comreg) compile();                       // lazy compilation
86    return comreg->compiled.re_nsub;
87}
88
89const RegMatch *RegExpr::subexpr_match(size_t subnr) const {
90    // get subexpression match from last 'match()'
91    // (or NULL if subexpression 'subnr' did not match)
92    //
93    // 'subnr' is in range [1..subexpr_count()]
94
95    const RegMatch *result = 0;
96    if (matches) {
97        size_t subs = subexpr_count();
98        re_assert(subnr >= 1 && subnr <= subs); // illegal subexpression index
99        if (subnr >= 1 && subnr <= subs) {
100            if (matches[subnr].didMatch()) result = &matches[subnr];
101        }
102    }
103    return result;
104}
105
106
107
Note: See TracBrowser for help on using the repository browser.