diff options
Diffstat (limited to 'contrib/llvm/tools/lldb/source/Utility/RegularExpression.cpp')
-rw-r--r-- | contrib/llvm/tools/lldb/source/Utility/RegularExpression.cpp | 198 |
1 files changed, 198 insertions, 0 deletions
diff --git a/contrib/llvm/tools/lldb/source/Utility/RegularExpression.cpp b/contrib/llvm/tools/lldb/source/Utility/RegularExpression.cpp new file mode 100644 index 0000000..d58b315 --- /dev/null +++ b/contrib/llvm/tools/lldb/source/Utility/RegularExpression.cpp @@ -0,0 +1,198 @@ +//===-- 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); +} |