<commit_before>//===-- 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/Core/RegularExpression.h"
#include "llvm/ADT/StringRef.h"
#include <string.h>

using namespace lldb_private;

//----------------------------------------------------------------------
// Default constructor
//----------------------------------------------------------------------
RegularExpression::RegularExpression() :
    m_re(),
    m_comp_err (1),
    m_preg(),
    m_compile_flags(REG_EXTENDED)
{
    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(const char* re, int flags) :
    m_re(),
    m_comp_err (1),
    m_preg(),
    m_compile_flags(flags)
{
    memset(&m_preg,0,sizeof(m_preg));
    Compile(re);
}

//----------------------------------------------------------------------
// Constructor that compiles "re" using "flags" and stores the
// resulting compiled regular expression into this object.
//----------------------------------------------------------------------
RegularExpression::RegularExpression(const char* re) :
    m_re(),
    m_comp_err (1),
    m_preg(),
    m_compile_flags(REG_EXTENDED)
{
    memset(&m_preg,0,sizeof(m_preg));
    Compile(re);
}

RegularExpression::RegularExpression(const RegularExpression &rhs)
{
    memset(&m_preg,0,sizeof(m_preg));
    Compile(rhs.GetText(), rhs.GetCompileFlags());
}

const RegularExpression &
RegularExpression::operator= (const RegularExpression &rhs)
{
    if (&rhs != this)
    {
        Compile (rhs.GetText(), rhs.GetCompileFlags());
    }
    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(const char* re)
{
    return Compile (re, m_compile_flags);
}

bool
RegularExpression::Compile(const char* re, int flags)
{
    Free();
    m_compile_flags = flags;
    
    if (re && re[0])
    {
        m_re = re;
        m_comp_err = ::regcomp (&m_preg, re, flags);
    }
    else
    {
        // No valid regular expression
        m_comp_err = 1;
    }

    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(const char* s, Match *match, int execute_flags) const
{
    int err = 1;
    if (s != NULL && m_comp_err == 0)
    {
        if (match)
        {
            err = ::regexec (&m_preg,
                             s,
                             match->GetSize(),
                             match->GetData(),
                             execute_flags);
        }
        else
        {
            err = ::regexec (&m_preg,
                             s,
                             0,
                             NULL,
                             execute_flags);
        }
    }
    
    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 (const char* s, uint32_t idx, std::string& match_str) const
{
    if (idx < m_matches.size())
    {
        if (m_matches[idx].rm_eo == m_matches[idx].rm_so)
        {
            // Matched the empty string...
            match_str.clear();
            return true;
        }
        else if (m_matches[idx].rm_eo > m_matches[idx].rm_so)
        {
            match_str.assign (s + m_matches[idx].rm_so,
                              m_matches[idx].rm_eo - m_matches[idx].rm_so);
            return true;
        }
    }
    return false;
}

bool
RegularExpression::Match::GetMatchAtIndex (const char* s, uint32_t idx, llvm::StringRef& match_str) const
{
    if (idx < m_matches.size())
    {
        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 = llvm::StringRef (s + m_matches[idx].rm_so, m_matches[idx].rm_eo - m_matches[idx].rm_so);
            return true;
        }
    }
    return false;
}

bool
RegularExpression::Match::GetMatchSpanningIndices (const char* s, uint32_t idx1, uint32_t idx2, llvm::StringRef& match_str) const
{<commit_msg>Re-use the GetMatchAtIndex() that uses the StringRef to avoid code duplication and properly detect when a capture is invalid and return false.<commit_after>//===-- 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/Core/RegularExpression.h"
#include "llvm/ADT/StringRef.h"
#include <string.h>

using namespace lldb_private;

//----------------------------------------------------------------------
// Default constructor
//----------------------------------------------------------------------
RegularExpression::RegularExpression() :
    m_re(),
    m_comp_err (1),
    m_preg(),
    m_compile_flags(REG_EXTENDED)
{
    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(const char* re, int flags) :
    m_re(),
    m_comp_err (1),
    m_preg(),
    m_compile_flags(flags)
{
    memset(&m_preg,0,sizeof(m_preg));
    Compile(re);
}

//----------------------------------------------------------------------
// Constructor that compiles "re" using "flags" and stores the
// resulting compiled regular expression into this object.
//----------------------------------------------------------------------
RegularExpression::RegularExpression(const char* re) :
    m_re(),
    m_comp_err (1),
    m_preg(),
    m_compile_flags(REG_EXTENDED)
{
    memset(&m_preg,0,sizeof(m_preg));
    Compile(re);
}

RegularExpression::RegularExpression(const RegularExpression &rhs)
{
    memset(&m_preg,0,sizeof(m_preg));
    Compile(rhs.GetText(), rhs.GetCompileFlags());
}

const RegularExpression &
RegularExpression::operator= (const RegularExpression &rhs)
{
    if (&rhs != this)
    {
        Compile (rhs.GetText(), rhs.GetCompileFlags());
    }
    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(const char* re)
{
    return Compile (re, m_compile_flags);
}

bool
RegularExpression::Compile(const char* re, int flags)
{
    Free();
    m_compile_flags = flags;
    
    if (re && re[0])
    {
        m_re = re;
        m_comp_err = ::regcomp (&m_preg, re, flags);
    }
    else
    {
        // No valid regular expression
        m_comp_err = 1;
    }

    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(const char* s, Match *match, int execute_flags) const
{
    int err = 1;
    if (s != NULL && m_comp_err == 0)
    {
        if (match)
        {
            err = ::regexec (&m_preg,
                             s,
                             match->GetSize(),
                             match->GetData(),
                             execute_flags);
        }
        else
        {
            err = ::regexec (&m_preg,
                             s,
                             0,
                             NULL,
                             execute_flags);
        }
    }
    
    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 (const char* s, uint32_t idx, std::string& match_str) const
{
    llvm::StringRef match_str_ref;
    if (GetMatchAtIndex(s, idx, match_str_ref))
    {
        match_str = std::move(match_str_ref.str());
        return true;
    }
    return false;
}

bool
RegularExpression::Match::GetMatchAtIndex (const char* 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 = llvm::StringRef (s + m_matches[idx].rm_so, m_matches[idx].rm_eo - m_matches[idx].rm_so);
            return true;
        }
    }
    return false;
}

bool
RegularExpression::Match::GetMatchSpanningIndices (const char* s, uint32_t idx1, uint32_t idx2, llvm::StringRef& match_str) const
{
{'fraction_non_alphanumeric': 0.25548770424162404, 'fraction_numerical': 0.00412609341475491, 'mean_word_length': 1.4448254992939278, 'pattern_counts': {'":': 0, '<': 8, '<?xml version=': 0, '>': 14, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6625688', 'n_tokens_mistral': 3179, 'n_tokens_neox': 3114, 'n_words': 856}