forked from OSchip/llvm-project
199 lines
6.8 KiB
C++
199 lines
6.8 KiB
C++
//===-- RegularExpression.cpp -----------------------------------*- C++ -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "lldb/Utility/RegularExpression.h"
|
|
|
|
#include "llvm/ADT/StringRef.h"
|
|
|
|
#include <string>
|
|
|
|
//----------------------------------------------------------------------
|
|
// Enable enhanced mode if it is available. This allows for things like
|
|
// \d for digit, \s for space, and many more, but it isn't available
|
|
// everywhere.
|
|
//----------------------------------------------------------------------
|
|
#if defined(REG_ENHANCED)
|
|
#define DEFAULT_COMPILE_FLAGS (REG_ENHANCED | REG_EXTENDED)
|
|
#else
|
|
#define DEFAULT_COMPILE_FLAGS (REG_EXTENDED)
|
|
#endif
|
|
|
|
using namespace lldb_private;
|
|
|
|
RegularExpression::RegularExpression() : m_re(), m_comp_err(1), m_preg() {
|
|
memset(&m_preg, 0, sizeof(m_preg));
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
// Constructor that compiles "re" using "flags" and stores the
|
|
// resulting compiled regular expression into this object.
|
|
//----------------------------------------------------------------------
|
|
RegularExpression::RegularExpression(llvm::StringRef str)
|
|
: m_re(), m_comp_err(1), m_preg() {
|
|
memset(&m_preg, 0, sizeof(m_preg));
|
|
Compile(str);
|
|
}
|
|
|
|
RegularExpression::RegularExpression(const RegularExpression &rhs) {
|
|
memset(&m_preg, 0, sizeof(m_preg));
|
|
Compile(rhs.GetText());
|
|
}
|
|
|
|
const RegularExpression &RegularExpression::
|
|
operator=(const RegularExpression &rhs) {
|
|
if (&rhs != this)
|
|
Compile(rhs.GetText());
|
|
return *this;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
// Destructor
|
|
//
|
|
// Any previously compiled regular expression contained in this
|
|
// object will be freed.
|
|
//----------------------------------------------------------------------
|
|
RegularExpression::~RegularExpression() { Free(); }
|
|
|
|
//----------------------------------------------------------------------
|
|
// Compile a regular expression using the supplied regular
|
|
// expression text and flags. The compiled regular expression lives
|
|
// in this object so that it can be readily used for regular
|
|
// expression matches. Execute() can be called after the regular
|
|
// expression is compiled. Any previously compiled regular
|
|
// expression contained in this object will be freed.
|
|
//
|
|
// RETURNS
|
|
// True if the regular expression compiles successfully, false
|
|
// otherwise.
|
|
//----------------------------------------------------------------------
|
|
bool RegularExpression::Compile(llvm::StringRef str) {
|
|
Free();
|
|
|
|
// regcomp() on darwin does not recognize "" as a valid regular expression, so
|
|
// we substitute it with an equivalent non-empty one.
|
|
m_re = str.empty() ? "()" : str;
|
|
m_comp_err = ::regcomp(&m_preg, m_re.c_str(), DEFAULT_COMPILE_FLAGS);
|
|
return m_comp_err == 0;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
// Execute a regular expression match using the compiled regular
|
|
// expression that is already in this object against the match
|
|
// string "s". If any parens are used for regular expression
|
|
// matches "match_count" should indicate the number of regmatch_t
|
|
// values that are present in "match_ptr". The regular expression
|
|
// will be executed using the "execute_flags".
|
|
//---------------------------------------------------------------------
|
|
bool RegularExpression::Execute(llvm::StringRef str, Match *match) const {
|
|
int err = 1;
|
|
if (m_comp_err == 0) {
|
|
// Argument to regexec must be null-terminated.
|
|
std::string reg_str = str;
|
|
if (match) {
|
|
err = ::regexec(&m_preg, reg_str.c_str(), match->GetSize(),
|
|
match->GetData(), 0);
|
|
} else {
|
|
err = ::regexec(&m_preg, reg_str.c_str(), 0, nullptr, 0);
|
|
}
|
|
}
|
|
|
|
if (err != 0) {
|
|
// The regular expression didn't compile, so clear the matches
|
|
if (match)
|
|
match->Clear();
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool RegularExpression::Match::GetMatchAtIndex(llvm::StringRef s, uint32_t idx,
|
|
std::string &match_str) const {
|
|
llvm::StringRef match_str_ref;
|
|
if (GetMatchAtIndex(s, idx, match_str_ref)) {
|
|
match_str = match_str_ref.str();
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool RegularExpression::Match::GetMatchAtIndex(
|
|
llvm::StringRef s, uint32_t idx, llvm::StringRef &match_str) const {
|
|
if (idx < m_matches.size()) {
|
|
if (m_matches[idx].rm_eo == -1 && m_matches[idx].rm_so == -1)
|
|
return false;
|
|
|
|
if (m_matches[idx].rm_eo == m_matches[idx].rm_so) {
|
|
// Matched the empty string...
|
|
match_str = llvm::StringRef();
|
|
return true;
|
|
} else if (m_matches[idx].rm_eo > m_matches[idx].rm_so) {
|
|
match_str = s.substr(m_matches[idx].rm_so,
|
|
m_matches[idx].rm_eo - m_matches[idx].rm_so);
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool RegularExpression::Match::GetMatchSpanningIndices(
|
|
llvm::StringRef s, uint32_t idx1, uint32_t idx2,
|
|
llvm::StringRef &match_str) const {
|
|
if (idx1 < m_matches.size() && idx2 < m_matches.size()) {
|
|
if (m_matches[idx1].rm_so == m_matches[idx2].rm_eo) {
|
|
// Matched the empty string...
|
|
match_str = llvm::StringRef();
|
|
return true;
|
|
} else if (m_matches[idx1].rm_so < m_matches[idx2].rm_eo) {
|
|
match_str = s.substr(m_matches[idx1].rm_so,
|
|
m_matches[idx2].rm_eo - m_matches[idx1].rm_so);
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
// Returns true if the regular expression compiled and is ready
|
|
// for execution.
|
|
//----------------------------------------------------------------------
|
|
bool RegularExpression::IsValid() const { return m_comp_err == 0; }
|
|
|
|
//----------------------------------------------------------------------
|
|
// Returns the text that was used to compile the current regular
|
|
// expression.
|
|
//----------------------------------------------------------------------
|
|
llvm::StringRef RegularExpression::GetText() const { return m_re; }
|
|
|
|
//----------------------------------------------------------------------
|
|
// Free any contained compiled regular expressions.
|
|
//----------------------------------------------------------------------
|
|
void RegularExpression::Free() {
|
|
if (m_comp_err == 0) {
|
|
m_re.clear();
|
|
regfree(&m_preg);
|
|
// Set a compile error since we no longer have a valid regex
|
|
m_comp_err = 1;
|
|
}
|
|
}
|
|
|
|
size_t RegularExpression::GetErrorAsCString(char *err_str,
|
|
size_t err_str_max_len) const {
|
|
if (m_comp_err == 0) {
|
|
if (err_str && err_str_max_len)
|
|
*err_str = '\0';
|
|
return 0;
|
|
}
|
|
|
|
return ::regerror(m_comp_err, &m_preg, err_str, err_str_max_len);
|
|
}
|
|
|
|
bool RegularExpression::operator<(const RegularExpression &rhs) const {
|
|
return (m_re < rhs.m_re);
|
|
}
|