]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Utility/RegularExpression.cpp
Merge ^/head r318560 through r318657.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / source / Utility / 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 "lldb/Utility/RegularExpression.h"
11
12 #include "llvm/ADT/StringRef.h"
13
14 #include <string>
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 RegularExpression::RegularExpression() : m_re(), m_comp_err(1), m_preg() {
30   memset(&m_preg, 0, sizeof(m_preg));
31 }
32
33 //----------------------------------------------------------------------
34 // Constructor that compiles "re" using "flags" and stores the
35 // resulting compiled regular expression into this object.
36 //----------------------------------------------------------------------
37 RegularExpression::RegularExpression(llvm::StringRef str)
38     : m_re(), m_comp_err(1), m_preg() {
39   memset(&m_preg, 0, sizeof(m_preg));
40   Compile(str);
41 }
42
43 RegularExpression::RegularExpression(const RegularExpression &rhs) {
44   memset(&m_preg, 0, sizeof(m_preg));
45   Compile(rhs.GetText());
46 }
47
48 const RegularExpression &RegularExpression::
49 operator=(const RegularExpression &rhs) {
50   if (&rhs != this)
51     Compile(rhs.GetText());
52   return *this;
53 }
54
55 //----------------------------------------------------------------------
56 // Destructor
57 //
58 // Any previously compiled regular expression contained in this
59 // object will be freed.
60 //----------------------------------------------------------------------
61 RegularExpression::~RegularExpression() { Free(); }
62
63 //----------------------------------------------------------------------
64 // Compile a regular expression using the supplied regular
65 // expression text and flags. The compiled regular expression lives
66 // in this object so that it can be readily used for regular
67 // expression matches. Execute() can be called after the regular
68 // expression is compiled. Any previously compiled regular
69 // expression contained in this object will be freed.
70 //
71 // RETURNS
72 //  True if the regular expression compiles successfully, false
73 //  otherwise.
74 //----------------------------------------------------------------------
75 bool RegularExpression::Compile(llvm::StringRef str) {
76   Free();
77
78   // regcomp() on darwin does not recognize "" as a valid regular expression, so
79   // we substitute it with an equivalent non-empty one.
80   m_re = str.empty() ? "()" : str;
81   m_comp_err = ::regcomp(&m_preg, m_re.c_str(), DEFAULT_COMPILE_FLAGS);
82   return m_comp_err == 0;
83 }
84
85 //----------------------------------------------------------------------
86 // Execute a regular expression match using the compiled regular
87 // expression that is already in this object against the match
88 // string "s". If any parens are used for regular expression
89 // matches "match_count" should indicate the number of regmatch_t
90 // values that are present in "match_ptr". The regular expression
91 // will be executed using the "execute_flags".
92 //---------------------------------------------------------------------
93 bool RegularExpression::Execute(llvm::StringRef str, Match *match) const {
94   int err = 1;
95   if (m_comp_err == 0) {
96     // Argument to regexec must be null-terminated.
97     std::string reg_str = str;
98     if (match) {
99       err = ::regexec(&m_preg, reg_str.c_str(), match->GetSize(),
100                       match->GetData(), 0);
101     } else {
102       err = ::regexec(&m_preg, reg_str.c_str(), 0, nullptr, 0);
103     }
104   }
105
106   if (err != 0) {
107     // The regular expression didn't compile, so clear the matches
108     if (match)
109       match->Clear();
110     return false;
111   }
112   return true;
113 }
114
115 bool RegularExpression::Match::GetMatchAtIndex(llvm::StringRef s, uint32_t idx,
116                                                std::string &match_str) const {
117   llvm::StringRef match_str_ref;
118   if (GetMatchAtIndex(s, idx, match_str_ref)) {
119     match_str = match_str_ref.str();
120     return true;
121   }
122   return false;
123 }
124
125 bool RegularExpression::Match::GetMatchAtIndex(
126     llvm::StringRef s, uint32_t idx, llvm::StringRef &match_str) const {
127   if (idx < m_matches.size()) {
128     if (m_matches[idx].rm_eo == -1 && m_matches[idx].rm_so == -1)
129       return false;
130
131     if (m_matches[idx].rm_eo == m_matches[idx].rm_so) {
132       // Matched the empty string...
133       match_str = llvm::StringRef();
134       return true;
135     } else if (m_matches[idx].rm_eo > m_matches[idx].rm_so) {
136       match_str = s.substr(m_matches[idx].rm_so,
137                            m_matches[idx].rm_eo - m_matches[idx].rm_so);
138       return true;
139     }
140   }
141   return false;
142 }
143
144 bool RegularExpression::Match::GetMatchSpanningIndices(
145     llvm::StringRef s, uint32_t idx1, uint32_t idx2,
146     llvm::StringRef &match_str) const {
147   if (idx1 < m_matches.size() && idx2 < m_matches.size()) {
148     if (m_matches[idx1].rm_so == m_matches[idx2].rm_eo) {
149       // Matched the empty string...
150       match_str = llvm::StringRef();
151       return true;
152     } else if (m_matches[idx1].rm_so < m_matches[idx2].rm_eo) {
153       match_str = s.substr(m_matches[idx1].rm_so,
154                            m_matches[idx2].rm_eo - m_matches[idx1].rm_so);
155       return true;
156     }
157   }
158   return false;
159 }
160
161 //----------------------------------------------------------------------
162 // Returns true if the regular expression compiled and is ready
163 // for execution.
164 //----------------------------------------------------------------------
165 bool RegularExpression::IsValid() const { return m_comp_err == 0; }
166
167 //----------------------------------------------------------------------
168 // Returns the text that was used to compile the current regular
169 // expression.
170 //----------------------------------------------------------------------
171 llvm::StringRef RegularExpression::GetText() const { return m_re; }
172
173 //----------------------------------------------------------------------
174 // Free any contained compiled regular expressions.
175 //----------------------------------------------------------------------
176 void RegularExpression::Free() {
177   if (m_comp_err == 0) {
178     m_re.clear();
179     regfree(&m_preg);
180     // Set a compile error since we no longer have a valid regex
181     m_comp_err = 1;
182   }
183 }
184
185 size_t RegularExpression::GetErrorAsCString(char *err_str,
186                                             size_t err_str_max_len) const {
187   if (m_comp_err == 0) {
188     if (err_str && err_str_max_len)
189       *err_str = '\0';
190     return 0;
191   }
192
193   return ::regerror(m_comp_err, &m_preg, err_str, err_str_max_len);
194 }
195
196 bool RegularExpression::operator<(const RegularExpression &rhs) const {
197   return (m_re < rhs.m_re);
198 }