forked from boostorg/regex
Almost complete POSIX regex support now...
[SVN r22624]
This commit is contained in:
1 parent
38b58f2007
commit
50b5391c8f
21 files changed
+1446
-605
No files matched your search
@@ -60,6 +60,7 @@
|
||||
# include <boost/throw_exception.hpp>
|
||||
# include <boost/scoped_ptr.hpp>
|
||||
# include <boost/shared_ptr.hpp>
|
||||
# include <boost/mpl/bool_fwd.hpp>
|
||||
# ifndef BOOST_NO_STD_LOCALE
|
||||
# include <locale>
|
||||
# endif
|
||||
|
||||
@@ -154,6 +154,11 @@ public:
|
||||
{
|
||||
return this->m_can_be_null;
|
||||
}
|
||||
const regex_data<charT, traits>& get_data()const
|
||||
{
|
||||
basic_regex_implementation<charT, traits> const* p = this;
|
||||
return *static_cast<const regex_data<charT, traits>*>(p);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace re_detail
|
||||
@@ -470,6 +475,11 @@ public:
|
||||
assert(m_pimpl.get());
|
||||
return m_pimpl->can_be_null();
|
||||
}
|
||||
const re_detail::regex_data<charT, traits>& get_data()const
|
||||
{
|
||||
assert(m_pimpl.get());
|
||||
return m_pimpl->get_data();
|
||||
}
|
||||
|
||||
private:
|
||||
shared_ptr<re_detail::basic_regex_implementation<charT, traits> > m_pimpl;
|
||||
|
||||
@@ -28,6 +28,106 @@ namespace boost{
|
||||
|
||||
namespace re_detail{
|
||||
|
||||
template <class charT>
|
||||
struct digraph : public std::pair<charT, charT>
|
||||
{
|
||||
digraph(charT c1 = 0, charT c2 = 0) : std::pair<charT, charT>(c1, c2){}
|
||||
digraph(const std::basic_string<charT>& s) : std::pair<charT, charT>()
|
||||
{
|
||||
BOOST_ASSERT(s.size() <= 2);
|
||||
BOOST_ASSERT(s.size());
|
||||
this->first = s[0];
|
||||
this->second = (s.size() > 1) ? s[1] : 0;
|
||||
}
|
||||
};
|
||||
|
||||
template <class charT, class traits>
|
||||
class basic_char_set
|
||||
{
|
||||
public:
|
||||
typedef digraph<charT> digraph_type;
|
||||
typedef std::basic_string<charT> string_type;
|
||||
typedef typename traits::char_class_type mask_type;
|
||||
|
||||
basic_char_set()
|
||||
{
|
||||
m_negate = false;
|
||||
m_has_digraphs = false;
|
||||
m_classes = 0;
|
||||
m_empty = true;
|
||||
}
|
||||
|
||||
void add_single(const digraph_type& s)
|
||||
{
|
||||
m_singles.push_back(s);
|
||||
if(s.second)
|
||||
m_has_digraphs = true;
|
||||
m_empty = false;
|
||||
}
|
||||
void add_range(const digraph_type& first, const digraph_type& end)
|
||||
{
|
||||
m_ranges.push_back(first);
|
||||
m_ranges.push_back(end);
|
||||
if(first.second || end.second)
|
||||
m_has_digraphs = true;
|
||||
m_empty = false;
|
||||
}
|
||||
void add_class(mask_type m)
|
||||
{
|
||||
m_classes |= m;
|
||||
m_empty = false;
|
||||
}
|
||||
void negate()
|
||||
{
|
||||
m_negate = true;
|
||||
m_empty = false;
|
||||
}
|
||||
|
||||
//
|
||||
// accessor functions:
|
||||
//
|
||||
bool has_digraphs()const
|
||||
{
|
||||
return m_has_digraphs;
|
||||
}
|
||||
bool is_negated()const
|
||||
{
|
||||
return m_negate;
|
||||
}
|
||||
typedef typename std::vector<digraph_type>::const_iterator list_iterator;
|
||||
list_iterator singles_begin()const
|
||||
{
|
||||
return m_singles.begin();
|
||||
}
|
||||
list_iterator singles_end()const
|
||||
{
|
||||
return m_singles.end();
|
||||
}
|
||||
list_iterator ranges_begin()const
|
||||
{
|
||||
return m_ranges.begin();
|
||||
}
|
||||
list_iterator ranges_end()const
|
||||
{
|
||||
return m_ranges.end();
|
||||
}
|
||||
mask_type classes()const
|
||||
{
|
||||
return m_classes;
|
||||
}
|
||||
bool empty()const
|
||||
{
|
||||
return m_empty;
|
||||
}
|
||||
private:
|
||||
std::vector<digraph_type> m_singles; // a list of single characters to match
|
||||
std::vector<digraph_type> m_ranges; // a list of end points of our ranges
|
||||
bool m_negate; // true if the set is to be negated
|
||||
bool m_has_digraphs; // true if we have digraphs present
|
||||
mask_type m_classes; // character classes to match
|
||||
bool m_empty; // whether we've added anything yet
|
||||
};
|
||||
|
||||
template <class charT, class traits>
|
||||
class basic_regex_creator
|
||||
{
|
||||
@@ -54,38 +154,63 @@ public:
|
||||
m_pdata->m_flags = flags;
|
||||
m_icase = flags & regex_constants::icase;
|
||||
}
|
||||
regbase::flag_type flags()
|
||||
{
|
||||
return m_pdata->m_flags;
|
||||
}
|
||||
re_syntax_base* append_state(syntax_element_type t, std::size_t s = sizeof(re_syntax_base));
|
||||
re_syntax_base* insert_state(std::ptrdiff_t pos, syntax_element_type t, std::size_t s = sizeof(re_syntax_base));
|
||||
re_literal* append_literal(charT c);
|
||||
re_syntax_base* append_set(const basic_char_set<charT, traits>& char_set);
|
||||
re_syntax_base* append_set(const basic_char_set<charT, traits>& char_set, mpl::false_*);
|
||||
re_syntax_base* append_set(const basic_char_set<charT, traits>& char_set, mpl::true_*);
|
||||
void finalize(const charT* p1, const charT* p2);
|
||||
protected:
|
||||
regex_data<charT, traits>* m_pdata; // pointer to the basic_regex_data struct we are filling in
|
||||
const traits& m_traits; // convenience reference to traits class
|
||||
re_syntax_base* m_last_state;// the last state we added
|
||||
bool m_icase; // true for case insensitive matches
|
||||
typename traits::char_class_type m_word_mask; // mask used to determine if a character is a word character
|
||||
typename traits::char_class_type m_mask_space; // mask used to determine if a character is a word character
|
||||
regex_data<charT, traits>* m_pdata; // pointer to the basic_regex_data struct we are filling in
|
||||
const traits& m_traits; // convenience reference to traits class
|
||||
re_syntax_base* m_last_state; // the last state we added
|
||||
bool m_icase; // true for case insensitive matches
|
||||
unsigned m_repeater_id; // the id of the next repeater
|
||||
unsigned m_backrefs; // bitmask of permitted backrefs
|
||||
boost::uintmax_t m_bad_repeats; // bitmask of repeats we can't deduce a startmap for;
|
||||
typename traits::char_class_type m_word_mask; // mask used to determine if a character is a word character
|
||||
typename traits::char_class_type m_mask_space; // mask used to determine if a character is a word character
|
||||
typename traits::char_class_type m_lower_mask; // mask used to determine if a character is a lowercase character
|
||||
typename traits::char_class_type m_upper_mask; // mask used to determine if a character is an uppercase character
|
||||
typename traits::char_class_type m_alpha_mask; // mask used to determine if a character is an alphabetic character
|
||||
private:
|
||||
basic_regex_creator& operator=(const basic_regex_creator&);
|
||||
basic_regex_creator(const basic_regex_creator&);
|
||||
|
||||
void fixup_pointers(re_syntax_base* state);
|
||||
void create_startmaps(re_syntax_base* state);
|
||||
void create_startmap(re_syntax_base* state, unsigned char* map, unsigned int* pnull, unsigned char mask, re_syntax_base* terminal);
|
||||
void create_startmap(re_syntax_base* state, unsigned char* map, unsigned int* pnull, unsigned char mask);
|
||||
unsigned get_restart_type(re_syntax_base* state);
|
||||
void set_all_masks(unsigned char* bits, unsigned char);
|
||||
bool is_bad_repeat(re_syntax_base* pt);
|
||||
void set_bad_repeat(re_syntax_base* pt);
|
||||
};
|
||||
|
||||
template <class charT, class traits>
|
||||
basic_regex_creator<charT, traits>::basic_regex_creator(regex_data<charT, traits>* data)
|
||||
: m_pdata(data), m_traits(data->m_traits), m_last_state(0)
|
||||
: m_pdata(data), m_traits(data->m_traits), m_last_state(0), m_repeater_id(0), m_backrefs(0)
|
||||
{
|
||||
m_pdata->m_data.clear();
|
||||
static const charT w = 'w';
|
||||
static const charT s = 's';
|
||||
static const charT l[] = { 'l', 'o', 'w', 'e', 'r', };
|
||||
static const charT u[] = { 'u', 'p', 'p', 'e', 'r', };
|
||||
static const charT a[] = { 'a', 'l', 'p', 'h', 'a', };
|
||||
m_word_mask = m_traits.lookup_classname(&w, &w +1);
|
||||
m_mask_space = m_traits.lookup_classname(&s, &s +1);
|
||||
m_lower_mask = m_traits.lookup_classname(l, l + 5);
|
||||
m_upper_mask = m_traits.lookup_classname(u, u + 5);
|
||||
m_alpha_mask = m_traits.lookup_classname(a, a + 5);
|
||||
BOOST_ASSERT(m_word_mask);
|
||||
BOOST_ASSERT(m_mask_space);
|
||||
BOOST_ASSERT(m_lower_mask);
|
||||
BOOST_ASSERT(m_upper_mask);
|
||||
BOOST_ASSERT(m_alpha_mask);
|
||||
}
|
||||
|
||||
template <class charT, class traits>
|
||||
@@ -148,6 +273,213 @@ re_literal* basic_regex_creator<charT, traits>::append_literal(charT c)
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class charT, class traits>
|
||||
inline re_syntax_base* basic_regex_creator<charT, traits>::append_set(
|
||||
const basic_char_set<charT, traits>& char_set)
|
||||
{
|
||||
typedef mpl::bool_<sizeof(charT) == 1> truth_type;
|
||||
return char_set.has_digraphs()
|
||||
? append_set(char_set, static_cast<mpl::false_*>(0))
|
||||
: append_set(char_set, static_cast<truth_type*>(0));
|
||||
}
|
||||
|
||||
template <class charT, class traits>
|
||||
re_syntax_base* basic_regex_creator<charT, traits>::append_set(
|
||||
const basic_char_set<charT, traits>& char_set, mpl::false_*)
|
||||
{
|
||||
typedef std::basic_string<charT> string_type;
|
||||
typedef typename basic_char_set<charT, traits>::list_iterator item_iterator;
|
||||
typedef typename traits::char_class_type mask_type;
|
||||
|
||||
re_set_long<mask_type>* result = static_cast<re_set_long<mask_type>*>(append_state(syntax_element_long_set, sizeof(re_set_long<mask_type>)));
|
||||
//
|
||||
// fill in the basics:
|
||||
//
|
||||
result->csingles = static_cast<unsigned int>(std::distance(char_set.singles_begin(), char_set.singles_end()));
|
||||
result->cranges = static_cast<unsigned int>(std::distance(char_set.ranges_begin(), char_set.ranges_end())) / 2;
|
||||
result->cequivalents = 0;
|
||||
result->cclasses = char_set.classes();
|
||||
if(flags() & regbase::icase)
|
||||
{
|
||||
// adjust classes as needed:
|
||||
if(((result->cclasses & m_lower_mask) == m_lower_mask) || ((result->cclasses & m_upper_mask) == m_upper_mask))
|
||||
result->cclasses |= m_alpha_mask;
|
||||
}
|
||||
|
||||
result->isnot = char_set.is_negated();
|
||||
result->singleton = !char_set.has_digraphs();
|
||||
//
|
||||
// remember where the state is for later:
|
||||
//
|
||||
std::ptrdiff_t offset = getoffset(result);
|
||||
//
|
||||
// now extend with all the singles:
|
||||
//
|
||||
item_iterator first, last;
|
||||
first = char_set.singles_begin();
|
||||
last = char_set.singles_end();
|
||||
while(first != last)
|
||||
{
|
||||
charT* p = static_cast<charT*>(this->m_pdata->m_data.extend(sizeof(charT) * (first->second ? 3 : 2)));
|
||||
p[0] = m_traits.translate(first->first, m_icase);
|
||||
if(first->second)
|
||||
{
|
||||
p[1] = m_traits.translate(first->second, m_icase);
|
||||
p[2] = 0;
|
||||
}
|
||||
else
|
||||
p[1] = 0;
|
||||
++first;
|
||||
}
|
||||
//
|
||||
// now extend with all the ranges:
|
||||
//
|
||||
first = char_set.ranges_begin();
|
||||
last = char_set.ranges_end();
|
||||
while(first != last)
|
||||
{
|
||||
// first grab the endpoints of the range:
|
||||
digraph<charT> c1 = *first;
|
||||
c1.first = this->m_traits.translate(c1.first, this->m_icase);
|
||||
c1.second = this->m_traits.translate(c1.second, this->m_icase);
|
||||
++first;
|
||||
digraph<charT> c2 = *first;
|
||||
c2.first = this->m_traits.translate(c2.first, this->m_icase);
|
||||
c2.second = this->m_traits.translate(c2.second, this->m_icase);
|
||||
++first;
|
||||
string_type s1, s2;
|
||||
// different actions now depending upon whether collation is turned on:
|
||||
if(flags() & regex_constants::collate)
|
||||
{
|
||||
// we need to transform our range into sort keys:
|
||||
s1 = this->m_traits.transform(&c1.first, (c1.second ? &c1.second +1 : &c1.second));
|
||||
s2 = this->m_traits.transform(&c2.first, (c2.second ? &c2.second +1 : &c2.second));
|
||||
}
|
||||
else
|
||||
{
|
||||
if(c1.second)
|
||||
s1 = string_type(&c1.first, &c1.second+1);
|
||||
else
|
||||
s1 = string_type(1, c1.first);
|
||||
if(c2.second)
|
||||
s2 = string_type(&c2.first, &c2.second+1);
|
||||
else
|
||||
s2 = string_type(1, c2.first);
|
||||
}
|
||||
if(s1 > s2)
|
||||
{
|
||||
// Oops error:
|
||||
return 0;
|
||||
}
|
||||
charT* p = static_cast<charT*>(this->m_pdata->m_data.extend(sizeof(charT) * (s1.size() + s2.size() + 2) ) );
|
||||
std::memcpy(p, s1.c_str(), sizeof(charT) * (s1.size() + 1));
|
||||
p += s1.size() + 1;
|
||||
std::memcpy(p, s2.c_str(), sizeof(charT) * (s2.size() + 1));
|
||||
}
|
||||
//
|
||||
// finally reset the address of our last state:
|
||||
//
|
||||
m_last_state = result = static_cast<re_set_long<mask_type>*>(getaddress(offset));
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class charT, class traits>
|
||||
re_syntax_base* basic_regex_creator<charT, traits>::append_set(
|
||||
const basic_char_set<charT, traits>& char_set, mpl::true_*)
|
||||
{
|
||||
typedef std::basic_string<charT> string_type;
|
||||
typedef typename basic_char_set<charT, traits>::list_iterator item_iterator;
|
||||
|
||||
re_set* result = static_cast<re_set*>(append_state(syntax_element_set, sizeof(re_set)));
|
||||
bool negate = char_set.is_negated();
|
||||
std::memset(result->_map, 0, sizeof(result->_map));
|
||||
//
|
||||
// handle singles first:
|
||||
//
|
||||
item_iterator first, last;
|
||||
first = char_set.singles_begin();
|
||||
last = char_set.singles_end();
|
||||
while(first != last)
|
||||
{
|
||||
for(unsigned int i = 0; i < (1 << CHAR_BIT); ++i)
|
||||
{
|
||||
if(this->m_traits.translate(static_cast<charT>(i), this->m_icase)
|
||||
== this->m_traits.translate(first->first, this->m_icase))
|
||||
result->_map[i] = true;
|
||||
}
|
||||
++first;
|
||||
}
|
||||
//
|
||||
// OK now handle ranges:
|
||||
//
|
||||
first = char_set.ranges_begin();
|
||||
last = char_set.ranges_end();
|
||||
while(first != last)
|
||||
{
|
||||
// first grab the endpoints of the range:
|
||||
charT c1 = this->m_traits.translate(first->first, this->m_icase);
|
||||
++first;
|
||||
charT c2 = this->m_traits.translate(first->first, this->m_icase);
|
||||
++first;
|
||||
// different actions now depending upon whether collation is turned on:
|
||||
if(flags() & regex_constants::collate)
|
||||
{
|
||||
// we need to transform our range into sort keys:
|
||||
string_type s1 = this->m_traits.transform(&c1, &c1 +1);
|
||||
string_type s2 = this->m_traits.transform(&c2, &c2 +1);
|
||||
if(s1 > s2)
|
||||
{
|
||||
// Oops error:
|
||||
return 0;
|
||||
}
|
||||
for(unsigned i = 0; i < (1u << CHAR_BIT); ++i)
|
||||
{
|
||||
charT c3 = static_cast<charT>(i);
|
||||
string_type s3 = this->m_traits.transform(&c3, &c3 +1);
|
||||
if((s1 <= s3) && (s3 <= s2))
|
||||
result->_map[i] = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(c1 > c2)
|
||||
{
|
||||
// Oops error:
|
||||
return 0;
|
||||
}
|
||||
// everything in range matches:
|
||||
std::memset(result->_map + static_cast<unsigned char>(c1), true, 1 + static_cast<unsigned char>(c2) - static_cast<unsigned char>(c1));
|
||||
}
|
||||
}
|
||||
//
|
||||
// and now the classes:
|
||||
//
|
||||
typedef typename traits::char_class_type mask_type;
|
||||
mask_type m = char_set.classes();
|
||||
if(flags() & regbase::icase)
|
||||
{
|
||||
// adjust m as needed:
|
||||
if(((m & m_lower_mask) == m_lower_mask) || ((m & m_upper_mask) == m_upper_mask))
|
||||
m |= m_alpha_mask;
|
||||
}
|
||||
if(m != 0)
|
||||
{
|
||||
for(unsigned i = 0; i < (1u << CHAR_BIT); ++i)
|
||||
{
|
||||
if(this->m_traits.is_class(static_cast<charT>(i), m))
|
||||
result->_map[i] = true;
|
||||
}
|
||||
}
|
||||
if(negate)
|
||||
{
|
||||
for(unsigned i = 0; i < (1u << CHAR_BIT); ++i)
|
||||
{
|
||||
result->_map[i] = !(result->_map[i]);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class charT, class traits>
|
||||
void basic_regex_creator<charT, traits>::finalize(const charT* p1, const charT* p2)
|
||||
{
|
||||
@@ -174,7 +506,8 @@ void basic_regex_creator<charT, traits>::finalize(const charT* p1, const charT*
|
||||
std::memset(m_pdata->m_startmap, 0, sizeof(m_pdata->m_startmap));
|
||||
m_pdata->m_can_be_null = 0;
|
||||
|
||||
create_startmap(m_pdata->m_first_state, m_pdata->m_startmap, &(m_pdata->m_can_be_null), mask_all, 0);
|
||||
m_bad_repeats = 0;
|
||||
create_startmap(m_pdata->m_first_state, m_pdata->m_startmap, &(m_pdata->m_can_be_null), mask_all);
|
||||
// get the restart type:
|
||||
m_pdata->m_restart_type = get_restart_type(m_pdata->m_first_state);
|
||||
}
|
||||
@@ -186,12 +519,15 @@ void basic_regex_creator<charT, traits>::fixup_pointers(re_syntax_base* state)
|
||||
{
|
||||
switch(state->type)
|
||||
{
|
||||
case syntax_element_alt:
|
||||
case syntax_element_rep:
|
||||
case syntax_element_dot_rep:
|
||||
case syntax_element_char_rep:
|
||||
case syntax_element_short_set_rep:
|
||||
case syntax_element_long_set_rep:
|
||||
// set the id of this repeat:
|
||||
static_cast<re_repeat*>(state)->id = m_repeater_id++;
|
||||
// fall through:
|
||||
case syntax_element_alt:
|
||||
std::memset(static_cast<re_alt*>(state)->_map, 0, sizeof(static_cast<re_alt*>(state)->_map));
|
||||
static_cast<re_alt*>(state)->can_be_null = 0;
|
||||
// fall through:
|
||||
@@ -227,8 +563,10 @@ void basic_regex_creator<charT, traits>::create_startmaps(re_syntax_base* state)
|
||||
// create other startmaps *first*, since we can use the
|
||||
// results from these when creating out own:
|
||||
create_startmaps(state->next.p);
|
||||
create_startmap(state->next.p, static_cast<re_alt*>(state)->_map, &static_cast<re_alt*>(state)->can_be_null, mask_take, state);
|
||||
create_startmap(static_cast<re_alt*>(state)->alt.p, static_cast<re_alt*>(state)->_map, &static_cast<re_alt*>(state)->can_be_null, mask_skip, state);
|
||||
m_bad_repeats = 0;
|
||||
create_startmap(state->next.p, static_cast<re_alt*>(state)->_map, &static_cast<re_alt*>(state)->can_be_null, mask_take);
|
||||
m_bad_repeats = 0;
|
||||
create_startmap(static_cast<re_alt*>(state)->alt.p, static_cast<re_alt*>(state)->_map, &static_cast<re_alt*>(state)->can_be_null, mask_skip);
|
||||
return;
|
||||
default:
|
||||
state = state->next.p;
|
||||
@@ -237,9 +575,10 @@ void basic_regex_creator<charT, traits>::create_startmaps(re_syntax_base* state)
|
||||
}
|
||||
|
||||
template <class charT, class traits>
|
||||
void basic_regex_creator<charT, traits>::create_startmap(re_syntax_base* state, unsigned char* map, unsigned int* pnull, unsigned char mask, re_syntax_base* terminal)
|
||||
void basic_regex_creator<charT, traits>::create_startmap(re_syntax_base* state, unsigned char* map, unsigned int* pnull, unsigned char mask)
|
||||
{
|
||||
while(state && (state != terminal))
|
||||
int not_last_jump = 1;
|
||||
while(state)
|
||||
{
|
||||
switch(state->type)
|
||||
{
|
||||
@@ -270,34 +609,20 @@ void basic_regex_creator<charT, traits>::create_startmap(re_syntax_base* state,
|
||||
}
|
||||
// now figure out if we can match a NULL string at this point:
|
||||
if(pnull)
|
||||
create_startmap(state->next.p, 0, pnull, mask, terminal);
|
||||
create_startmap(state->next.p, 0, pnull, mask);
|
||||
return;
|
||||
}
|
||||
case syntax_element_backref:
|
||||
case syntax_element_wild:
|
||||
{
|
||||
// can't be null, any character can match:
|
||||
if(map)
|
||||
{
|
||||
map[0] |= mask_init;
|
||||
for(unsigned int i = 0; i < (1u << CHAR_BIT); ++i)
|
||||
{
|
||||
map[i] |= mask;
|
||||
}
|
||||
}
|
||||
set_all_masks(map, mask);
|
||||
return;
|
||||
}
|
||||
case syntax_element_match:
|
||||
{
|
||||
// must be null, any character can match:
|
||||
if(map)
|
||||
{
|
||||
map[0] |= mask_init;
|
||||
for(unsigned int i = 0; i < (1u << CHAR_BIT); ++i)
|
||||
{
|
||||
map[i] |= mask;
|
||||
}
|
||||
}
|
||||
set_all_masks(map, mask);
|
||||
if(pnull)
|
||||
*pnull |= mask;
|
||||
return;
|
||||
@@ -305,7 +630,7 @@ void basic_regex_creator<charT, traits>::create_startmap(re_syntax_base* state,
|
||||
case syntax_element_word_start:
|
||||
{
|
||||
// recurse, then AND with all the word characters:
|
||||
create_startmap(state->next.p, map, pnull, mask, terminal);
|
||||
create_startmap(state->next.p, map, pnull, mask);
|
||||
if(map)
|
||||
{
|
||||
map[0] |= mask_init;
|
||||
@@ -320,7 +645,7 @@ void basic_regex_creator<charT, traits>::create_startmap(re_syntax_base* state,
|
||||
case syntax_element_word_end:
|
||||
{
|
||||
// recurse, then AND with all the word characters:
|
||||
create_startmap(state->next.p, map, pnull, mask, terminal);
|
||||
create_startmap(state->next.p, map, pnull, mask);
|
||||
if(map)
|
||||
{
|
||||
map[0] |= mask_init;
|
||||
@@ -340,13 +665,35 @@ void basic_regex_creator<charT, traits>::create_startmap(re_syntax_base* state,
|
||||
return;
|
||||
}
|
||||
case syntax_element_long_set:
|
||||
assert(0);
|
||||
if(map)
|
||||
{
|
||||
typedef typename traits::char_class_type mask_type;
|
||||
map[0] |= mask_init;
|
||||
for(unsigned int i = 0; i < (1u << CHAR_BIT); ++i)
|
||||
{
|
||||
charT c = static_cast<charT>(i);
|
||||
if(&c != re_is_set_member(&c, &c + 1, static_cast<re_set_long<mask_type>*>(state), *m_pdata))
|
||||
map[i] |= mask;
|
||||
}
|
||||
}
|
||||
return;
|
||||
case syntax_element_set:
|
||||
assert(0);
|
||||
if(map)
|
||||
{
|
||||
map[0] |= mask_init;
|
||||
for(unsigned int i = 0; i < (1u << CHAR_BIT); ++i)
|
||||
{
|
||||
if(static_cast<re_set*>(state)->_map[
|
||||
static_cast<unsigned char>(m_traits.translate(static_cast<charT>(i), this->m_icase))])
|
||||
map[i] |= mask;
|
||||
}
|
||||
}
|
||||
return;
|
||||
case syntax_element_jump:
|
||||
// take the jump:
|
||||
state = static_cast<re_alt*>(state)->alt.p;
|
||||
break;;
|
||||
not_last_jump = -1;
|
||||
break;
|
||||
case syntax_element_alt:
|
||||
case syntax_element_rep:
|
||||
case syntax_element_dot_rep:
|
||||
@@ -360,6 +707,7 @@ void basic_regex_creator<charT, traits>::create_startmap(re_syntax_base* state,
|
||||
if(map)
|
||||
{
|
||||
// copy previous results:
|
||||
map[0] |= mask_init;
|
||||
for(unsigned int i = 0; i <= UCHAR_MAX; ++i)
|
||||
{
|
||||
if(rep->_map[i] & mask_any)
|
||||
@@ -376,8 +724,17 @@ void basic_regex_creator<charT, traits>::create_startmap(re_syntax_base* state,
|
||||
{
|
||||
// we haven't created a startmap for this alternative yet
|
||||
// so take the union of the two options:
|
||||
create_startmap(state->next.p, map, pnull, mask, state);
|
||||
create_startmap(rep->alt.p, map, pnull, mask, state);
|
||||
if(is_bad_repeat(state))
|
||||
{
|
||||
set_all_masks(map, mask);
|
||||
return;
|
||||
}
|
||||
set_bad_repeat(state);
|
||||
create_startmap(state->next.p, map, pnull, mask);
|
||||
if((state->type == syntax_element_alt)
|
||||
|| (static_cast<re_repeat*>(state)->min == 0)
|
||||
|| (not_last_jump == 0))
|
||||
create_startmap(rep->alt.p, map, pnull, mask);
|
||||
}
|
||||
}
|
||||
return;
|
||||
@@ -395,6 +752,7 @@ void basic_regex_creator<charT, traits>::create_startmap(re_syntax_base* state,
|
||||
default:
|
||||
state = state->next.p;
|
||||
}
|
||||
++not_last_jump;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -416,8 +774,9 @@ unsigned basic_regex_creator<charT, traits>::get_restart_type(re_syntax_base* st
|
||||
return regbase::restart_line;
|
||||
case syntax_element_word_boundary:
|
||||
case syntax_element_word_start:
|
||||
return regbase::restart_line;
|
||||
return regbase::restart_word;
|
||||
case syntax_element_buffer_start:
|
||||
case syntax_element_restart_continue:
|
||||
return regbase::restart_continue;
|
||||
default:
|
||||
state = 0;
|
||||
@@ -427,6 +786,68 @@ unsigned basic_regex_creator<charT, traits>::get_restart_type(re_syntax_base* st
|
||||
return regbase::restart_any;
|
||||
}
|
||||
|
||||
template <class charT, class traits>
|
||||
void basic_regex_creator<charT, traits>::set_all_masks(unsigned char* bits, unsigned char mask)
|
||||
{
|
||||
//
|
||||
// set mask in all of bits elements,
|
||||
// if bits[0] has mask_init not set then we can
|
||||
// optimise this to a call to memset:
|
||||
//
|
||||
if(bits)
|
||||
{
|
||||
if(bits[0] == 0)
|
||||
(std::memset)(bits, mask, 1u << CHAR_BIT);
|
||||
else
|
||||
{
|
||||
for(unsigned i = 0; i < (1u << CHAR_BIT); ++i)
|
||||
bits[i] |= mask;
|
||||
}
|
||||
bits[0] |= mask_init;
|
||||
}
|
||||
}
|
||||
|
||||
template <class charT, class traits>
|
||||
bool basic_regex_creator<charT, traits>::is_bad_repeat(re_syntax_base* pt)
|
||||
{
|
||||
switch(pt->type)
|
||||
{
|
||||
case syntax_element_rep:
|
||||
case syntax_element_dot_rep:
|
||||
case syntax_element_char_rep:
|
||||
case syntax_element_short_set_rep:
|
||||
case syntax_element_long_set_rep:
|
||||
{
|
||||
unsigned id = static_cast<re_repeat*>(pt)->id;
|
||||
if(id > sizeof(m_bad_repeats) * CHAR_BIT)
|
||||
return true; // run out of bits, assume we can't traverse this one.
|
||||
return m_bad_repeats & (1u << id);
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
template <class charT, class traits>
|
||||
void basic_regex_creator<charT, traits>::set_bad_repeat(re_syntax_base* pt)
|
||||
{
|
||||
switch(pt->type)
|
||||
{
|
||||
case syntax_element_rep:
|
||||
case syntax_element_dot_rep:
|
||||
case syntax_element_char_rep:
|
||||
case syntax_element_short_set_rep:
|
||||
case syntax_element_long_set_rep:
|
||||
{
|
||||
unsigned id = static_cast<re_repeat*>(pt)->id;
|
||||
if(id <= sizeof(m_bad_repeats) * CHAR_BIT)
|
||||
m_bad_repeats |= (1u << id);
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace re_detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
@@ -45,6 +45,12 @@ public:
|
||||
bool parse_repeat(std::size_t low = 0, std::size_t high = (std::numeric_limits<std::size_t>::max)());
|
||||
bool parse_repeat_range(bool isbasic);
|
||||
bool parse_alt();
|
||||
bool parse_set();
|
||||
bool parse_backref();
|
||||
void parse_set_literal(basic_char_set<charT, traits>& char_set);
|
||||
bool parse_inner_set(basic_char_set<charT, traits>& char_set);
|
||||
digraph<charT> get_next_set_literal();
|
||||
charT unescape_character();
|
||||
|
||||
private:
|
||||
typedef bool (basic_regex_parser::*parser_proc_type)();
|
||||
@@ -54,7 +60,6 @@ private:
|
||||
const charT* m_position; // our current parser position
|
||||
unsigned m_mark_count; // how many sub-expressions we have
|
||||
std::ptrdiff_t m_paren_start; // where the last seen ')' began (where repeats are inserted).
|
||||
unsigned m_repeater_id; // the id of the next repeater
|
||||
std::ptrdiff_t m_alt_insert_point; // where to insert the next alternative
|
||||
|
||||
basic_regex_parser& operator=(const basic_regex_parser&);
|
||||
@@ -63,7 +68,7 @@ private:
|
||||
|
||||
template <class charT, class traits>
|
||||
basic_regex_parser<charT, traits>::basic_regex_parser(regex_data<charT, traits>* data)
|
||||
: basic_regex_creator<charT, traits>(data), m_mark_count(0), m_paren_start(0), m_repeater_id(0), m_alt_insert_point(0)
|
||||
: basic_regex_creator<charT, traits>(data), m_mark_count(0), m_paren_start(0), m_alt_insert_point(0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -151,6 +156,8 @@ bool basic_regex_parser<charT, traits>::parse_basic()
|
||||
++m_position;
|
||||
return parse_repeat();
|
||||
}
|
||||
case regex_constants::syntax_open_set:
|
||||
return parse_set();
|
||||
default:
|
||||
return parse_literal();
|
||||
}
|
||||
@@ -160,7 +167,7 @@ bool basic_regex_parser<charT, traits>::parse_basic()
|
||||
template <class charT, class traits>
|
||||
bool basic_regex_parser<charT, traits>::parse_extended()
|
||||
{
|
||||
bool result;
|
||||
bool result = true;
|
||||
switch(this->m_traits.syntax_type(*m_position))
|
||||
{
|
||||
case regex_constants::syntax_open_mark:
|
||||
@@ -205,6 +212,8 @@ bool basic_regex_parser<charT, traits>::parse_extended()
|
||||
break;
|
||||
case regex_constants::syntax_or:
|
||||
return parse_alt();
|
||||
case regex_constants::syntax_open_set:
|
||||
return parse_set();
|
||||
default:
|
||||
result = parse_literal();
|
||||
break;
|
||||
@@ -260,6 +269,11 @@ bool basic_regex_parser<charT, traits>::parse_open_paren()
|
||||
// restore the alternate insertion point:
|
||||
//
|
||||
this->m_alt_insert_point = last_alt_point;
|
||||
//
|
||||
// allow backrefs to this mark:
|
||||
//
|
||||
if((markid > 0) && (markid < sizeof(unsigned) * CHAR_BIT))
|
||||
this->m_backrefs |= 1u << (markid - 1);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -276,7 +290,7 @@ bool basic_regex_parser<charT, traits>::parse_basic_escape()
|
||||
case regex_constants::syntax_close_mark:
|
||||
return false;
|
||||
case regex_constants::syntax_plus:
|
||||
if(this->m_pdata->m_flags & regex_constants::bk_plus_qm)
|
||||
if(this->flags() & regex_constants::bk_plus_qm)
|
||||
{
|
||||
++m_position;
|
||||
return parse_repeat(1);
|
||||
@@ -284,7 +298,7 @@ bool basic_regex_parser<charT, traits>::parse_basic_escape()
|
||||
else
|
||||
return parse_literal();
|
||||
case regex_constants::syntax_question:
|
||||
if(this->m_pdata->m_flags & regex_constants::bk_plus_qm)
|
||||
if(this->flags() & regex_constants::bk_plus_qm)
|
||||
{
|
||||
++m_position;
|
||||
return parse_repeat(0, 1);
|
||||
@@ -292,22 +306,24 @@ bool basic_regex_parser<charT, traits>::parse_basic_escape()
|
||||
else
|
||||
return parse_literal();
|
||||
case regex_constants::syntax_open_brace:
|
||||
if(this->m_pdata->m_flags & regbase::no_intervals)
|
||||
if(this->flags() & regbase::no_intervals)
|
||||
return parse_literal();
|
||||
++m_position;
|
||||
return parse_repeat_range(true);
|
||||
case regex_constants::syntax_close_brace:
|
||||
if(this->m_pdata->m_flags & regbase::no_intervals)
|
||||
if(this->flags() & regbase::no_intervals)
|
||||
return parse_literal();
|
||||
fail(REG_EBRACE, this->m_position - this->m_base);
|
||||
result = false;
|
||||
break;
|
||||
case regex_constants::syntax_or:
|
||||
if(this->m_pdata->m_flags & regbase::bk_vbar)
|
||||
if(this->flags() & regbase::bk_vbar)
|
||||
return parse_alt();
|
||||
else
|
||||
result = parse_literal();
|
||||
break;
|
||||
case regex_constants::syntax_digit:
|
||||
return parse_backref();
|
||||
default:
|
||||
result = parse_literal();
|
||||
break;
|
||||
@@ -319,8 +335,35 @@ template <class charT, class traits>
|
||||
bool basic_regex_parser<charT, traits>::parse_extended_escape()
|
||||
{
|
||||
++m_position;
|
||||
bool negate = false; // in case this is a character class escape: \w \d etc
|
||||
switch(this->m_traits.escape_syntax_type(*m_position))
|
||||
{
|
||||
case regex_constants::escape_type_not_class:
|
||||
negate = true;
|
||||
// fall through:
|
||||
case regex_constants::escape_type_class:
|
||||
{
|
||||
typedef typename traits::char_class_type mask_type;
|
||||
mask_type m = this->m_traits.lookup_classname(m_position, m_position+1);
|
||||
if(m != 0)
|
||||
{
|
||||
basic_char_set<charT, traits> char_set;
|
||||
if(negate)
|
||||
char_set.negate();
|
||||
char_set.add_class(m);
|
||||
if(0 == this->append_set(char_set))
|
||||
fail(REG_ERANGE, m_position - m_base);
|
||||
++m_position;
|
||||
return true;
|
||||
}
|
||||
//
|
||||
// not a class, just a regular unknown escape:
|
||||
//
|
||||
this->append_literal(unescape_character());
|
||||
break;
|
||||
}
|
||||
case regex_constants::syntax_digit:
|
||||
return parse_backref();
|
||||
case regex_constants::escape_type_left_word:
|
||||
++m_position;
|
||||
this->append_state(syntax_element_word_start);
|
||||
@@ -329,8 +372,29 @@ bool basic_regex_parser<charT, traits>::parse_extended_escape()
|
||||
++m_position;
|
||||
this->append_state(syntax_element_word_end);
|
||||
break;
|
||||
case regex_constants::escape_type_start_buffer:
|
||||
++m_position;
|
||||
this->append_state(syntax_element_buffer_start);
|
||||
break;
|
||||
case regex_constants::escape_type_end_buffer:
|
||||
++m_position;
|
||||
this->append_state(syntax_element_buffer_end);
|
||||
break;
|
||||
case regex_constants::escape_type_word_assert:
|
||||
++m_position;
|
||||
this->append_state(syntax_element_word_boundary);
|
||||
break;
|
||||
case regex_constants::escape_type_not_word_assert:
|
||||
++m_position;
|
||||
this->append_state(syntax_element_within_word);
|
||||
break;
|
||||
case regex_constants::escape_type_Z:
|
||||
++m_position;
|
||||
this->append_state(syntax_element_soft_buffer_end);
|
||||
break;
|
||||
default:
|
||||
return parse_literal();
|
||||
this->append_literal(unescape_character());
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -355,7 +419,7 @@ bool basic_regex_parser<charT, traits>::parse_repeat(std::size_t low, std::size_
|
||||
// when we get to here we may have a non-greedy ? mark still to come:
|
||||
//
|
||||
if((m_position != m_end)
|
||||
&& (0 == (this->m_pdata->m_flags & (regbase::main_option_type | regbase::no_perl_ex))))
|
||||
&& (0 == (this->flags() & (regbase::main_option_type | regbase::no_perl_ex))))
|
||||
{
|
||||
// OK we have a perl regex, check for a '?':
|
||||
if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_question)
|
||||
@@ -417,7 +481,6 @@ bool basic_regex_parser<charT, traits>::parse_repeat(std::size_t low, std::size_
|
||||
rep->max = high;
|
||||
rep->greedy = greedy;
|
||||
rep->leading = false;
|
||||
rep->id = m_repeater_id++;
|
||||
// store our repeater position for later:
|
||||
std::ptrdiff_t rep_off = this->getoffset(rep);
|
||||
// and append a back jump to the repeat:
|
||||
@@ -535,7 +598,7 @@ bool basic_regex_parser<charT, traits>::parse_alt()
|
||||
//
|
||||
// if we didn't actually add any trailing states then that's an error:
|
||||
//
|
||||
if(this->m_alt_insert_point == this->m_pdata->m_data.size())
|
||||
if(this->m_alt_insert_point == static_cast<std::ptrdiff_t>(this->m_pdata->m_data.size()))
|
||||
fail(REG_EMPTY, this->m_position - this->m_base);
|
||||
//
|
||||
// fix up the jump we added to point to the end of the states
|
||||
@@ -548,6 +611,311 @@ bool basic_regex_parser<charT, traits>::parse_alt()
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class charT, class traits>
|
||||
bool basic_regex_parser<charT, traits>::parse_set()
|
||||
{
|
||||
++m_position;
|
||||
if(m_position == m_end)
|
||||
fail(REG_EBRACK, m_position - m_base);
|
||||
basic_char_set<charT, traits> char_set;
|
||||
|
||||
const charT* base = m_position; // where the '[' was
|
||||
const charT* item_base = m_position; // where the '[' or '^' was
|
||||
|
||||
while(m_position != m_end)
|
||||
{
|
||||
switch(this->m_traits.syntax_type(*m_position))
|
||||
{
|
||||
case regex_constants::syntax_caret:
|
||||
if(m_position == base)
|
||||
{
|
||||
char_set.negate();
|
||||
++m_position;
|
||||
item_base = m_position;
|
||||
}
|
||||
else
|
||||
parse_set_literal(char_set);
|
||||
break;
|
||||
case regex_constants::syntax_close_set:
|
||||
if(m_position == item_base)
|
||||
{
|
||||
parse_set_literal(char_set);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
++m_position;
|
||||
if(0 == this->append_set(char_set))
|
||||
fail(REG_ERANGE, m_position - m_base);
|
||||
}
|
||||
return true;
|
||||
case regex_constants::syntax_open_set:
|
||||
if(parse_inner_set(char_set))
|
||||
break;
|
||||
return true;
|
||||
default:
|
||||
parse_set_literal(char_set);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return m_position != m_end;
|
||||
}
|
||||
|
||||
template <class charT, class traits>
|
||||
bool basic_regex_parser<charT, traits>::parse_inner_set(basic_char_set<charT, traits>& char_set)
|
||||
{
|
||||
//
|
||||
// we have either a character class [:name:]
|
||||
// a collating element [.name.]
|
||||
// or an equivalence class [=name=]
|
||||
//
|
||||
if(m_end == ++m_position)
|
||||
fail(REG_EBRACK, m_position - m_base);
|
||||
switch(this->m_traits.syntax_type(*m_position))
|
||||
{
|
||||
case regex_constants::syntax_colon:
|
||||
{
|
||||
// check that character classes are actually enabled:
|
||||
if((this->flags() & (regbase::main_option_type | regbase::no_char_classes))
|
||||
== (regbase::basic_syntax_group | regbase::no_char_classes))
|
||||
{
|
||||
--m_position;
|
||||
parse_set_literal(char_set);
|
||||
return true;
|
||||
}
|
||||
// skip the ':'
|
||||
if(m_end == ++m_position)
|
||||
fail(REG_EBRACK, m_position - m_base);
|
||||
const charT* name_first = m_position;
|
||||
// skip at least one character, then find the matching ':]'
|
||||
if(m_end == ++m_position)
|
||||
fail(REG_EBRACK, m_position - m_base);
|
||||
while((m_position != m_end)
|
||||
&& (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_colon))
|
||||
++m_position;
|
||||
const charT* name_last = m_position;
|
||||
if(m_end == m_position)
|
||||
fail(REG_EBRACK, m_position - m_base);
|
||||
if((m_end == ++m_position)
|
||||
|| (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_set))
|
||||
fail(REG_EBRACK, m_position - m_base);
|
||||
typedef typename traits::char_class_type mask_type;
|
||||
mask_type m = this->m_traits.lookup_classname(name_first, name_last);
|
||||
if(0 == m)
|
||||
{
|
||||
if(char_set.empty() && (name_last - name_first == 1))
|
||||
{
|
||||
// maybe a special case:
|
||||
++m_position;
|
||||
if( (m_position != m_end)
|
||||
&& (this->m_traits.syntax_type(*m_position)
|
||||
== regex_constants::syntax_close_set))
|
||||
{
|
||||
if(this->m_traits.escape_syntax_type(*name_first)
|
||||
== regex_constants::escape_type_left_word)
|
||||
{
|
||||
++m_position;
|
||||
this->append_state(syntax_element_word_start);
|
||||
return false;
|
||||
}
|
||||
if(this->m_traits.escape_syntax_type(*name_first)
|
||||
== regex_constants::escape_type_right_word)
|
||||
{
|
||||
++m_position;
|
||||
this->append_state(syntax_element_word_end);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
fail(REG_ECTYPE, name_first - m_base);
|
||||
}
|
||||
char_set.add_class(m);
|
||||
++m_position;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
--m_position;
|
||||
parse_set_literal(char_set);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class charT, class traits>
|
||||
void basic_regex_parser<charT, traits>::parse_set_literal(basic_char_set<charT, traits>& char_set)
|
||||
{
|
||||
digraph<charT> start_range = get_next_set_literal();
|
||||
if(m_end == m_position)
|
||||
fail(REG_EBRACK, m_position - m_base);
|
||||
if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_dash)
|
||||
{
|
||||
// we have a range:
|
||||
if(m_end == ++m_position)
|
||||
fail(REG_EBRACK, m_position - m_base);
|
||||
if(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_set)
|
||||
{
|
||||
digraph<charT> end_range = get_next_set_literal();
|
||||
char_set.add_range(start_range, end_range);
|
||||
if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_dash)
|
||||
fail(REG_ERANGE, m_position - m_base);
|
||||
return;
|
||||
}
|
||||
--m_position;
|
||||
}
|
||||
char_set.add_single(start_range);
|
||||
}
|
||||
|
||||
template <class charT, class traits>
|
||||
digraph<charT> basic_regex_parser<charT, traits>::get_next_set_literal()
|
||||
{
|
||||
digraph<charT> result;
|
||||
switch(this->m_traits.syntax_type(*m_position))
|
||||
{
|
||||
case regex_constants::syntax_escape:
|
||||
// check to see if escapes are supported first:
|
||||
if(this->flags() & regex_constants::no_escape_in_lists)
|
||||
{
|
||||
result = *m_position++;
|
||||
break;
|
||||
}
|
||||
++m_position;
|
||||
result = unescape_character();
|
||||
break;
|
||||
default:
|
||||
result = *m_position++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class charT, class traits>
|
||||
charT basic_regex_parser<charT, traits>::unescape_character()
|
||||
{
|
||||
charT result(0);
|
||||
if(m_position == m_end)
|
||||
fail(REG_EESCAPE, m_position - m_base);
|
||||
switch(this->m_traits.syntax_type(*m_position))
|
||||
{
|
||||
case regex_constants::escape_type_control_a:
|
||||
result = charT('\a');
|
||||
break;
|
||||
case regex_constants::escape_type_e:
|
||||
result = charT(27);
|
||||
break;
|
||||
case regex_constants::escape_type_control_f:
|
||||
result = charT('\f');
|
||||
break;
|
||||
case regex_constants::escape_type_control_n:
|
||||
result = charT('\n');
|
||||
break;
|
||||
case regex_constants::escape_type_control_r:
|
||||
result = charT('\r');
|
||||
break;
|
||||
case regex_constants::escape_type_control_t:
|
||||
result = charT('\t');
|
||||
break;
|
||||
case regex_constants::escape_type_control_v:
|
||||
result = charT('\v');
|
||||
break;
|
||||
case regex_constants::escape_type_word_assert:
|
||||
result = charT('\b');
|
||||
break;
|
||||
case regex_constants::escape_type_ascii_control:
|
||||
++m_position;
|
||||
if(m_position == m_end)
|
||||
{
|
||||
fail(REG_EESCAPE, m_position - m_base);
|
||||
return result;
|
||||
}
|
||||
if((*m_position < charT('@'))
|
||||
|| (*m_position > charT(125)) )
|
||||
{
|
||||
fail(REG_EESCAPE, m_position - m_base);
|
||||
return result;
|
||||
}
|
||||
result = static_cast<charT>(*m_position - charT('@'));
|
||||
break;
|
||||
case regex_constants::escape_type_hex:
|
||||
++m_position;
|
||||
if(m_position == m_end)
|
||||
{
|
||||
fail(REG_EESCAPE, m_position - m_base);
|
||||
break;
|
||||
}
|
||||
// maybe have \x{ddd}
|
||||
if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_open_brace)
|
||||
{
|
||||
++m_position;
|
||||
if(m_position == m_end)
|
||||
{
|
||||
fail(REG_EESCAPE, m_position - m_base);
|
||||
break;
|
||||
}
|
||||
int i = this->m_traits.toi(m_position, m_end, 16);
|
||||
if((m_position == m_end)
|
||||
|| (i < 0)
|
||||
|| (i > (std::numeric_limits<charT>::max)())
|
||||
|| (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_brace))
|
||||
{
|
||||
fail(REG_BADBR, m_position - m_base);
|
||||
}
|
||||
++m_position;
|
||||
result = charT(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::ptrdiff_t len = (std::min)(static_cast<std::ptrdiff_t>(2), m_end - m_position);
|
||||
int i = this->m_traits.toi(m_position, m_position + len, 16);
|
||||
if((i < 0)
|
||||
|| (i >> (sizeof(charT) * CHAR_BIT)))
|
||||
{
|
||||
fail(REG_EESCAPE, m_position - m_base);
|
||||
}
|
||||
result = charT(i);
|
||||
}
|
||||
return result;
|
||||
case regex_constants::syntax_digit:
|
||||
{
|
||||
// an octal escape sequence, the first character must be a zero
|
||||
// followed by up to 3 octal digits:
|
||||
std::ptrdiff_t len = (std::min)(std::distance(m_position, m_end), static_cast<std::ptrdiff_t>(4));
|
||||
int val = this->m_traits.toi(m_position, m_position + len, 8);
|
||||
if(val < 0)
|
||||
fail(REG_EESCAPE, m_position - m_base);
|
||||
return static_cast<charT>(val);
|
||||
}
|
||||
default:
|
||||
result = *m_position;
|
||||
break;
|
||||
}
|
||||
++m_position;
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class charT, class traits>
|
||||
bool basic_regex_parser<charT, traits>::parse_backref()
|
||||
{
|
||||
if(m_position == m_end)
|
||||
{
|
||||
fail(REG_EESCAPE, m_position - m_end);
|
||||
}
|
||||
int i = this->m_traits.toi(m_position, m_position + 1, 10);
|
||||
if((i > 0) && (this->m_backrefs & (1u << (i-1))))
|
||||
{
|
||||
re_brace* pb = static_cast<re_brace*>(this->append_state(syntax_element_backref, sizeof(re_brace)));
|
||||
pb->index = i;
|
||||
}
|
||||
else if(i == 0)
|
||||
{
|
||||
// not a backref at all but an octal escape sequence:
|
||||
--m_position;
|
||||
charT c = unescape_character();
|
||||
this->append_literal(c);
|
||||
}
|
||||
else
|
||||
fail(REG_ESUBREG, m_position - m_end);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace re_detail
|
||||
} // namespace boost
|
||||
|
||||
|
||||
@@ -304,6 +304,27 @@ template <class charT>
|
||||
class cpp_regex_traits_implementation : public cpp_regex_traits_char_layer<charT>
|
||||
{
|
||||
public:
|
||||
typedef typename cpp_regex_traits<charT>::char_class_type char_class_type;
|
||||
BOOST_STATIC_CONSTANT(char_class_type, mask_blank = 1u << 16);
|
||||
BOOST_STATIC_CONSTANT(char_class_type, mask_word = 1u << 17);
|
||||
BOOST_STATIC_CONSTANT(char_class_type, mask_unicode = 1u << 18);
|
||||
BOOST_STATIC_CONSTANT(char_class_type,
|
||||
mask_base =
|
||||
std::ctype<charT>::alnum
|
||||
| std::ctype<charT>::alpha
|
||||
| std::ctype<charT>::cntrl
|
||||
| std::ctype<charT>::digit
|
||||
| std::ctype<charT>::graph
|
||||
| std::ctype<charT>::lower
|
||||
| std::ctype<charT>::print
|
||||
| std::ctype<charT>::punct
|
||||
| std::ctype<charT>::space
|
||||
| std::ctype<charT>::upper
|
||||
| std::ctype<charT>::xdigit);
|
||||
|
||||
//BOOST_STATIC_ASSERT(0 == (mask_base & (mask_word | mask_unicode)));
|
||||
|
||||
|
||||
typedef std::basic_string<charT> string_type;
|
||||
//cpp_regex_traits_implementation();
|
||||
cpp_regex_traits_implementation(const std::locale& l);
|
||||
@@ -316,10 +337,25 @@ public:
|
||||
}
|
||||
return get_default_error_string(n);
|
||||
}
|
||||
char_class_type lookup_classname(const charT* p1, const charT* p2) const
|
||||
{
|
||||
char_class_type result = lookup_classname_imp(p1, p2);
|
||||
if(result == 0)
|
||||
{
|
||||
string_type s(p1, p2);
|
||||
this->m_pctype->tolower(&*s.begin(), &*s.end());
|
||||
result = lookup_classname_imp(&*s.begin(), &*s.end());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
re_detail::parser_buf<charT> m_sbuf; // buffer for parsing numbers.
|
||||
std::basic_istream<charT> m_is; // stream for parsing numbers.
|
||||
private:
|
||||
std::map<int, std::string> m_error_strings; // error messages indexed by numberic ID
|
||||
//
|
||||
// helpers:
|
||||
//
|
||||
char_class_type lookup_classname_imp(const charT* p1, const charT* p2) const;
|
||||
};
|
||||
|
||||
template <class charT>
|
||||
@@ -349,7 +385,7 @@ cpp_regex_traits_implementation<charT>::cpp_regex_traits_implementation(const st
|
||||
//
|
||||
if((int)cat >= 0)
|
||||
{
|
||||
for(int i = 0; i <= boost::regex_constants::error_unknown; ++i)
|
||||
for(boost::regex_constants::error_type i = 0; i <= boost::regex_constants::error_unknown; ++i)
|
||||
{
|
||||
const char* p = get_default_error_string(i);
|
||||
string_type default_message;
|
||||
@@ -369,6 +405,39 @@ cpp_regex_traits_implementation<charT>::cpp_regex_traits_implementation(const st
|
||||
}
|
||||
}
|
||||
|
||||
template <class charT>
|
||||
typename cpp_regex_traits_implementation<charT>::char_class_type
|
||||
cpp_regex_traits_implementation<charT>::lookup_classname_imp(const charT* p1, const charT* p2) const
|
||||
{
|
||||
static const char_class_type masks[] =
|
||||
{
|
||||
0,
|
||||
std::ctype<char>::alnum,
|
||||
std::ctype<char>::alpha,
|
||||
cpp_regex_traits_implementation<charT>::mask_blank,
|
||||
std::ctype<char>::cntrl,
|
||||
std::ctype<char>::digit,
|
||||
std::ctype<char>::digit,
|
||||
std::ctype<char>::graph,
|
||||
std::ctype<char>::lower,
|
||||
std::ctype<char>::lower,
|
||||
std::ctype<char>::print,
|
||||
std::ctype<char>::punct,
|
||||
std::ctype<char>::space,
|
||||
std::ctype<char>::space,
|
||||
std::ctype<char>::upper,
|
||||
cpp_regex_traits_implementation<charT>::mask_unicode,
|
||||
std::ctype<char>::upper,
|
||||
std::ctype<char>::alnum | cpp_regex_traits_implementation<charT>::mask_word,
|
||||
std::ctype<char>::alnum | cpp_regex_traits_implementation<charT>::mask_word,
|
||||
std::ctype<char>::xdigit,
|
||||
};
|
||||
std::size_t id = 1 + re_detail::get_default_class_id(p1, p2);
|
||||
assert(id < sizeof(masks) / sizeof(masks[0]));
|
||||
return masks[id];
|
||||
}
|
||||
|
||||
|
||||
template <class charT>
|
||||
boost::shared_ptr<cpp_regex_traits_implementation<charT> > create_cpp_regex_traits(const std::locale& l BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(charT))
|
||||
{
|
||||
@@ -376,6 +445,15 @@ boost::shared_ptr<cpp_regex_traits_implementation<charT> > create_cpp_regex_trai
|
||||
return boost::shared_ptr<cpp_regex_traits_implementation<charT> >(new cpp_regex_traits_implementation<charT>(l));
|
||||
}
|
||||
|
||||
//
|
||||
// helpers to suppress warnings:
|
||||
//
|
||||
template <class charT>
|
||||
inline bool is_extended(charT c)
|
||||
{ return c > 256; }
|
||||
inline bool is_extended(char)
|
||||
{ return false; }
|
||||
|
||||
} // re_detail
|
||||
|
||||
template <class charT>
|
||||
@@ -390,25 +468,6 @@ public:
|
||||
typedef std::locale locale_type;
|
||||
typedef boost::uint_least32_t char_class_type;
|
||||
|
||||
BOOST_STATIC_CONSTANT(char_class_type, mask_blank = 1u << 16);
|
||||
BOOST_STATIC_CONSTANT(char_class_type, mask_word = 1u << 17);
|
||||
BOOST_STATIC_CONSTANT(char_class_type, mask_unicode = 1u << 18);
|
||||
BOOST_STATIC_CONSTANT(char_class_type,
|
||||
mask_base =
|
||||
std::ctype<char>::alnum
|
||||
| std::ctype<char>::alpha
|
||||
| std::ctype<char>::cntrl
|
||||
| std::ctype<char>::digit
|
||||
| std::ctype<char>::graph
|
||||
| std::ctype<char>::lower
|
||||
| std::ctype<char>::print
|
||||
| std::ctype<char>::punct
|
||||
| std::ctype<char>::space
|
||||
| std::ctype<char>::upper
|
||||
| std::ctype<char>::xdigit);
|
||||
|
||||
//BOOST_STATIC_ASSERT(0 == (mask_base & (mask_word | mask_unicode)));
|
||||
|
||||
cpp_regex_traits()
|
||||
: m_pimpl(re_detail::create_cpp_regex_traits<charT>(std::locale()))
|
||||
{ }
|
||||
@@ -438,33 +497,7 @@ public:
|
||||
}
|
||||
char_class_type lookup_classname(const charT* p1, const charT* p2) const
|
||||
{
|
||||
static const char_class_type masks[] =
|
||||
{
|
||||
0,
|
||||
std::ctype<char>::alnum,
|
||||
std::ctype<char>::alpha,
|
||||
cpp_regex_traits<charT>::mask_blank,
|
||||
std::ctype<char>::cntrl,
|
||||
std::ctype<char>::digit,
|
||||
std::ctype<char>::digit,
|
||||
std::ctype<char>::graph,
|
||||
std::ctype<char>::lower,
|
||||
std::ctype<char>::lower,
|
||||
std::ctype<char>::print,
|
||||
std::ctype<char>::punct,
|
||||
std::ctype<char>::space,
|
||||
std::ctype<char>::space,
|
||||
cpp_regex_traits<charT>::mask_unicode,
|
||||
std::ctype<char>::upper,
|
||||
std::ctype<char>::upper,
|
||||
std::ctype<char>::alnum | cpp_regex_traits<charT>::mask_word,
|
||||
std::ctype<char>::alnum | cpp_regex_traits<charT>::mask_word,
|
||||
std::ctype<char>::xdigit,
|
||||
};
|
||||
int id = re_detail::get_default_class_id(p1, p2);
|
||||
assert(id >= -1);
|
||||
assert(id < sizeof(masks) / sizeof(masks[0]));
|
||||
return masks[1 + id];
|
||||
return m_pimpl->lookup_classname(p1, p2);
|
||||
}
|
||||
string_type lookup_collatename(const charT* p1, const charT* p2) const
|
||||
{
|
||||
@@ -472,16 +505,17 @@ public:
|
||||
}
|
||||
bool is_class(charT c, char_class_type f) const
|
||||
{
|
||||
if((f & cpp_regex_traits<charT>::mask_base)
|
||||
typedef typename std::ctype<charT>::mask ctype_mask;
|
||||
if((f & re_detail::cpp_regex_traits_implementation<charT>::mask_base)
|
||||
&& (m_pimpl->m_pctype->is(
|
||||
static_cast<std::ctype<charT>::mask>(f & cpp_regex_traits<charT>::mask_base), c)))
|
||||
static_cast<ctype_mask>(f & re_detail::cpp_regex_traits_implementation<charT>::mask_base), c)))
|
||||
return true;
|
||||
else if((f & cpp_regex_traits<charT>::mask_unicode) && (c >= 256))
|
||||
else if((f & re_detail::cpp_regex_traits_implementation<charT>::mask_unicode) && re_detail::is_extended(c))
|
||||
return true;
|
||||
else if((f & cpp_regex_traits<charT>::mask_word) && (c == '_'))
|
||||
else if((f & re_detail::cpp_regex_traits_implementation<charT>::mask_word) && (c == '_'))
|
||||
return true;
|
||||
else if((f & cpp_regex_traits<charT>::mask_blank)
|
||||
&& m_pimpl->m_pctype->is(static_cast<std::ctype<charT>::mask>(f & cpp_regex_traits<charT>::mask_base), c)
|
||||
else if((f & re_detail::cpp_regex_traits_implementation<charT>::mask_blank)
|
||||
&& m_pimpl->m_pctype->is(std::ctype<charT>::space, c)
|
||||
&& !re_detail::is_separator(c))
|
||||
return true;
|
||||
return false;
|
||||
@@ -515,6 +549,7 @@ private:
|
||||
// catalog name handler:
|
||||
//
|
||||
static std::string& get_catalog_name_inst();
|
||||
|
||||
#ifdef BOOST_HAS_THREADS
|
||||
static static_mutex& get_mutex_inst();
|
||||
#endif
|
||||
|
||||
@@ -23,12 +23,15 @@
|
||||
#ifndef BOOST_REGEX_ERROR_TYPE_HPP
|
||||
#define BOOST_REGEX_ERROR_TYPE_HPP
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace boost{
|
||||
#endif
|
||||
|
||||
//
|
||||
// start with the POSIX API versions of these:
|
||||
//
|
||||
typedef unsigned reg_error_t;
|
||||
typedef reg_error_t reg_errcode_t; // backwards compatibility
|
||||
|
||||
static const reg_error_t REG_NOERROR = 0; /* Success. */
|
||||
static const reg_error_t REG_NOMATCH = 1; /* Didn't find a match (for regexec). */
|
||||
@@ -57,6 +60,7 @@ static const reg_error_t REG_ESTACK = 19; /* out of stack space */
|
||||
static const reg_error_t REG_E_UNKNOWN = 20; /* unknown error */
|
||||
static const reg_error_t REG_ENOSYS = REG_E_UNKNOWN; /* Reserved. */
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace regex_constants{
|
||||
|
||||
typedef ::boost::reg_error_t error_type;
|
||||
@@ -80,5 +84,6 @@ static const error_type error_unknown = REG_E_UNKNOWN;
|
||||
|
||||
}
|
||||
}
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif
|
||||
@@ -91,17 +91,17 @@ template <class iterator, class charT, class traits_type, class char_classT>
|
||||
iterator BOOST_REGEX_CALL re_is_set_member(iterator next,
|
||||
iterator last,
|
||||
const re_set_long<char_classT>* set_,
|
||||
const basic_regex<charT, traits_type>& e)
|
||||
const regex_data<charT, traits_type>& e)
|
||||
{
|
||||
const charT* p = reinterpret_cast<const charT*>(set_+1);
|
||||
iterator ptr;
|
||||
unsigned int i;
|
||||
bool icase = e.flags() & regex_constants::icase;
|
||||
bool icase = e.m_flags & regex_constants::icase;
|
||||
|
||||
if(next == last) return next;
|
||||
|
||||
typedef typename traits_type::string_type traits_string_type;
|
||||
const traits_type& traits_inst = e.get_traits();
|
||||
const traits_type& traits_inst = e.m_traits;
|
||||
|
||||
// dwa 9/13/00 suppress incorrect MSVC warning - it claims this is never
|
||||
// referenced
|
||||
@@ -149,17 +149,17 @@ iterator BOOST_REGEX_CALL re_is_set_member(iterator next,
|
||||
// try and match a range, NB only a single character can match
|
||||
if(set_->cranges)
|
||||
{
|
||||
if((e.flags() & regex_constants::collate) == 0)
|
||||
if((e.m_flags & regex_constants::collate) == 0)
|
||||
s1.assign(1, col);
|
||||
else
|
||||
s1 = traits_inst.transform(&col, &col + 1);
|
||||
for(i = 0; i < set_->cranges; ++i)
|
||||
{
|
||||
if(STR_COMP(s1, p) <= 0)
|
||||
if(STR_COMP(s1, p) >= 0)
|
||||
{
|
||||
while(*p)++p;
|
||||
++p;
|
||||
if(STR_COMP(s1, p) >= 0)
|
||||
if(STR_COMP(s1, p) <= 0)
|
||||
return set_->isnot ? next : ++next;
|
||||
}
|
||||
else
|
||||
@@ -412,7 +412,7 @@ private:
|
||||
void push_assertion(const re_syntax_base* ps, bool positive);
|
||||
void push_alt(const re_syntax_base* ps);
|
||||
void push_repeater_count(int i, repeater_count<BidiIterator>** s);
|
||||
void push_single_repeat(unsigned c, const re_repeat* r, BidiIterator last_position, int id);
|
||||
void push_single_repeat(std::size_t c, const re_repeat* r, BidiIterator last_position, int id);
|
||||
void push_non_greedy_repeat(const re_syntax_base* ps);
|
||||
|
||||
|
||||
|
||||
@@ -208,10 +208,10 @@ bool perl_matcher<BidiIterator, Allocator, traits>::find_imp()
|
||||
else
|
||||
{
|
||||
// start again:
|
||||
search_base = position = (*m_presult)[0].second;
|
||||
search_base = position = m_result[0].second;
|
||||
// If last match was null and match_not_null was not set then increment
|
||||
// our start position, otherwise we go into an infinite loop:
|
||||
if(((m_match_flags & match_not_null) == 0) && (m_presult->length() == 0))
|
||||
if(((m_match_flags & match_not_null) == 0) && (m_result.length() == 0))
|
||||
{
|
||||
if(position == last)
|
||||
return false;
|
||||
@@ -590,7 +590,7 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_long_set()
|
||||
// let the traits class do the work:
|
||||
if(position == last)
|
||||
return false;
|
||||
BidiIterator t = re_is_set_member(position, last, static_cast<const re_set_long<char_class_type>*>(pstate), re);
|
||||
BidiIterator t = re_is_set_member(position, last, static_cast<const re_set_long<char_class_type>*>(pstate), re.get_data());
|
||||
if(t != position)
|
||||
{
|
||||
pstate = pstate->next.p;
|
||||
|
||||
@@ -103,10 +103,10 @@ struct save_state_init
|
||||
template <class BidiIterator>
|
||||
struct saved_single_repeat : public saved_state
|
||||
{
|
||||
unsigned count;
|
||||
std::size_t count;
|
||||
const re_repeat* rep;
|
||||
BidiIterator last_position;
|
||||
saved_single_repeat(unsigned c, const re_repeat* r, BidiIterator lp, int arg_id)
|
||||
saved_single_repeat(std::size_t c, const re_repeat* r, BidiIterator lp, int arg_id)
|
||||
: saved_state(arg_id), count(c), rep(r), last_position(lp){}
|
||||
};
|
||||
|
||||
@@ -275,7 +275,7 @@ inline void perl_matcher<BidiIterator, Allocator, traits>::push_repeater_count(i
|
||||
}
|
||||
|
||||
template <class BidiIterator, class Allocator, class traits>
|
||||
inline void perl_matcher<BidiIterator, Allocator, traits>::push_single_repeat(unsigned c, const re_repeat* r, BidiIterator last_position, int id)
|
||||
inline void perl_matcher<BidiIterator, Allocator, traits>::push_single_repeat(std::size_t c, const re_repeat* r, BidiIterator last_position, int id)
|
||||
{
|
||||
saved_single_repeat<BidiIterator>* pmp = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state);
|
||||
--pmp;
|
||||
@@ -585,11 +585,11 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_char_repeat()
|
||||
const re_repeat* rep = static_cast<const re_repeat*>(pstate);
|
||||
assert(1 == static_cast<const re_literal*>(rep->next.p)->length);
|
||||
const char_type what = *reinterpret_cast<const char_type*>(static_cast<const re_literal*>(rep->next.p) + 1);
|
||||
unsigned count = 0;
|
||||
std::size_t count = 0;
|
||||
//
|
||||
// start by working out how much we can skip:
|
||||
//
|
||||
unsigned desired = rep->greedy ? rep->max : rep->min;
|
||||
std::size_t desired = rep->greedy ? rep->max : rep->min;
|
||||
if(::boost::is_random_access_iterator<BidiIterator>::value)
|
||||
{
|
||||
BidiIterator end = position;
|
||||
@@ -652,11 +652,11 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_set_repeat()
|
||||
#endif
|
||||
const re_repeat* rep = static_cast<const re_repeat*>(pstate);
|
||||
const unsigned char* map = static_cast<const re_set*>(rep->next.p)->_map;
|
||||
unsigned count = 0;
|
||||
std::size_t count = 0;
|
||||
//
|
||||
// start by working out how much we can skip:
|
||||
//
|
||||
unsigned desired = rep->greedy ? rep->max : rep->min;
|
||||
std::size_t desired = rep->greedy ? rep->max : rep->min;
|
||||
if(::boost::is_random_access_iterator<BidiIterator>::value)
|
||||
{
|
||||
BidiIterator end = position;
|
||||
@@ -719,17 +719,17 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_long_set_repeat()
|
||||
#endif
|
||||
const re_repeat* rep = static_cast<const re_repeat*>(pstate);
|
||||
const re_set_long<typename traits::char_class_type>* set = static_cast<const re_set_long<typename traits::char_class_type>*>(pstate->next.p);
|
||||
unsigned count = 0;
|
||||
std::size_t count = 0;
|
||||
//
|
||||
// start by working out how much we can skip:
|
||||
//
|
||||
unsigned desired = rep->greedy ? rep->max : rep->min;
|
||||
std::size_t desired = rep->greedy ? rep->max : rep->min;
|
||||
if(::boost::is_random_access_iterator<BidiIterator>::value)
|
||||
{
|
||||
BidiIterator end = position;
|
||||
std::advance(end, (std::min)((unsigned)re_detail::distance(position, last), desired));
|
||||
BidiIterator origin(position);
|
||||
while((position != end) && (position != re_is_set_member(position, last, set, re)))
|
||||
while((position != end) && (position != re_is_set_member(position, last, set, re.get_data())))
|
||||
{
|
||||
++position;
|
||||
}
|
||||
@@ -737,7 +737,7 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_long_set_repeat()
|
||||
}
|
||||
else
|
||||
{
|
||||
while((count < desired) && (position != last) && (position != re_is_set_member(position, last, set, re)))
|
||||
while((count < desired) && (position != last) && (position != re_is_set_member(position, last, set, re.get_data())))
|
||||
{
|
||||
++position;
|
||||
++count;
|
||||
@@ -926,7 +926,7 @@ bool perl_matcher<BidiIterator, Allocator, traits>::unwind_greedy_single_repeat(
|
||||
}
|
||||
|
||||
const re_repeat* rep = pmp->rep;
|
||||
unsigned count = pmp->count;
|
||||
std::size_t count = pmp->count;
|
||||
assert(rep->next.p);
|
||||
assert(rep->alt.p);
|
||||
|
||||
@@ -975,7 +975,7 @@ bool perl_matcher<BidiIterator, Allocator, traits>::unwind_slow_dot_repeat(bool
|
||||
}
|
||||
|
||||
const re_repeat* rep = pmp->rep;
|
||||
unsigned count = pmp->count;
|
||||
std::size_t count = pmp->count;
|
||||
assert(rep->type == syntax_element_dot_rep);
|
||||
assert(rep->next.p);
|
||||
assert(rep->alt.p);
|
||||
@@ -1037,7 +1037,7 @@ bool perl_matcher<BidiIterator, Allocator, traits>::unwind_fast_dot_repeat(bool
|
||||
}
|
||||
|
||||
const re_repeat* rep = pmp->rep;
|
||||
unsigned count = pmp->count;
|
||||
std::size_t count = pmp->count;
|
||||
|
||||
assert(count < rep->max);
|
||||
position = pmp->last_position;
|
||||
@@ -1089,7 +1089,7 @@ bool perl_matcher<BidiIterator, Allocator, traits>::unwind_char_repeat(bool r)
|
||||
}
|
||||
|
||||
const re_repeat* rep = pmp->rep;
|
||||
unsigned count = pmp->count;
|
||||
std::size_t count = pmp->count;
|
||||
pstate = rep->next.p;
|
||||
const char_type what = *reinterpret_cast<const char_type*>(static_cast<const re_literal*>(pstate) + 1);
|
||||
position = pmp->last_position;
|
||||
@@ -1153,7 +1153,7 @@ bool perl_matcher<BidiIterator, Allocator, traits>::unwind_short_set_repeat(bool
|
||||
}
|
||||
|
||||
const re_repeat* rep = pmp->rep;
|
||||
unsigned count = pmp->count;
|
||||
std::size_t count = pmp->count;
|
||||
pstate = rep->next.p;
|
||||
const unsigned char* map = static_cast<const re_set*>(rep->next.p)->_map;
|
||||
position = pmp->last_position;
|
||||
@@ -1217,7 +1217,7 @@ bool perl_matcher<BidiIterator, Allocator, traits>::unwind_long_set_repeat(bool
|
||||
}
|
||||
|
||||
const re_repeat* rep = pmp->rep;
|
||||
unsigned count = pmp->count;
|
||||
std::size_t count = pmp->count;
|
||||
pstate = rep->next.p;
|
||||
const re_set_long<typename traits::char_class_type>* set = static_cast<const re_set_long<typename traits::char_class_type>*>(pstate);
|
||||
position = pmp->last_position;
|
||||
@@ -1234,7 +1234,7 @@ bool perl_matcher<BidiIterator, Allocator, traits>::unwind_long_set_repeat(bool
|
||||
// wind forward until we can skip out of the repeat:
|
||||
do
|
||||
{
|
||||
if(position == re_is_set_member(position, last, set, re))
|
||||
if(position == re_is_set_member(position, last, set, re.get_data()))
|
||||
{
|
||||
// failed repeat match, discard this state and look for another:
|
||||
destroy_single_repeat();
|
||||
|
||||
@@ -637,7 +637,7 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_long_set_repeat()
|
||||
BidiIterator end = position;
|
||||
std::advance(end, (std::min)((unsigned)re_detail::distance(position, last), desired));
|
||||
BidiIterator origin(position);
|
||||
while((position != end) && (position != re_is_set_member(position, last, set, re)))
|
||||
while((position != end) && (position != re_is_set_member(position, last, set, re.get_data())))
|
||||
{
|
||||
++position;
|
||||
}
|
||||
@@ -645,7 +645,7 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_long_set_repeat()
|
||||
}
|
||||
else
|
||||
{
|
||||
while((count < desired) && (position != last) && (position != re_is_set_member(position, last, set, re)))
|
||||
while((count < desired) && (position != last) && (position != re_is_set_member(position, last, set, re.get_data())))
|
||||
{
|
||||
++position;
|
||||
++count;
|
||||
@@ -665,7 +665,7 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_long_set_repeat()
|
||||
{
|
||||
while((position != last) && (count < rep->max) && !can_start(*position, rep->_map, mask_skip))
|
||||
{
|
||||
if(position != re_is_set_member(position, last, set, re))
|
||||
if(position != re_is_set_member(position, last, set, re.get_data()))
|
||||
{
|
||||
++position;
|
||||
++count;
|
||||
@@ -685,7 +685,7 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_long_set_repeat()
|
||||
if(position == last)
|
||||
return false;
|
||||
position = save_pos;
|
||||
if(position != re_is_set_member(position, last, set, re))
|
||||
if(position != re_is_set_member(position, last, set, re.get_data()))
|
||||
{
|
||||
++position;
|
||||
++count;
|
||||
|
||||
@@ -76,7 +76,7 @@ public:
|
||||
|
||||
|
||||
|
||||
basic = basic_syntax_group | collate,
|
||||
basic = basic_syntax_group | collate | no_escape_in_lists,
|
||||
extended = no_bk_refs | collate | no_perl_ex | no_escape_in_lists,
|
||||
normal = 0,
|
||||
emacs = basic | no_char_classes | no_intervals,
|
||||
@@ -123,6 +123,8 @@ namespace regex_constants{
|
||||
bk_plus_qm = ::boost::regbase::bk_plus_qm,
|
||||
bk_vbar = ::boost::regbase::bk_vbar,
|
||||
no_intervals = ::boost::regbase::no_intervals,
|
||||
no_char_classes = ::boost::regbase::no_char_classes,
|
||||
no_escape_in_lists = ::boost::regbase::no_escape_in_lists,
|
||||
|
||||
basic = ::boost::regbase::basic,
|
||||
extended = ::boost::regbase::extended,
|
||||
|
||||
@@ -54,23 +54,22 @@ inline unsigned int regex_grep(Predicate foo,
|
||||
return count; // we've reached the end, don't try and find an extra null match.
|
||||
if(m.length() == 0)
|
||||
{
|
||||
if(m[0].second == last)
|
||||
return count;
|
||||
// we found a NULL-match, now try to find
|
||||
// a non-NULL one at the same position:
|
||||
BidiIterator last_end(m[0].second);
|
||||
if(last_end == last)
|
||||
return count;
|
||||
match_results<BidiIterator, match_allocator_type> m2(m);
|
||||
matcher.setf(match_not_null | match_continuous);
|
||||
if(matcher.find())
|
||||
{
|
||||
++count;
|
||||
last_end = m[0].second;
|
||||
if(0 == foo(m))
|
||||
return count;
|
||||
}
|
||||
else
|
||||
{
|
||||
// reset match back to where it was:
|
||||
m.set_second(last_end);
|
||||
m = m2;
|
||||
}
|
||||
matcher.unsetf((match_not_null | match_continuous) & ~flags);
|
||||
}
|
||||
|
||||
@@ -132,17 +132,19 @@ int get_default_class_id(const charT* p1, const charT* p2)
|
||||
{data+40, data+45,}, // punct
|
||||
{data+45, data+46,}, // s
|
||||
{data+45, data+50,}, // space
|
||||
{data+50, data+57,}, // unicode
|
||||
{data+57, data+58,}, // u
|
||||
{data+50, data+57,}, // unicode
|
||||
{data+57, data+62,}, // upper
|
||||
{data+62, data+63,}, // w
|
||||
{data+62, data+66,}, // word
|
||||
{data+66, data+72,}, // xdigit
|
||||
};
|
||||
static const character_pointer_range<charT>* ranges_begin = ranges;
|
||||
static const character_pointer_range<charT>* ranges_end = ranges + (sizeof(ranges)/sizeof(ranges[0]));
|
||||
|
||||
character_pointer_range<charT> t = { p1, p2, };
|
||||
const character_pointer_range<charT>* p = std::lower_bound(ranges, ranges + (sizeof(ranges)/sizeof(ranges[0])), t);
|
||||
if(t == *p)
|
||||
const character_pointer_range<charT>* p = std::lower_bound(ranges_begin, ranges_end, t);
|
||||
if((p != ranges_end) && (t == *p))
|
||||
return static_cast<int>(p - ranges);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -222,11 +222,15 @@ enum re_jump_size_type
|
||||
/*** proc re_is_set_member *********************************************
|
||||
Forward declaration: we'll need this one later...
|
||||
***********************************************************************/
|
||||
|
||||
template<class charT, class traits>
|
||||
struct regex_data;
|
||||
|
||||
template <class iterator, class charT, class traits_type, class char_classT>
|
||||
iterator BOOST_REGEX_CALL re_is_set_member(iterator next,
|
||||
iterator last,
|
||||
const re_set_long<char_classT>* set_,
|
||||
const basic_regex<charT, traits_type>& e);
|
||||
const regex_data<charT, traits_type>& e);
|
||||
|
||||
} // namespace re_detail
|
||||
|
||||
|
||||
Reference in new issue
Block a user