Home | History | Annotate | Download | only in Core
      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 
     14 using namespace lldb_private;
     15 
     16 //----------------------------------------------------------------------
     17 // Default constructor
     18 //----------------------------------------------------------------------
     19 RegularExpression::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 //----------------------------------------------------------------------
     32 RegularExpression::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 //----------------------------------------------------------------------
     46 RegularExpression::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 
     56 RegularExpression::RegularExpression(const RegularExpression &rhs)
     57 {
     58     memset(&m_preg,0,sizeof(m_preg));
     59     Compile(rhs.GetText(), rhs.GetCompileFlags());
     60 }
     61 
     62 const RegularExpression &
     63 RegularExpression::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 //----------------------------------------------------------------------
     77 RegularExpression::~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 //----------------------------------------------------------------------
     94 bool
     95 RegularExpression::Compile(const char* re)
     96 {
     97     return Compile (re, m_compile_flags);
     98 }
     99 
    100 bool
    101 RegularExpression::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 //---------------------------------------------------------------------
    128 bool
    129 RegularExpression::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 
    162 bool
    163 RegularExpression::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 
    183 bool
    184 RegularExpression::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 
    203 bool
    204 RegularExpression::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 //----------------------------------------------------------------------
    228 bool
    229 RegularExpression::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 //----------------------------------------------------------------------
    238 const char*
    239 RegularExpression::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 //----------------------------------------------------------------------
    249 void
    250 RegularExpression::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 
    261 size_t
    262 RegularExpression::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 
    274 bool
    275 RegularExpression::operator < (const RegularExpression& rhs) const
    276 {
    277     return (m_re < rhs.m_re);
    278 }
    279 
    280