blob: 54924d06953792c3348cb51cffd08a9fa0cce7f0 [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//
Bruce Mitchenerd93c4a32014-07-01 21:22:11 +000074// Any previously compiled regular expression contained in this
Chris Lattner30fdc8d2010-06-08 16:52:24 +000075// object will be freed.
76//----------------------------------------------------------------------
77RegularExpression::~RegularExpression()
78{
79 Free();
80}
81
82//----------------------------------------------------------------------
83// Compile a regular expression using the supplied regular
Bruce Mitchenerd93c4a32014-07-01 21:22:11 +000084// expression text and flags. The compiled regular expression lives
Chris Lattner30fdc8d2010-06-08 16:52:24 +000085// in this object so that it can be readily used for regular
86// expression matches. Execute() can be called after the regular
Bruce Mitchenerd93c4a32014-07-01 21:22:11 +000087// expression is compiled. Any previously compiled regular
Chris Lattner30fdc8d2010-06-08 16:52:24 +000088// expression contained in this object will be freed.
89//
90// RETURNS
Bruce Mitchenerd93c4a32014-07-01 21:22:11 +000091// True if the regular expression compiles successfully, false
Chris Lattner30fdc8d2010-06-08 16:52:24 +000092// 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 Claytonfa226b72014-10-22 21:43:15 +0000165 llvm::StringRef match_str_ref;
166 if (GetMatchAtIndex(s, idx, match_str_ref))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000167 {
Greg Claytonfa226b72014-10-22 21:43:15 +0000168 match_str = std::move(match_str_ref.str());
169 return true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000170 }
171 return false;
172}
173
Greg Clayton1b3815c2013-01-30 00:18:29 +0000174bool
Greg Claytonbc43cab2013-04-03 21:37:16 +0000175RegularExpression::Match::GetMatchAtIndex (const char* s, uint32_t idx, llvm::StringRef& match_str) const
Greg Clayton1b3815c2013-01-30 00:18:29 +0000176{
Greg Claytonbc43cab2013-04-03 21:37:16 +0000177 if (idx < m_matches.size())
Greg Clayton1b3815c2013-01-30 00:18:29 +0000178 {
Greg Claytonfa226b72014-10-22 21:43:15 +0000179 if (m_matches[idx].rm_eo == -1 && m_matches[idx].rm_so == -1)
180 return false;
181
Greg Clayton1b3815c2013-01-30 00:18:29 +0000182 if (m_matches[idx].rm_eo == m_matches[idx].rm_so)
183 {
184 // Matched the empty string...
185 match_str = llvm::StringRef();
186 return true;
187 }
188 else if (m_matches[idx].rm_eo > m_matches[idx].rm_so)
189 {
190 match_str = llvm::StringRef (s + m_matches[idx].rm_so, m_matches[idx].rm_eo - m_matches[idx].rm_so);
191 return true;
192 }
193 }
194 return false;
195}
196
197bool
Greg Claytonbc43cab2013-04-03 21:37:16 +0000198RegularExpression::Match::GetMatchSpanningIndices (const char* s, uint32_t idx1, uint32_t idx2, llvm::StringRef& match_str) const
Greg Clayton1b3815c2013-01-30 00:18:29 +0000199{
Greg Claytonbc43cab2013-04-03 21:37:16 +0000200 if (idx1 < m_matches.size() && idx2 < m_matches.size())
Greg Clayton1b3815c2013-01-30 00:18:29 +0000201 {
202 if (m_matches[idx1].rm_so == m_matches[idx2].rm_eo)
203 {
204 // Matched the empty string...
205 match_str = llvm::StringRef();
206 return true;
207 }
208 else if (m_matches[idx1].rm_so < m_matches[idx2].rm_eo)
209 {
210 match_str = llvm::StringRef (s + m_matches[idx1].rm_so, m_matches[idx2].rm_eo - m_matches[idx1].rm_so);
211 return true;
212 }
213 }
214 return false;
215}
216
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000217
218//----------------------------------------------------------------------
219// Returns true if the regular expression compiled and is ready
220// for execution.
221//----------------------------------------------------------------------
222bool
223RegularExpression::IsValid () const
224{
225 return m_comp_err == 0;
226}
227
228//----------------------------------------------------------------------
229// Returns the text that was used to compile the current regular
230// expression.
231//----------------------------------------------------------------------
232const char*
233RegularExpression::GetText () const
234{
Greg Clayton67cc0632012-08-22 17:17:09 +0000235 if (m_re.empty())
236 return NULL;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000237 return m_re.c_str();
238}
239
240//----------------------------------------------------------------------
241// Free any contained compiled regular expressions.
242//----------------------------------------------------------------------
243void
244RegularExpression::Free()
245{
246 if (m_comp_err == 0)
247 {
248 m_re.clear();
249 regfree(&m_preg);
250 // Set a compile error since we no longer have a valid regex
251 m_comp_err = 1;
252 }
253}
Greg Clayton46747022010-10-10 23:55:27 +0000254
255size_t
256RegularExpression::GetErrorAsCString (char *err_str, size_t err_str_max_len) const
257{
258 if (m_comp_err == 0)
259 {
260 if (err_str && err_str_max_len)
261 *err_str = '\0';
262 return 0;
263 }
264
265 return ::regerror (m_comp_err, &m_preg, err_str, err_str_max_len);
266}
267
Enrico Granata0a3958e2011-07-02 00:25:22 +0000268bool
269RegularExpression::operator < (const RegularExpression& rhs) const
270{
271 return (m_re < rhs.m_re);
272}
Greg Clayton46747022010-10-10 23:55:27 +0000273