blob: 4ccd7748b13e95b339c8d5468232d5cd8bb02f16 [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(),
Greg Claytonbc43cab2013-04-03 21:37:16 +000023 m_compile_flags(REG_EXTENDED)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000024{
25 memset(&m_preg,0,sizeof(m_preg));
26}
27
28//----------------------------------------------------------------------
29// Constructor that compiles "re" using "flags" and stores the
30// resulting compiled regular expression into this object.
31//----------------------------------------------------------------------
32RegularExpression::RegularExpression(const char* re, int flags) :
33 m_re(),
34 m_comp_err (1),
Daniel Dunbara08823f2011-10-31 22:50:49 +000035 m_preg(),
36 m_compile_flags(flags)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000037{
38 memset(&m_preg,0,sizeof(m_preg));
Jim Ingham969795f2011-09-21 01:17:13 +000039 Compile(re);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000040}
41
42//----------------------------------------------------------------------
Jim Ingham969795f2011-09-21 01:17:13 +000043// Constructor that compiles "re" using "flags" and stores the
44// resulting compiled regular expression into this object.
45//----------------------------------------------------------------------
46RegularExpression::RegularExpression(const char* re) :
47 m_re(),
48 m_comp_err (1),
Daniel Dunbara08823f2011-10-31 22:50:49 +000049 m_preg(),
50 m_compile_flags(REG_EXTENDED)
Jim Ingham969795f2011-09-21 01:17:13 +000051{
52 memset(&m_preg,0,sizeof(m_preg));
53 Compile(re);
54}
55
56RegularExpression::RegularExpression(const RegularExpression &rhs)
57{
58 memset(&m_preg,0,sizeof(m_preg));
59 Compile(rhs.GetText(), rhs.GetCompileFlags());
60}
61
62const RegularExpression &
63RegularExpression::operator= (const RegularExpression &rhs)
64{
65 if (&rhs != this)
66 {
67 Compile (rhs.GetText(), rhs.GetCompileFlags());
68 }
69 return *this;
70}
71//----------------------------------------------------------------------
Chris Lattner30fdc8d2010-06-08 16:52:24 +000072// Destructor
73//
74// Any previosuly compiled regular expression contained in this
75// object will be freed.
76//----------------------------------------------------------------------
77RegularExpression::~RegularExpression()
78{
79 Free();
80}
81
82//----------------------------------------------------------------------
83// Compile a regular expression using the supplied regular
84// expression text and flags. The compied regular expression lives
85// in this object so that it can be readily used for regular
86// expression matches. Execute() can be called after the regular
87// expression is compiled. Any previosuly compiled regular
88// expression contained in this object will be freed.
89//
90// RETURNS
91// True of the refular expression compiles successfully, false
92// otherwise.
93//----------------------------------------------------------------------
94bool
Jim Ingham969795f2011-09-21 01:17:13 +000095RegularExpression::Compile(const char* re)
96{
97 return Compile (re, m_compile_flags);
98}
99
100bool
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000101RegularExpression::Compile(const char* re, int flags)
102{
103 Free();
Jim Ingham969795f2011-09-21 01:17:13 +0000104 m_compile_flags = flags;
105
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000106 if (re && re[0])
107 {
108 m_re = re;
109 m_comp_err = ::regcomp (&m_preg, re, flags);
110 }
111 else
112 {
113 // No valid regular expression
114 m_comp_err = 1;
115 }
116
117 return m_comp_err == 0;
118}
119
120//----------------------------------------------------------------------
121// Execute a regular expression match using the compiled regular
122// expression that is already in this object against the match
123// string "s". If any parens are used for regular expression
124// matches "match_count" should indicate the number of regmatch_t
125// values that are present in "match_ptr". The regular expression
126// will be executed using the "execute_flags".
Greg Claytonbc43cab2013-04-03 21:37:16 +0000127//---------------------------------------------------------------------
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000128bool
Greg Claytonbc43cab2013-04-03 21:37:16 +0000129RegularExpression::Execute(const char* s, Match *match, int execute_flags) const
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000130{
Greg Claytonbc43cab2013-04-03 21:37:16 +0000131 int err = 1;
Greg Claytoncc247752013-05-23 20:27:15 +0000132 if (s != NULL && m_comp_err == 0)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000133 {
Greg Claytonbc43cab2013-04-03 21:37:16 +0000134 if (match)
Greg Clayton1b3815c2013-01-30 00:18:29 +0000135 {
Greg Claytonbc43cab2013-04-03 21:37:16 +0000136 err = ::regexec (&m_preg,
137 s,
138 match->GetSize(),
139 match->GetData(),
140 execute_flags);
141 }
142 else
143 {
144 err = ::regexec (&m_preg,
145 s,
146 0,
147 NULL,
148 execute_flags);
Greg Clayton1b3815c2013-01-30 00:18:29 +0000149 }
150 }
Greg Claytonbc43cab2013-04-03 21:37:16 +0000151
152 if (err != 0)
153 {
154 // The regular expression didn't compile, so clear the matches
155 if (match)
156 match->Clear();
157 return false;
158 }
159 return true;
Greg Clayton1b3815c2013-01-30 00:18:29 +0000160}
161
162bool
Greg Claytonbc43cab2013-04-03 21:37:16 +0000163RegularExpression::Match::GetMatchAtIndex (const char* s, uint32_t idx, std::string& match_str) const
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000164{
Greg Claytonbc43cab2013-04-03 21:37:16 +0000165 if (idx < m_matches.size())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000166 {
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000167 if (m_matches[idx].rm_eo == m_matches[idx].rm_so)
168 {
169 // Matched the empty string...
170 match_str.clear();
171 return true;
172 }
173 else if (m_matches[idx].rm_eo > m_matches[idx].rm_so)
174 {
175 match_str.assign (s + m_matches[idx].rm_so,
176 m_matches[idx].rm_eo - m_matches[idx].rm_so);
177 return true;
178 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000179 }
180 return false;
181}
182
Greg Clayton1b3815c2013-01-30 00:18:29 +0000183bool
Greg Claytonbc43cab2013-04-03 21:37:16 +0000184RegularExpression::Match::GetMatchAtIndex (const char* s, uint32_t idx, llvm::StringRef& match_str) const
Greg Clayton1b3815c2013-01-30 00:18:29 +0000185{
Greg Claytonbc43cab2013-04-03 21:37:16 +0000186 if (idx < m_matches.size())
Greg Clayton1b3815c2013-01-30 00:18:29 +0000187 {
188 if (m_matches[idx].rm_eo == m_matches[idx].rm_so)
189 {
190 // Matched the empty string...
191 match_str = llvm::StringRef();
192 return true;
193 }
194 else if (m_matches[idx].rm_eo > m_matches[idx].rm_so)
195 {
196 match_str = llvm::StringRef (s + m_matches[idx].rm_so, m_matches[idx].rm_eo - m_matches[idx].rm_so);
197 return true;
198 }
199 }
200 return false;
201}
202
203bool
Greg Claytonbc43cab2013-04-03 21:37:16 +0000204RegularExpression::Match::GetMatchSpanningIndices (const char* s, uint32_t idx1, uint32_t idx2, llvm::StringRef& match_str) const
Greg Clayton1b3815c2013-01-30 00:18:29 +0000205{
Greg Claytonbc43cab2013-04-03 21:37:16 +0000206 if (idx1 < m_matches.size() && idx2 < m_matches.size())
Greg Clayton1b3815c2013-01-30 00:18:29 +0000207 {
208 if (m_matches[idx1].rm_so == m_matches[idx2].rm_eo)
209 {
210 // Matched the empty string...
211 match_str = llvm::StringRef();
212 return true;
213 }
214 else if (m_matches[idx1].rm_so < m_matches[idx2].rm_eo)
215 {
216 match_str = llvm::StringRef (s + m_matches[idx1].rm_so, m_matches[idx2].rm_eo - m_matches[idx1].rm_so);
217 return true;
218 }
219 }
220 return false;
221}
222
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000223
224//----------------------------------------------------------------------
225// Returns true if the regular expression compiled and is ready
226// for execution.
227//----------------------------------------------------------------------
228bool
229RegularExpression::IsValid () const
230{
231 return m_comp_err == 0;
232}
233
234//----------------------------------------------------------------------
235// Returns the text that was used to compile the current regular
236// expression.
237//----------------------------------------------------------------------
238const char*
239RegularExpression::GetText () const
240{
Greg Clayton67cc0632012-08-22 17:17:09 +0000241 if (m_re.empty())
242 return NULL;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000243 return m_re.c_str();
244}
245
246//----------------------------------------------------------------------
247// Free any contained compiled regular expressions.
248//----------------------------------------------------------------------
249void
250RegularExpression::Free()
251{
252 if (m_comp_err == 0)
253 {
254 m_re.clear();
255 regfree(&m_preg);
256 // Set a compile error since we no longer have a valid regex
257 m_comp_err = 1;
258 }
259}
Greg Clayton46747022010-10-10 23:55:27 +0000260
261size_t
262RegularExpression::GetErrorAsCString (char *err_str, size_t err_str_max_len) const
263{
264 if (m_comp_err == 0)
265 {
266 if (err_str && err_str_max_len)
267 *err_str = '\0';
268 return 0;
269 }
270
271 return ::regerror (m_comp_err, &m_preg, err_str, err_str_max_len);
272}
273
Enrico Granata0a3958e2011-07-02 00:25:22 +0000274bool
275RegularExpression::operator < (const RegularExpression& rhs) const
276{
277 return (m_re < rhs.m_re);
278}
Greg Clayton46747022010-10-10 23:55:27 +0000279