OLD | NEW |
| (Empty) |
1 // Copyright 2010 The RE2 Authors. All Rights Reserved. | |
2 // Use of this source code is governed by a BSD-style | |
3 // license that can be found in the LICENSE file. | |
4 | |
5 #include "re2/set.h" | |
6 | |
7 #include "util/util.h" | |
8 #include "re2/stringpiece.h" | |
9 #include "re2/prog.h" | |
10 #include "re2/re2.h" | |
11 #include "re2/regexp.h" | |
12 | |
13 using namespace re2; | |
14 | |
15 RE2::Set::Set(const RE2::Options& options, RE2::Anchor anchor) { | |
16 options_.Copy(options); | |
17 anchor_ = anchor; | |
18 prog_ = NULL; | |
19 compiled_ = false; | |
20 } | |
21 | |
22 RE2::Set::~Set() { | |
23 for (size_t i = 0; i < re_.size(); i++) | |
24 re_[i]->Decref(); | |
25 delete prog_; | |
26 } | |
27 | |
28 int RE2::Set::Add(const StringPiece& pattern, string* error) { | |
29 if (compiled_) { | |
30 LOG(DFATAL) << "RE2::Set::Add after Compile"; | |
31 return -1; | |
32 } | |
33 | |
34 Regexp::ParseFlags pf = static_cast<Regexp::ParseFlags>( | |
35 options_.ParseFlags()); | |
36 | |
37 RegexpStatus status; | |
38 re2::Regexp* re = Regexp::Parse(pattern, pf, &status); | |
39 if (re == NULL) { | |
40 if (error != NULL) | |
41 *error = status.Text(); | |
42 if (options_.log_errors()) | |
43 LOG(ERROR) << "Error parsing '" << pattern << "': " << status.Text(); | |
44 return -1; | |
45 } | |
46 | |
47 // Concatenate with match index and push on vector. | |
48 int n = static_cast<int>(re_.size()); | |
49 re2::Regexp* m = re2::Regexp::HaveMatch(n, pf); | |
50 if (re->op() == kRegexpConcat) { | |
51 int nsub = re->nsub(); | |
52 re2::Regexp** sub = new re2::Regexp*[nsub + 1]; | |
53 for (int i = 0; i < nsub; i++) | |
54 sub[i] = re->sub()[i]->Incref(); | |
55 sub[nsub] = m; | |
56 re->Decref(); | |
57 re = re2::Regexp::Concat(sub, nsub + 1, pf); | |
58 delete[] sub; | |
59 } else { | |
60 re2::Regexp* sub[2]; | |
61 sub[0] = re; | |
62 sub[1] = m; | |
63 re = re2::Regexp::Concat(sub, 2, pf); | |
64 } | |
65 re_.push_back(re); | |
66 return n; | |
67 } | |
68 | |
69 bool RE2::Set::Compile() { | |
70 if (compiled_) { | |
71 LOG(DFATAL) << "RE2::Set::Compile multiple times"; | |
72 return false; | |
73 } | |
74 compiled_ = true; | |
75 | |
76 Regexp::ParseFlags pf = static_cast<Regexp::ParseFlags>( | |
77 options_.ParseFlags()); | |
78 re2::Regexp* re = re2::Regexp::Alternate(const_cast<re2::Regexp**>(re_.data())
, | |
79 static_cast<int>(re_.size()), pf); | |
80 re_.clear(); | |
81 re2::Regexp* sre = re->Simplify(); | |
82 re->Decref(); | |
83 re = sre; | |
84 if (re == NULL) { | |
85 if (options_.log_errors()) | |
86 LOG(ERROR) << "Error simplifying during Compile."; | |
87 return false; | |
88 } | |
89 | |
90 prog_ = Prog::CompileSet(options_, anchor_, re); | |
91 return prog_ != NULL; | |
92 } | |
93 | |
94 bool RE2::Set::Match(const StringPiece& text, vector<int>* v) const { | |
95 if (!compiled_) { | |
96 LOG(DFATAL) << "RE2::Set::Match without Compile"; | |
97 return false; | |
98 } | |
99 v->clear(); | |
100 bool failed; | |
101 bool ret = prog_->SearchDFA(text, text, Prog::kAnchored, | |
102 Prog::kManyMatch, NULL, &failed, v); | |
103 if (failed) | |
104 LOG(DFATAL) << "RE2::Set::Match: DFA ran out of cache space"; | |
105 | |
106 if (ret == false) | |
107 return false; | |
108 if (v->size() == 0) { | |
109 LOG(DFATAL) << "RE2::Set::Match: match but unknown regexp set"; | |
110 return false; | |
111 } | |
112 return true; | |
113 } | |
OLD | NEW |