blob: 1f99bc745f8d82697428eb0677d515159780e82b [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- RegularExpression.cpp -----------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "lldb/Core/RegularExpression.h"
Greg Clayton1b3815c2013-01-30 00:18:29 +000011#include "llvm/ADT/StringRef.h"
Eli Friedman88966972010-06-09 08:50:27 +000012#include <string.h>
Chris Lattner30fdc8d2010-06-08 16:52:24 +000013
14using namespace lldb_private;
15
16//----------------------------------------------------------------------
17// Default constructor
18//----------------------------------------------------------------------
19RegularExpression::RegularExpression() :
20 m_re(),
21 m_comp_err (1),
22 m_preg(),
Jim Ingham969795f2011-09-21 01:17:13 +000023 m_compile_flags(REG_EXTENDED),
Chris Lattner30fdc8d2010-06-08 16:52:24 +000024 m_matches()
25{
26 memset(&m_preg,0,sizeof(m_preg));
27}
28
29//----------------------------------------------------------------------
30// Constructor that compiles "re" using "flags" and stores the
31// resulting compiled regular expression into this object.
32//----------------------------------------------------------------------
33RegularExpression::RegularExpression(const char* re, int flags) :
34 m_re(),
35 m_comp_err (1),
Daniel Dunbara08823f2011-10-31 22:50:49 +000036 m_preg(),
37 m_compile_flags(flags)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000038{
39 memset(&m_preg,0,sizeof(m_preg));
Jim Ingham969795f2011-09-21 01:17:13 +000040 Compile(re);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000041}
42
43//----------------------------------------------------------------------
Jim Ingham969795f2011-09-21 01:17:13 +000044// Constructor that compiles "re" using "flags" and stores the
45// resulting compiled regular expression into this object.
46//----------------------------------------------------------------------
47RegularExpression::RegularExpression(const char* re) :
48 m_re(),
49 m_comp_err (1),
Daniel Dunbara08823f2011-10-31 22:50:49 +000050 m_preg(),
51 m_compile_flags(REG_EXTENDED)
Jim Ingham969795f2011-09-21 01:17:13 +000052{
53 memset(&m_preg,0,sizeof(m_preg));
54 Compile(re);
55}
56
57RegularExpression::RegularExpression(const RegularExpression &rhs)
58{
59 memset(&m_preg,0,sizeof(m_preg));
60 Compile(rhs.GetText(), rhs.GetCompileFlags());
61}
62
63const RegularExpression &
64RegularExpression::operator= (const RegularExpression &rhs)
65{
66 if (&rhs != this)
67 {
68 Compile (rhs.GetText(), rhs.GetCompileFlags());
69 }
70 return *this;
71}
72//----------------------------------------------------------------------
Chris Lattner30fdc8d2010-06-08 16:52:24 +000073// Destructor
74//
75// Any previosuly compiled regular expression contained in this
76// object will be freed.
77//----------------------------------------------------------------------
78RegularExpression::~RegularExpression()
79{
80 Free();
81}
82
83//----------------------------------------------------------------------
84// Compile a regular expression using the supplied regular
85// expression text and flags. The compied regular expression lives
86// in this object so that it can be readily used for regular
87// expression matches. Execute() can be called after the regular
88// expression is compiled. Any previosuly compiled regular
89// expression contained in this object will be freed.
90//
91// RETURNS
92// True of the refular expression compiles successfully, false
93// otherwise.
94//----------------------------------------------------------------------
95bool
Jim Ingham969795f2011-09-21 01:17:13 +000096RegularExpression::Compile(const char* re)
97{
98 return Compile (re, m_compile_flags);
99}
100
101bool
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000102RegularExpression::Compile(const char* re, int flags)
103{
104 Free();
Jim Ingham969795f2011-09-21 01:17:13 +0000105 m_compile_flags = flags;
106
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000107 if (re && re[0])
108 {
109 m_re = re;
110 m_comp_err = ::regcomp (&m_preg, re, flags);
111 }
112 else
113 {
114 // No valid regular expression
115 m_comp_err = 1;
116 }
117
118 return m_comp_err == 0;
119}
120
121//----------------------------------------------------------------------
122// Execute a regular expression match using the compiled regular
123// expression that is already in this object against the match
124// string "s". If any parens are used for regular expression
125// matches "match_count" should indicate the number of regmatch_t
126// values that are present in "match_ptr". The regular expression
127// will be executed using the "execute_flags".
128//----------------------------------------------------------------------
129bool
130RegularExpression::Execute(const char* s, size_t num_matches, int execute_flags) const
131{
132 int match_result = 1;
133 if (m_comp_err == 0)
134 {
135 if (num_matches > 0)
136 m_matches.resize(num_matches + 1);
137 else
138 m_matches.clear();
139
140 match_result = ::regexec (&m_preg,
141 s,
142 m_matches.size(),
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000143 &m_matches[0],
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000144 execute_flags);
145 }
146 return match_result == 0;
147}
148
149bool
Greg Clayton1b3815c2013-01-30 00:18:29 +0000150RegularExpression::ExecuteThreadSafe (const char* s, llvm::StringRef *match_srefs, size_t count, int execute_flags) const
151{
152 bool success = false;
153 if (m_comp_err == 0)
154 {
155 std::vector<regmatch_t> matches;
156
157 if (match_srefs && count > 0)
158 matches.resize(count + 1);
159
160 success = ::regexec (&m_preg,
161 s,
162 matches.size(),
163 matches.data(),
164 execute_flags) == 0;
165 for (size_t i=0; i<count; ++i)
166 {
167 size_t match_idx = i+1;
168 if (success && matches[match_idx].rm_so < matches[match_idx].rm_eo)
169 match_srefs[i] = llvm::StringRef(s + matches[match_idx].rm_so, matches[match_idx].rm_eo - matches[match_idx].rm_so);
170 else
171 match_srefs[i] = llvm::StringRef();
172 }
173 }
174 return success;
175}
176
177bool
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000178RegularExpression::GetMatchAtIndex (const char* s, uint32_t idx, std::string& match_str) const
179{
180 if (idx <= m_preg.re_nsub && idx < m_matches.size())
181 {
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000182 if (m_matches[idx].rm_eo == m_matches[idx].rm_so)
183 {
184 // Matched the empty string...
185 match_str.clear();
186 return true;
187 }
188 else if (m_matches[idx].rm_eo > m_matches[idx].rm_so)
189 {
190 match_str.assign (s + m_matches[idx].rm_so,
191 m_matches[idx].rm_eo - m_matches[idx].rm_so);
192 return true;
193 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000194 }
195 return false;
196}
197
Greg Clayton1b3815c2013-01-30 00:18:29 +0000198bool
199RegularExpression::GetMatchAtIndex (const char* s, uint32_t idx, llvm::StringRef& match_str) const
200{
201 if (idx <= m_preg.re_nsub && idx < m_matches.size())
202 {
203 if (m_matches[idx].rm_eo == m_matches[idx].rm_so)
204 {
205 // Matched the empty string...
206 match_str = llvm::StringRef();
207 return true;
208 }
209 else if (m_matches[idx].rm_eo > m_matches[idx].rm_so)
210 {
211 match_str = llvm::StringRef (s + m_matches[idx].rm_so, m_matches[idx].rm_eo - m_matches[idx].rm_so);
212 return true;
213 }
214 }
215 return false;
216}
217
218bool
219RegularExpression::GetMatchSpanningIndices (const char* s, uint32_t idx1, uint32_t idx2, llvm::StringRef& match_str) const
220{
221 if (idx1 <= m_preg.re_nsub && idx1 < m_matches.size() && idx2 <= m_preg.re_nsub && idx2 < m_matches.size())
222 {
223 if (m_matches[idx1].rm_so == m_matches[idx2].rm_eo)
224 {
225 // Matched the empty string...
226 match_str = llvm::StringRef();
227 return true;
228 }
229 else if (m_matches[idx1].rm_so < m_matches[idx2].rm_eo)
230 {
231 match_str = llvm::StringRef (s + m_matches[idx1].rm_so, m_matches[idx2].rm_eo - m_matches[idx1].rm_so);
232 return true;
233 }
234 }
235 return false;
236}
237
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000238
239//----------------------------------------------------------------------
240// Returns true if the regular expression compiled and is ready
241// for execution.
242//----------------------------------------------------------------------
243bool
244RegularExpression::IsValid () const
245{
246 return m_comp_err == 0;
247}
248
249//----------------------------------------------------------------------
250// Returns the text that was used to compile the current regular
251// expression.
252//----------------------------------------------------------------------
253const char*
254RegularExpression::GetText () const
255{
Greg Clayton67cc0632012-08-22 17:17:09 +0000256 if (m_re.empty())
257 return NULL;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000258 return m_re.c_str();
259}
260
261//----------------------------------------------------------------------
262// Free any contained compiled regular expressions.
263//----------------------------------------------------------------------
264void
265RegularExpression::Free()
266{
267 if (m_comp_err == 0)
268 {
269 m_re.clear();
270 regfree(&m_preg);
271 // Set a compile error since we no longer have a valid regex
272 m_comp_err = 1;
273 }
274}
Greg Clayton46747022010-10-10 23:55:27 +0000275
276size_t
277RegularExpression::GetErrorAsCString (char *err_str, size_t err_str_max_len) const
278{
279 if (m_comp_err == 0)
280 {
281 if (err_str && err_str_max_len)
282 *err_str = '\0';
283 return 0;
284 }
285
286 return ::regerror (m_comp_err, &m_preg, err_str, err_str_max_len);
287}
288
Enrico Granata0a3958e2011-07-02 00:25:22 +0000289bool
290RegularExpression::operator < (const RegularExpression& rhs) const
291{
292 return (m_re < rhs.m_re);
293}
Greg Clayton46747022010-10-10 23:55:27 +0000294