mirror of
https://github.com/boostorg/regex.git
synced 2025-07-29 20:17:24 +02:00
Merge branch 'develop'
# Please enter a commit message to explain why this merge is necessary, # especially if it merges an updated upstream into a topic branch. # # Lines starting with '#' will be ignored, and an empty message aborts # the commit.
This commit is contained in:
@ -18,6 +18,7 @@ All issues including closed ones can be viewed [@https://svn.boost.org/trac/boos
|
||||
[h4 Boost.Regex-5.1.1]
|
||||
|
||||
* Change to lockfree implementation of memory cache, see [@https://github.com/boostorg/regex/pull/23 PR#23].
|
||||
* Fix bug in case sensitivity change, see [@https://svn.boost.org/trac/boost/ticket/11940 #11940].
|
||||
|
||||
[h4 Boost.Regex-5.1.0 (Boost-1.60.0)]
|
||||
|
||||
|
@ -39,9 +39,14 @@
|
||||
<a name="boost_regex.background_information.history.h0"></a>
|
||||
<span class="phrase"><a name="boost_regex.background_information.history.boost_regex_5_1_1"></a></span><a class="link" href="history.html#boost_regex.background_information.history.boost_regex_5_1_1">Boost.Regex-5.1.1</a>
|
||||
</h5>
|
||||
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
|
||||
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
|
||||
<li class="listitem">
|
||||
Change to lockfree implementation of memory cache, see <a href="https://github.com/boostorg/regex/pull/23" target="_top">PR#23</a>.
|
||||
</li></ul></div>
|
||||
</li>
|
||||
<li class="listitem">
|
||||
Fix bug in case sensitivity change, see <a href="https://svn.boost.org/trac/boost/ticket/11940" target="_top">#11940</a>.
|
||||
</li>
|
||||
</ul></div>
|
||||
<h5>
|
||||
<a name="boost_regex.background_information.history.h1"></a>
|
||||
<span class="phrase"><a name="boost_regex.background_information.history.boost_regex_5_1_0_boost_1_60_0"></a></span><a class="link" href="history.html#boost_regex.background_information.history.boost_regex_5_1_0_boost_1_60_0">Boost.Regex-5.1.0
|
||||
|
@ -178,6 +178,17 @@
|
||||
It's more efficient to work this way, but may not be the behavior you want
|
||||
in all situations.
|
||||
</li>
|
||||
<li class="listitem">
|
||||
There are situations where full matches are found even though partial matches
|
||||
are also possible: for example if the partial string terminates with "abc"
|
||||
and the regular expression is "\w+", then a full match is found
|
||||
even though there may be more alphabetical characters to come. This particular
|
||||
case can be detected by checking if the match found terminates at the end
|
||||
of current input string. However, there are situations where that is not
|
||||
possible: for example an expression such as "abc.*123" may always
|
||||
have longer matches available since it could conceivably match the entire
|
||||
input string (no matter how long it may be).
|
||||
</li>
|
||||
</ul></div>
|
||||
<p>
|
||||
The following example tests to see whether the text could be a valid credit
|
||||
|
@ -221,7 +221,7 @@
|
||||
</p>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"><p><small>Last revised: January 10, 2016 at 18:43:41 GMT</small></p></td>
|
||||
<td align="left"><p><small>Last revised: March 14, 2016 at 19:20:20 GMT</small></p></td>
|
||||
<td align="right"><div class="copyright-footer"></div></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
|
@ -34,6 +34,9 @@ imperfect behavior:
|
||||
|
||||
* There are some expressions, such as ".\*abc" that will always produce a partial match. This problem can be reduced by careful construction of the regular expressions used, or by setting flags like match_not_dot_newline so that expressions like .\* can't match past line boundaries.
|
||||
* Boost.Regex currently prefers leftmost matches to full matches, so for example matching "abc|b" against "ab" produces a partial match against the "ab" rather than a full match against "b". It's more efficient to work this way, but may not be the behavior you want in all situations.
|
||||
* There are situations where full matches are found even though partial matches are also possible: for example if the partial string terminates with "abc" and the regular expression is "\w+", then a full match is found
|
||||
even though there may be more alphabetical characters to come. This particular case can be detected by checking if the match found terminates at the end of current input string. However, there are situations where
|
||||
that is not possible: for example an expression such as "abc.*123" may always have longer matches available since it could conceivably match the entire input string (no matter how long it may be).
|
||||
|
||||
The following example tests to see whether the text could be a valid
|
||||
credit card number, as the user presses a key, the character entered
|
||||
|
@ -152,7 +152,7 @@ public:
|
||||
char_class_type lookup_classname(const char_type* p1, const char_type* p2) const;
|
||||
string_type lookup_collatename(const char_type* p1, const char_type* p2) const;
|
||||
bool isctype(char_type c, char_class_type f) const;
|
||||
int toi(const char_type*& p1, const char_type* p2, int radix)const
|
||||
boost::intmax_t toi(const char_type*& p1, const char_type* p2, int radix)const
|
||||
{
|
||||
return BOOST_REGEX_DETAIL_NS::global_toi(p1, p2, radix, *this);
|
||||
}
|
||||
|
@ -38,6 +38,21 @@ namespace BOOST_REGEX_DETAIL_NS{
|
||||
#pragma warning(disable:4244 4800)
|
||||
#endif
|
||||
|
||||
inline boost::intmax_t umax(mpl::false_ const&)
|
||||
{
|
||||
// Get out clause here, just in case numeric_limits is unspecialized:
|
||||
return std::numeric_limits<boost::intmax_t>::is_specialized ? (std::numeric_limits<boost::intmax_t>::max)() : INT_MAX;
|
||||
}
|
||||
inline boost::intmax_t umax(mpl::true_ const&)
|
||||
{
|
||||
return (std::numeric_limits<std::size_t>::max)();
|
||||
}
|
||||
|
||||
inline boost::intmax_t umax()
|
||||
{
|
||||
return umax(mpl::bool_<std::numeric_limits<boost::intmax_t>::digits >= std::numeric_limits<std::size_t>::digits>());
|
||||
}
|
||||
|
||||
template <class charT, class traits>
|
||||
class basic_regex_parser : public basic_regex_creator<charT, traits>
|
||||
{
|
||||
@ -868,7 +883,7 @@ escape_type_class_jump:
|
||||
return false;
|
||||
}
|
||||
const charT* pc = m_position;
|
||||
int i = this->m_traits.toi(pc, m_end, 10);
|
||||
boost::intmax_t i = this->m_traits.toi(pc, m_end, 10);
|
||||
if((i < 0) && syn_end)
|
||||
{
|
||||
// Check for a named capture, get the leftmost one if there is more than one:
|
||||
@ -1075,7 +1090,7 @@ bool basic_regex_parser<charT, traits>::parse_repeat_range(bool isbasic)
|
||||
// parse a repeat-range:
|
||||
//
|
||||
std::size_t min, max;
|
||||
int v;
|
||||
boost::intmax_t v;
|
||||
// skip whitespace:
|
||||
while((m_position != m_end) && this->m_traits.isctype(*m_position, this->m_mask_space))
|
||||
++m_position;
|
||||
@ -1094,7 +1109,7 @@ bool basic_regex_parser<charT, traits>::parse_repeat_range(bool isbasic)
|
||||
// get min:
|
||||
v = this->m_traits.toi(m_position, m_end, 10);
|
||||
// skip whitespace:
|
||||
if(v < 0)
|
||||
if((v < 0) || (v > umax()))
|
||||
{
|
||||
if(this->flags() & (regbase::main_option_type | regbase::no_perl_ex))
|
||||
{
|
||||
@ -1120,7 +1135,7 @@ bool basic_regex_parser<charT, traits>::parse_repeat_range(bool isbasic)
|
||||
while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_brace) --m_position;
|
||||
return parse_literal();
|
||||
}
|
||||
min = v;
|
||||
min = static_cast<std::size_t>(v);
|
||||
// see if we have a comma:
|
||||
if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_comma)
|
||||
{
|
||||
@ -1143,7 +1158,7 @@ bool basic_regex_parser<charT, traits>::parse_repeat_range(bool isbasic)
|
||||
}
|
||||
// get the value if any:
|
||||
v = this->m_traits.toi(m_position, m_end, 10);
|
||||
max = (v >= 0) ? (std::size_t)v : (std::numeric_limits<std::size_t>::max)();
|
||||
max = ((v >= 0) && (v < umax())) ? (std::size_t)v : (std::numeric_limits<std::size_t>::max)();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1665,19 +1680,19 @@ digraph<charT> basic_regex_parser<charT, traits>::get_next_set_literal(basic_cha
|
||||
// does a value fit in the specified charT type?
|
||||
//
|
||||
template <class charT>
|
||||
bool valid_value(charT, int v, const mpl::true_&)
|
||||
bool valid_value(charT, boost::intmax_t v, const mpl::true_&)
|
||||
{
|
||||
return (v >> (sizeof(charT) * CHAR_BIT)) == 0;
|
||||
}
|
||||
template <class charT>
|
||||
bool valid_value(charT, int, const mpl::false_&)
|
||||
bool valid_value(charT, boost::intmax_t, const mpl::false_&)
|
||||
{
|
||||
return true; // v will alsways fit in a charT
|
||||
}
|
||||
template <class charT>
|
||||
bool valid_value(charT c, int v)
|
||||
bool valid_value(charT c, boost::intmax_t v)
|
||||
{
|
||||
return valid_value(c, v, mpl::bool_<(sizeof(charT) < sizeof(int))>());
|
||||
return valid_value(c, v, mpl::bool_<(sizeof(charT) < sizeof(boost::intmax_t))>());
|
||||
}
|
||||
|
||||
template <class charT, class traits>
|
||||
@ -1753,10 +1768,10 @@ charT basic_regex_parser<charT, traits>::unescape_character()
|
||||
fail(regex_constants::error_escape, m_position - m_base, "Missing } in hexadecimal escape sequence.");
|
||||
return result;
|
||||
}
|
||||
int i = this->m_traits.toi(m_position, m_end, 16);
|
||||
boost::intmax_t i = this->m_traits.toi(m_position, m_end, 16);
|
||||
if((m_position == m_end)
|
||||
|| (i < 0)
|
||||
|| ((std::numeric_limits<charT>::is_specialized) && (i > (int)(std::numeric_limits<charT>::max)()))
|
||||
|| ((std::numeric_limits<charT>::is_specialized) && (i > (boost::intmax_t)(std::numeric_limits<charT>::max)()))
|
||||
|| (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_brace))
|
||||
{
|
||||
// Rewind to start of escape:
|
||||
@ -1771,7 +1786,7 @@ charT basic_regex_parser<charT, traits>::unescape_character()
|
||||
else
|
||||
{
|
||||
std::ptrdiff_t len = (std::min)(static_cast<std::ptrdiff_t>(2), static_cast<std::ptrdiff_t>(m_end - m_position));
|
||||
int i = this->m_traits.toi(m_position, m_position + len, 16);
|
||||
boost::intmax_t i = this->m_traits.toi(m_position, m_position + len, 16);
|
||||
if((i < 0)
|
||||
|| !valid_value(charT(0), i))
|
||||
{
|
||||
@ -1790,7 +1805,7 @@ charT basic_regex_parser<charT, traits>::unescape_character()
|
||||
// followed by up to 3 octal digits:
|
||||
std::ptrdiff_t len = (std::min)(::boost::BOOST_REGEX_DETAIL_NS::distance(m_position, m_end), static_cast<std::ptrdiff_t>(4));
|
||||
const charT* bp = m_position;
|
||||
int val = this->m_traits.toi(bp, bp + 1, 8);
|
||||
boost::intmax_t val = this->m_traits.toi(bp, bp + 1, 8);
|
||||
if(val != 0)
|
||||
{
|
||||
// Rewind to start of escape:
|
||||
@ -1801,7 +1816,7 @@ charT basic_regex_parser<charT, traits>::unescape_character()
|
||||
return result;
|
||||
}
|
||||
val = this->m_traits.toi(m_position, m_position + len, 8);
|
||||
if(val < 0)
|
||||
if((val < 0) || (val > (boost::intmax_t)(std::numeric_limits<charT>::max)()))
|
||||
{
|
||||
// Rewind to start of escape:
|
||||
--m_position;
|
||||
@ -1874,7 +1889,7 @@ bool basic_regex_parser<charT, traits>::parse_backref()
|
||||
{
|
||||
BOOST_ASSERT(m_position != m_end);
|
||||
const charT* pc = m_position;
|
||||
int i = this->m_traits.toi(pc, pc + 1, 10);
|
||||
boost::intmax_t i = this->m_traits.toi(pc, pc + 1, 10);
|
||||
if((i == 0) || (((this->flags() & regbase::main_option_type) == regbase::perl_syntax_group) && (this->flags() & regbase::no_bk_refs)))
|
||||
{
|
||||
// not a backref at all but an octal escape sequence:
|
||||
@ -1996,7 +2011,7 @@ bool basic_regex_parser<charT, traits>::parse_perl_extension()
|
||||
int max_mark = m_max_mark;
|
||||
m_mark_reset = -1;
|
||||
m_max_mark = m_mark_count;
|
||||
int v;
|
||||
boost::intmax_t v;
|
||||
//
|
||||
// select the actual extension used:
|
||||
//
|
||||
|
@ -1027,11 +1027,11 @@ public:
|
||||
return m_pimpl->isctype(c, f);
|
||||
#endif
|
||||
}
|
||||
int toi(const charT*& p1, const charT* p2, int radix)const;
|
||||
boost::intmax_t toi(const charT*& p1, const charT* p2, int radix)const;
|
||||
int value(charT c, int radix)const
|
||||
{
|
||||
const charT* pc = &c;
|
||||
return toi(pc, pc + 1, radix);
|
||||
return (int)toi(pc, pc + 1, radix);
|
||||
}
|
||||
locale_type imbue(locale_type l)
|
||||
{
|
||||
@ -1069,7 +1069,7 @@ private:
|
||||
|
||||
|
||||
template <class charT>
|
||||
int cpp_regex_traits<charT>::toi(const charT*& first, const charT* last, int radix)const
|
||||
boost::intmax_t cpp_regex_traits<charT>::toi(const charT*& first, const charT* last, int radix)const
|
||||
{
|
||||
BOOST_REGEX_DETAIL_NS::parser_buf<charT> sbuf; // buffer for parsing numbers.
|
||||
std::basic_istream<charT> is(&sbuf); // stream for parsing numbers.
|
||||
@ -1082,7 +1082,7 @@ int cpp_regex_traits<charT>::toi(const charT*& first, const charT* last, int rad
|
||||
if(std::abs(radix) == 16) is >> std::hex;
|
||||
else if(std::abs(radix) == 8) is >> std::oct;
|
||||
else is >> std::dec;
|
||||
int val;
|
||||
boost::intmax_t val;
|
||||
if(is >> val)
|
||||
{
|
||||
first = first + ((last - first) - sbuf.in_avail());
|
||||
|
@ -157,7 +157,7 @@ bool cpp_regex_traits_implementation<BOOST_REGEX_CHAR_T>::isctype(const BOOST_RE
|
||||
#endif
|
||||
} // namespace
|
||||
template BOOST_REGEX_DECL
|
||||
int cpp_regex_traits<BOOST_REGEX_CHAR_T>::toi(const BOOST_REGEX_CHAR_T*& first, const BOOST_REGEX_CHAR_T* last, int radix)const;
|
||||
boost::intmax_t cpp_regex_traits<BOOST_REGEX_CHAR_T>::toi(const BOOST_REGEX_CHAR_T*& first, const BOOST_REGEX_CHAR_T* last, int radix)const;
|
||||
template BOOST_REGEX_DECL
|
||||
std::string cpp_regex_traits<BOOST_REGEX_CHAR_T>::catalog_name(const std::string& name);
|
||||
template BOOST_REGEX_DECL
|
||||
|
@ -537,6 +537,7 @@ private:
|
||||
bool unwind_recursion_pop(bool);
|
||||
bool unwind_commit(bool);
|
||||
bool unwind_then(bool);
|
||||
bool unwind_case(bool);
|
||||
void destroy_single_repeat();
|
||||
void push_matched_paren(int index, const sub_match<BidiIterator>& sub);
|
||||
void push_recursion_stopper();
|
||||
@ -547,6 +548,7 @@ private:
|
||||
void push_non_greedy_repeat(const re_syntax_base* ps);
|
||||
void push_recursion(int idx, const re_syntax_base* p, results_type* presults);
|
||||
void push_recursion_pop();
|
||||
void push_case_change(bool);
|
||||
|
||||
// pointer to base of stack:
|
||||
saved_state* m_stack_base;
|
||||
|
@ -206,7 +206,7 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_imp()
|
||||
search_base = base;
|
||||
state_count = 0;
|
||||
m_match_flags |= regex_constants::match_all;
|
||||
m_presult->set_size((m_match_flags & match_nosubs) ? 1 : 1 + re.mark_count(), search_base, last);
|
||||
m_presult->set_size((m_match_flags & match_nosubs) ? 1u : static_cast<typename results_type::size_type>(1u + re.mark_count()), search_base, last);
|
||||
m_presult->set_base(base);
|
||||
m_presult->set_named_subs(this->re.get_named_subs());
|
||||
if(m_match_flags & match_posix)
|
||||
@ -268,7 +268,7 @@ bool perl_matcher<BidiIterator, Allocator, traits>::find_imp()
|
||||
// reset our state machine:
|
||||
search_base = position = base;
|
||||
pstate = re.get_first_state();
|
||||
m_presult->set_size((m_match_flags & match_nosubs) ? 1 : 1 + re.mark_count(), base, last);
|
||||
m_presult->set_size((m_match_flags & match_nosubs) ? 1u : static_cast<typename results_type::size_type>(1u + re.mark_count()), base, last);
|
||||
m_presult->set_base(base);
|
||||
m_presult->set_named_subs(this->re.get_named_subs());
|
||||
m_match_flags |= regex_constants::match_init;
|
||||
@ -287,13 +287,13 @@ bool perl_matcher<BidiIterator, Allocator, traits>::find_imp()
|
||||
++position;
|
||||
}
|
||||
// reset $` start:
|
||||
m_presult->set_size((m_match_flags & match_nosubs) ? 1 : 1 + re.mark_count(), search_base, last);
|
||||
m_presult->set_size((m_match_flags & match_nosubs) ? 1u : static_cast<typename results_type::size_type>(1u + re.mark_count()), search_base, last);
|
||||
//if((base != search_base) && (base == backstop))
|
||||
// m_match_flags |= match_prev_avail;
|
||||
}
|
||||
if(m_match_flags & match_posix)
|
||||
{
|
||||
m_result.set_size(1 + re.mark_count(), base, last);
|
||||
m_result.set_size(static_cast<typename results_type::size_type>(1u + re.mark_count()), base, last);
|
||||
m_result.set_base(base);
|
||||
}
|
||||
|
||||
@ -793,15 +793,6 @@ inline bool perl_matcher<BidiIterator, Allocator, traits>::match_assert_backref(
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class BidiIterator, class Allocator, class traits>
|
||||
bool perl_matcher<BidiIterator, Allocator, traits>::match_toggle_case()
|
||||
{
|
||||
// change our case sensitivity:
|
||||
this->icase = static_cast<const re_case*>(pstate)->icase;
|
||||
pstate = pstate->next.p;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class BidiIterator, class Allocator, class traits>
|
||||
bool perl_matcher<BidiIterator, Allocator, traits>::match_fail()
|
||||
{
|
||||
|
@ -138,6 +138,12 @@ struct saved_recursion : public saved_state
|
||||
Results results;
|
||||
};
|
||||
|
||||
struct saved_change_case : public saved_state
|
||||
{
|
||||
bool icase;
|
||||
saved_change_case(bool c) : saved_state(18), icase(c) {}
|
||||
};
|
||||
|
||||
template <class BidiIterator, class Allocator, class traits>
|
||||
bool perl_matcher<BidiIterator, Allocator, traits>::match_all_states()
|
||||
{
|
||||
@ -242,6 +248,22 @@ inline void perl_matcher<BidiIterator, Allocator, traits>::push_matched_paren(in
|
||||
m_backup_state = pmp;
|
||||
}
|
||||
|
||||
template <class BidiIterator, class Allocator, class traits>
|
||||
inline void perl_matcher<BidiIterator, Allocator, traits>::push_case_change(bool c)
|
||||
{
|
||||
//BOOST_ASSERT(index);
|
||||
saved_change_case* pmp = static_cast<saved_change_case*>(m_backup_state);
|
||||
--pmp;
|
||||
if(pmp < m_stack_base)
|
||||
{
|
||||
extend_stack();
|
||||
pmp = static_cast<saved_change_case*>(m_backup_state);
|
||||
--pmp;
|
||||
}
|
||||
(void) new (pmp)saved_change_case(c);
|
||||
m_backup_state = pmp;
|
||||
}
|
||||
|
||||
template <class BidiIterator, class Allocator, class traits>
|
||||
inline void perl_matcher<BidiIterator, Allocator, traits>::push_recursion_stopper()
|
||||
{
|
||||
@ -347,6 +369,16 @@ inline void perl_matcher<BidiIterator, Allocator, traits>::push_recursion(int id
|
||||
m_backup_state = pmp;
|
||||
}
|
||||
|
||||
template <class BidiIterator, class Allocator, class traits>
|
||||
bool perl_matcher<BidiIterator, Allocator, traits>::match_toggle_case()
|
||||
{
|
||||
// change our case sensitivity:
|
||||
push_case_change(this->icase);
|
||||
this->icase = static_cast<const re_case*>(pstate)->icase;
|
||||
pstate = pstate->next.p;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class BidiIterator, class Allocator, class traits>
|
||||
bool perl_matcher<BidiIterator, Allocator, traits>::match_startmark()
|
||||
{
|
||||
@ -1142,6 +1174,7 @@ bool perl_matcher<BidiIterator, Allocator, traits>::unwind(bool have_match)
|
||||
&perl_matcher<BidiIterator, Allocator, traits>::unwind_recursion_pop,
|
||||
&perl_matcher<BidiIterator, Allocator, traits>::unwind_commit,
|
||||
&perl_matcher<BidiIterator, Allocator, traits>::unwind_then,
|
||||
&perl_matcher<BidiIterator, Allocator, traits>::unwind_case,
|
||||
};
|
||||
|
||||
m_recursive_result = have_match;
|
||||
@ -1170,6 +1203,16 @@ bool perl_matcher<BidiIterator, Allocator, traits>::unwind_end(bool)
|
||||
return false; // end of stack nothing more to search
|
||||
}
|
||||
|
||||
template <class BidiIterator, class Allocator, class traits>
|
||||
bool perl_matcher<BidiIterator, Allocator, traits>::unwind_case(bool)
|
||||
{
|
||||
saved_change_case* pmp = static_cast<saved_change_case*>(m_backup_state);
|
||||
icase = pmp->icase;
|
||||
boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp++);
|
||||
m_backup_state = pmp;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class BidiIterator, class Allocator, class traits>
|
||||
bool perl_matcher<BidiIterator, Allocator, traits>::unwind_paren(bool have_match)
|
||||
{
|
||||
|
@ -289,11 +289,13 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_alt()
|
||||
BidiIterator oldposition(position);
|
||||
const re_syntax_base* old_pstate = jmp->alt.p;
|
||||
pstate = pstate->next.p;
|
||||
bool oldcase = icase;
|
||||
m_have_then = false;
|
||||
if(!match_all_states())
|
||||
{
|
||||
pstate = old_pstate;
|
||||
position = oldposition;
|
||||
icase = oldcase;
|
||||
if(m_have_then)
|
||||
{
|
||||
m_can_backtrack = true;
|
||||
@ -1036,6 +1038,20 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_then()
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class BidiIterator, class Allocator, class traits>
|
||||
bool perl_matcher<BidiIterator, Allocator, traits>::match_toggle_case()
|
||||
{
|
||||
// change our case sensitivity:
|
||||
bool oldcase = this->icase;
|
||||
this->icase = static_cast<const re_case*>(pstate)->icase;
|
||||
pstate = pstate->next.p;
|
||||
bool result = match_all_states();
|
||||
this->icase = oldcase;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <class BidiIterator, class Allocator, class traits>
|
||||
bool perl_matcher<BidiIterator, Allocator, traits>::skip_until_paren(int index, bool have_match)
|
||||
{
|
||||
|
@ -86,7 +86,7 @@ struct trivial_format_traits
|
||||
}
|
||||
int toi(const charT*& p1, const charT* p2, int radix)const
|
||||
{
|
||||
return global_toi(p1, p2, radix, *this);
|
||||
return (int)global_toi(p1, p2, radix, *this);
|
||||
}
|
||||
};
|
||||
|
||||
@ -165,7 +165,7 @@ private:
|
||||
std::vector<char_type> v(i, j);
|
||||
const char_type* start = &v[0];
|
||||
const char_type* pos = start;
|
||||
int r = m_traits.toi(pos, &v[0] + v.size(), base);
|
||||
int r = (int)m_traits.toi(pos, &v[0] + v.size(), base);
|
||||
std::advance(i, pos - start);
|
||||
return r;
|
||||
}
|
||||
|
@ -109,7 +109,7 @@ struct default_wrapper : public BaseT
|
||||
{
|
||||
return ((c & 0x7f) == c) ? get_default_escape_syntax_type(static_cast<char>(c)) : ::boost::regex_constants::escape_type_identity;
|
||||
}
|
||||
int toi(const char_type*& p1, const char_type* p2, int radix)const
|
||||
boost::intmax_t toi(const char_type*& p1, const char_type* p2, int radix)const
|
||||
{
|
||||
return ::boost::BOOST_REGEX_DETAIL_NS::global_toi(p1, p2, radix, *this);
|
||||
}
|
||||
|
@ -304,13 +304,13 @@ int global_value(charT c)
|
||||
return -1;
|
||||
}
|
||||
template <class charT, class traits>
|
||||
int global_toi(const charT*& p1, const charT* p2, int radix, const traits& t)
|
||||
boost::intmax_t global_toi(const charT*& p1, const charT* p2, int radix, const traits& t)
|
||||
{
|
||||
(void)t; // warning suppression
|
||||
int next_value = t.value(*p1, radix);
|
||||
boost::intmax_t next_value = t.value(*p1, radix);
|
||||
if((p1 == p2) || (next_value < 0) || (next_value >= radix))
|
||||
return -1;
|
||||
int result = 0;
|
||||
boost::intmax_t result = 0;
|
||||
while(p1 != p2)
|
||||
{
|
||||
next_value = t.value(*p1, radix);
|
||||
|
@ -640,13 +640,13 @@ public:
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
int toi(const charT*& p1, const charT* p2, int radix)const
|
||||
boost::intmax_t toi(const charT*& p1, const charT* p2, int radix)const
|
||||
{
|
||||
return ::boost::BOOST_REGEX_DETAIL_NS::global_toi(p1, p2, radix, *this);
|
||||
}
|
||||
int value(charT c, int radix)const
|
||||
{
|
||||
int result = ::boost::BOOST_REGEX_DETAIL_NS::global_value(c);
|
||||
int result = (int)::boost::BOOST_REGEX_DETAIL_NS::global_value(c);
|
||||
return result < radix ? result : -1;
|
||||
}
|
||||
locale_type imbue(locale_type l)
|
||||
|
@ -153,6 +153,7 @@ test-suite regex
|
||||
[ link concepts/concept_check.cpp ../build//boost_regex ]
|
||||
[ link concepts/icu_concept_check.cpp ../build//boost_regex ]
|
||||
[ link concepts/range_concept_check.cpp ../build//boost_regex ]
|
||||
[ run concepts/test_bug_11988.cpp ../build//boost_regex ]
|
||||
|
||||
[ run
|
||||
# sources
|
||||
|
115
test/concepts/test_bug_11988.cpp
Normal file
115
test/concepts/test_bug_11988.cpp
Normal file
@ -0,0 +1,115 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2016
|
||||
* John Maddock
|
||||
*
|
||||
* Use, modification and distribution are subject to the
|
||||
* Boost Software License, Version 1.0. (See accompanying file
|
||||
* LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
*/
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#ifndef BOOST_NO_CXX11_CHAR32_T
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace boost {
|
||||
|
||||
std::size_t hash_value(char32_t const& c) { return c; }
|
||||
|
||||
}
|
||||
|
||||
#include <boost/regex.hpp>
|
||||
|
||||
struct char32_traits
|
||||
{
|
||||
typedef char32_t char_type;
|
||||
typedef std::size_t size_type;
|
||||
typedef std::vector<char32_t> string_type;
|
||||
typedef int locale_type; // not used
|
||||
typedef unsigned char_class_type;
|
||||
|
||||
static size_type length(const char32_t* p)
|
||||
{
|
||||
size_type result = 0;
|
||||
while(*p)
|
||||
{
|
||||
++p;
|
||||
++result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
static char_type translate(char_type c) { return c; }
|
||||
static char_type translate_nocase(char_type c) { return c; }
|
||||
static string_type transform(const char32_t* p1, const char32_t* p2)
|
||||
{
|
||||
return string_type(p1, p2);
|
||||
}
|
||||
static string_type transform_primary(const char32_t* p1, const char32_t* p2)
|
||||
{
|
||||
return string_type(p1, p2);
|
||||
}
|
||||
static char_class_type lookup_classname(const char32_t* p1, const char32_t* p2)
|
||||
{
|
||||
std::string s(p1, p2);
|
||||
return boost::c_regex_traits<char>::lookup_classname(s.c_str(), s.c_str() + s.length());
|
||||
return 0;
|
||||
}
|
||||
static string_type lookup_collatename(const char32_t* p1, const char32_t* p2)
|
||||
{
|
||||
return string_type(p1, p2);
|
||||
}
|
||||
static bool isctype(char_type c, char_class_type t)
|
||||
{
|
||||
if(c < 0xff)
|
||||
return boost::c_regex_traits<char>::isctype(c, t);
|
||||
return false;
|
||||
}
|
||||
static boost::intmax_t value(char_type c, int radix)
|
||||
{
|
||||
switch(radix)
|
||||
{
|
||||
case 8:
|
||||
if((c >= '0') && (c <= '7'))
|
||||
return c - '0';
|
||||
break;
|
||||
case 10:
|
||||
if((c >= '0') && (c <= '9'))
|
||||
return c - '0';
|
||||
break;
|
||||
case 16:
|
||||
if((c >= '0') && (c <= '9'))
|
||||
return c - '0';
|
||||
if((c >= 'a') && (c <= 'f'))
|
||||
return (c - 'a') + 10;
|
||||
if((c >= 'A') && (c <= 'F'))
|
||||
return (c - 'A') + 10;
|
||||
break;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
static locale_type imbue(locale_type) { return 0; }
|
||||
static locale_type getloc() { return 0; }
|
||||
};
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
char32_t big_char[] = { 0xF, 0xFF, 0xFFF, 0xFFFF, 0xFFFFF, 0xFFFFFF, 0xFFFFFFF, 0xFFFFFFFF, 0 };
|
||||
|
||||
boost::basic_regex<char32_t, char32_traits> e(U"\\x{F}\\x{FF}\\x{FFF}\\x{FFFF}\\x{FFFFF}\\x{FFFFFF}\\x{FFFFFFF}\\x{FFFFFFFF}");
|
||||
|
||||
if(!regex_match(big_char, e))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int main() { return 0; }
|
||||
|
||||
#endif
|
@ -245,6 +245,10 @@ void test_options2()
|
||||
TEST_REGEX_SEARCH("a(?i:b)*c", perl, "aBBc", match_default, make_array(0, 4, -2, -2));
|
||||
TEST_REGEX_SEARCH("a(?i:b)*c", perl, "aBC", match_default, make_array(-2, -2));
|
||||
TEST_REGEX_SEARCH("a(?i:b)*c", perl, "aBBC", match_default, make_array(-2, -2));
|
||||
TEST_REGEX_SEARCH("(?i:j)|h", perl, "J", match_default, make_array(0, 1, -2, -2));
|
||||
TEST_REGEX_SEARCH("(?i:j)|h", perl, "j", match_default, make_array(0, 1, -2, -2));
|
||||
TEST_REGEX_SEARCH("(?i:j)|h", perl, "h", match_default, make_array(0, 1, -2, -2));
|
||||
TEST_REGEX_SEARCH("(?i:j)|h", perl, "H", match_default, make_array(-2, -2));
|
||||
|
||||
TEST_REGEX_SEARCH("a(?=b(?i)c)\\w\\wd", perl, "abcd", match_default, make_array(0, 4, -2, -2));
|
||||
TEST_REGEX_SEARCH("a(?=b(?i)c)\\w\\wd", perl, "abCd", match_default, make_array(0, 4, -2, -2));
|
||||
|
Reference in New Issue
Block a user