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 14using namespace lldb_private; 15 16//---------------------------------------------------------------------- 17// Default constructor 18//---------------------------------------------------------------------- 19RegularExpression::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//---------------------------------------------------------------------- 32RegularExpression::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//---------------------------------------------------------------------- 46RegularExpression::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 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//---------------------------------------------------------------------- 72// Destructor 73// 74// Any previosuly compiled regular expression contained in this 75// object will be freed. 76//---------------------------------------------------------------------- 77RegularExpression::~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//---------------------------------------------------------------------- 94bool 95RegularExpression::Compile(const char* re) 96{ 97 return Compile (re, m_compile_flags); 98} 99 100bool 101RegularExpression::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//--------------------------------------------------------------------- 128bool 129RegularExpression::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 162bool 163RegularExpression::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 183bool 184RegularExpression::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 203bool 204RegularExpression::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//---------------------------------------------------------------------- 228bool 229RegularExpression::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//---------------------------------------------------------------------- 238const char* 239RegularExpression::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//---------------------------------------------------------------------- 249void 250RegularExpression::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 261size_t 262RegularExpression::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 274bool 275RegularExpression::operator < (const RegularExpression& rhs) const 276{ 277 return (m_re < rhs.m_re); 278} 279 280