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