1 //===-- 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"
11 #include "llvm/ADT/StringRef.h"
12 #include <string.h>
13
14 using namespace lldb_private;
15
16 //----------------------------------------------------------------------
17 // Default constructor
18 //----------------------------------------------------------------------
RegularExpression()19 RegularExpression::RegularExpression() :
20 m_re(),
21 m_comp_err (1),
22 m_preg(),
23 m_compile_flags(REG_EXTENDED)
24 {
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 //----------------------------------------------------------------------
RegularExpression(const char * re,int flags)32 RegularExpression::RegularExpression(const char* re, int flags) :
33 m_re(),
34 m_comp_err (1),
35 m_preg(),
36 m_compile_flags(flags)
37 {
38 memset(&m_preg,0,sizeof(m_preg));
39 Compile(re);
40 }
41
42 //----------------------------------------------------------------------
43 // Constructor that compiles "re" using "flags" and stores the
44 // resulting compiled regular expression into this object.
45 //----------------------------------------------------------------------
RegularExpression(const char * re)46 RegularExpression::RegularExpression(const char* re) :
47 m_re(),
48 m_comp_err (1),
49 m_preg(),
50 m_compile_flags(REG_EXTENDED)
51 {
52 memset(&m_preg,0,sizeof(m_preg));
53 Compile(re);
54 }
55
RegularExpression(const RegularExpression & rhs)56 RegularExpression::RegularExpression(const RegularExpression &rhs)
57 {
58 memset(&m_preg,0,sizeof(m_preg));
59 Compile(rhs.GetText(), rhs.GetCompileFlags());
60 }
61
62 const RegularExpression &
operator =(const RegularExpression & rhs)63 RegularExpression::operator= (const RegularExpression &rhs)
64 {
65 if (&rhs != this)
66 {
67 Compile (rhs.GetText(), rhs.GetCompileFlags());
68 }
69 return *this;
70 }
71 //----------------------------------------------------------------------
72 // Destructor
73 //
74 // Any previosuly compiled regular expression contained in this
75 // object will be freed.
76 //----------------------------------------------------------------------
~RegularExpression()77 RegularExpression::~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 //----------------------------------------------------------------------
94 bool
Compile(const char * re)95 RegularExpression::Compile(const char* re)
96 {
97 return Compile (re, m_compile_flags);
98 }
99
100 bool
Compile(const char * re,int flags)101 RegularExpression::Compile(const char* re, int flags)
102 {
103 Free();
104 m_compile_flags = flags;
105
106 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".
127 //---------------------------------------------------------------------
128 bool
Execute(const char * s,Match * match,int execute_flags) const129 RegularExpression::Execute(const char* s, Match *match, int execute_flags) const
130 {
131 int err = 1;
132 if (s != NULL && m_comp_err == 0)
133 {
134 if (match)
135 {
136 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);
149 }
150 }
151
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;
160 }
161
162 bool
GetMatchAtIndex(const char * s,uint32_t idx,std::string & match_str) const163 RegularExpression::Match::GetMatchAtIndex (const char* s, uint32_t idx, std::string& match_str) const
164 {
165 if (idx < m_matches.size())
166 {
167 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 }
179 }
180 return false;
181 }
182
183 bool
GetMatchAtIndex(const char * s,uint32_t idx,llvm::StringRef & match_str) const184 RegularExpression::Match::GetMatchAtIndex (const char* s, uint32_t idx, llvm::StringRef& match_str) const
185 {
186 if (idx < m_matches.size())
187 {
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
203 bool
GetMatchSpanningIndices(const char * s,uint32_t idx1,uint32_t idx2,llvm::StringRef & match_str) const204 RegularExpression::Match::GetMatchSpanningIndices (const char* s, uint32_t idx1, uint32_t idx2, llvm::StringRef& match_str) const
205 {
206 if (idx1 < m_matches.size() && idx2 < m_matches.size())
207 {
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
223
224 //----------------------------------------------------------------------
225 // Returns true if the regular expression compiled and is ready
226 // for execution.
227 //----------------------------------------------------------------------
228 bool
IsValid() const229 RegularExpression::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 //----------------------------------------------------------------------
238 const char*
GetText() const239 RegularExpression::GetText () const
240 {
241 if (m_re.empty())
242 return NULL;
243 return m_re.c_str();
244 }
245
246 //----------------------------------------------------------------------
247 // Free any contained compiled regular expressions.
248 //----------------------------------------------------------------------
249 void
Free()250 RegularExpression::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 }
260
261 size_t
GetErrorAsCString(char * err_str,size_t err_str_max_len) const262 RegularExpression::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
274 bool
operator <(const RegularExpression & rhs) const275 RegularExpression::operator < (const RegularExpression& rhs) const
276 {
277 return (m_re < rhs.m_re);
278 }
279
280