]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Core/RegularExpression.cpp
Merge ^/head r286694 through r286696.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / source / Core / RegularExpression.cpp
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 <string.h>
11 #include "lldb/Core/RegularExpression.h"
12 #include "llvm/ADT/StringRef.h"
13 #include "lldb/Core/Error.h"
14
15
16 //----------------------------------------------------------------------
17 // Enable enhanced mode if it is available. This allows for things like
18 // \d for digit, \s for space, and many more, but it isn't available
19 // everywhere.
20 //----------------------------------------------------------------------
21 #if defined(REG_ENHANCED)
22 #define DEFAULT_COMPILE_FLAGS (REG_ENHANCED|REG_EXTENDED)
23 #else
24 #define DEFAULT_COMPILE_FLAGS (REG_EXTENDED)
25 #endif
26
27 using namespace lldb_private;
28
29 //----------------------------------------------------------------------
30 // Default constructor
31 //----------------------------------------------------------------------
32 RegularExpression::RegularExpression() :
33     m_re(),
34     m_comp_err (1),
35     m_preg()
36 {
37     memset(&m_preg,0,sizeof(m_preg));
38 }
39
40 //----------------------------------------------------------------------
41 // Constructor that compiles "re" using "flags" and stores the
42 // resulting compiled regular expression into this object.
43 //----------------------------------------------------------------------
44 RegularExpression::RegularExpression(const char* re) :
45     m_re(),
46     m_comp_err (1),
47     m_preg()
48 {
49     memset(&m_preg,0,sizeof(m_preg));
50     Compile(re);
51 }
52
53 RegularExpression::RegularExpression(const RegularExpression &rhs)
54 {
55     memset(&m_preg,0,sizeof(m_preg));
56     Compile(rhs.GetText());
57 }
58
59 const RegularExpression &
60 RegularExpression::operator= (const RegularExpression &rhs)
61 {
62     if (&rhs != this)
63         Compile (rhs.GetText());
64     return *this;
65 }
66 //----------------------------------------------------------------------
67 // Destructor
68 //
69 // Any previously compiled regular expression contained in this
70 // object will be freed.
71 //----------------------------------------------------------------------
72 RegularExpression::~RegularExpression()
73 {
74     Free();
75 }
76
77 //----------------------------------------------------------------------
78 // Compile a regular expression using the supplied regular
79 // expression text and flags. The compiled regular expression lives
80 // in this object so that it can be readily used for regular
81 // expression matches. Execute() can be called after the regular
82 // expression is compiled. Any previously compiled regular
83 // expression contained in this object will be freed.
84 //
85 // RETURNS
86 //  True if the regular expression compiles successfully, false
87 //  otherwise.
88 //----------------------------------------------------------------------
89 bool
90 RegularExpression::Compile(const char* re)
91 {
92     Free();
93     
94     if (re && re[0])
95     {
96         m_re = re;
97         m_comp_err = ::regcomp (&m_preg, re, DEFAULT_COMPILE_FLAGS);
98     }
99     else
100     {
101         // No valid regular expression
102         m_comp_err = 1;
103     }
104
105     return m_comp_err == 0;
106 }
107
108 //----------------------------------------------------------------------
109 // Execute a regular expression match using the compiled regular
110 // expression that is already in this object against the match
111 // string "s". If any parens are used for regular expression
112 // matches "match_count" should indicate the number of regmatch_t
113 // values that are present in "match_ptr". The regular expression
114 // will be executed using the "execute_flags".
115 //---------------------------------------------------------------------
116 bool
117 RegularExpression::Execute (const char* s, Match *match) const
118 {
119     int err = 1;
120     if (s != NULL && m_comp_err == 0)
121     {
122         if (match)
123         {
124             err = ::regexec (&m_preg,
125                              s,
126                              match->GetSize(),
127                              match->GetData(),
128                              0);
129         }
130         else
131         {
132             err = ::regexec (&m_preg,
133                              s,
134                              0,
135                              NULL,
136                              0);
137         }
138     }
139     
140     if (err != 0)
141     {
142         // The regular expression didn't compile, so clear the matches
143         if (match)
144             match->Clear();
145         return false;
146     }
147     return true;
148 }
149
150 bool
151 RegularExpression::Match::GetMatchAtIndex (const char* s, uint32_t idx, std::string& match_str) const
152 {
153     llvm::StringRef match_str_ref;
154     if (GetMatchAtIndex(s, idx, match_str_ref))
155     {
156         match_str = std::move(match_str_ref.str());
157         return true;
158     }
159     return false;
160 }
161
162 bool
163 RegularExpression::Match::GetMatchAtIndex (const char* s, uint32_t idx, llvm::StringRef& match_str) const
164 {
165     if (idx < m_matches.size())
166     {
167         if (m_matches[idx].rm_eo == -1 && m_matches[idx].rm_so == -1)
168             return false;
169
170         if (m_matches[idx].rm_eo == m_matches[idx].rm_so)
171         {
172             // Matched the empty string...
173             match_str = llvm::StringRef();
174             return true;
175         }
176         else if (m_matches[idx].rm_eo > m_matches[idx].rm_so)
177         {
178             match_str = llvm::StringRef (s + m_matches[idx].rm_so, m_matches[idx].rm_eo - m_matches[idx].rm_so);
179             return true;
180         }
181     }
182     return false;
183 }
184
185 bool
186 RegularExpression::Match::GetMatchSpanningIndices (const char* s, uint32_t idx1, uint32_t idx2, llvm::StringRef& match_str) const
187 {
188     if (idx1 < m_matches.size() && idx2 < m_matches.size())
189     {
190         if (m_matches[idx1].rm_so == m_matches[idx2].rm_eo)
191         {
192             // Matched the empty string...
193             match_str = llvm::StringRef();
194             return true;
195         }
196         else if (m_matches[idx1].rm_so < m_matches[idx2].rm_eo)
197         {
198             match_str = llvm::StringRef (s + m_matches[idx1].rm_so, m_matches[idx2].rm_eo - m_matches[idx1].rm_so);
199             return true;
200         }
201     }
202     return false;
203 }
204
205
206 //----------------------------------------------------------------------
207 // Returns true if the regular expression compiled and is ready
208 // for execution.
209 //----------------------------------------------------------------------
210 bool
211 RegularExpression::IsValid () const
212 {
213     return m_comp_err == 0;
214 }
215
216 //----------------------------------------------------------------------
217 // Returns the text that was used to compile the current regular
218 // expression.
219 //----------------------------------------------------------------------
220 const char*
221 RegularExpression::GetText () const
222 {
223     if (m_re.empty())
224         return NULL;
225     return m_re.c_str();
226 }
227
228 //----------------------------------------------------------------------
229 // Free any contained compiled regular expressions.
230 //----------------------------------------------------------------------
231 void
232 RegularExpression::Free()
233 {
234     if (m_comp_err == 0)
235     {
236         m_re.clear();
237         regfree(&m_preg);
238         // Set a compile error since we no longer have a valid regex
239         m_comp_err = 1;
240     }
241 }
242
243 size_t
244 RegularExpression::GetErrorAsCString (char *err_str, size_t err_str_max_len) const
245 {
246     if (m_comp_err == 0)
247     {
248         if (err_str && err_str_max_len) 
249             *err_str = '\0';
250         return 0;
251     }
252     
253     return ::regerror (m_comp_err, &m_preg, err_str, err_str_max_len);
254 }
255
256 bool
257 RegularExpression::operator < (const RegularExpression& rhs) const
258 {
259     return (m_re < rhs.m_re);
260 }
261