Merge bug fixes from Trunk - see history for full details.

[SVN r58234]
This commit is contained in:
John Maddock
2009-12-08 12:42:33 +00:00
parent 95ddff1f01
commit ae79f29895
133 changed files with 1893 additions and 933 deletions

View File

@ -747,6 +747,46 @@ struct RegexConcept
};
#ifndef BOOST_REGEX_TEST_STD
template <class M>
struct functor1
{
typedef typename M::char_type char_type;
const char_type* operator()(const M&)
{
static const char_type c = static_cast<char_type>(0);
return &c;
}
};
template <class M>
struct functor1b
{
typedef typename M::char_type char_type;
std::vector<char_type> operator()(const M&)
{
static const std::vector<char_type> c;
return c;
}
};
template <class M>
struct functor2
{
template <class O>
O operator()(const M& /*m*/, O i)
{
return i;
}
};
template <class M>
struct functor3
{
template <class O>
O operator()(const M& /*m*/, O i, regex_constants::match_flag_type)
{
return i;
}
};
//
// BoostRegexConcept:
// Test every interface in the Boost implementation:
@ -764,6 +804,7 @@ struct BoostRegexConcept
typedef std::basic_string<value_type> string_type;
typedef typename Regex::const_iterator const_iterator;
typedef bidirectional_iterator_archetype<value_type> BidiIterator;
typedef output_iterator_archetype<value_type> OutputIterator;
typedef global_regex_namespace::sub_match<BidiIterator> sub_match_type;
typedef global_regex_namespace::match_results<BidiIterator> match_results_type;
@ -884,6 +925,58 @@ struct BoostRegexConcept
m_stream << m_sub;
m_stream << m_cresults;
#endif
//
// Extended formatting with a functor:
//
regex_constants::match_flag_type f = regex_constants::match_default;
OutputIterator out = static_object<OutputIterator>::get();
functor3<match_results_type> func3;
out = regex_format(out, m_cresults, func3, f);
out = regex_format(out, m_cresults, func3);
functor2<match_results_type> func2;
out = regex_format(out, m_cresults, func2, f);
out = regex_format(out, m_cresults, func2);
functor1<match_results_type> func1;
out = regex_format(out, m_cresults, func1, f);
out = regex_format(out, m_cresults, func1);
m_string += regex_format(m_cresults, func3, f);
m_string += regex_format(m_cresults, func3);
m_string += regex_format(m_cresults, func2, f);
m_string += regex_format(m_cresults, func2);
m_string += regex_format(m_cresults, func1, f);
m_string += regex_format(m_cresults, func1);
out = m_cresults.format(out, func3, f);
out = m_cresults.format(out, func3);
out = m_cresults.format(out, func2, f);
out = m_cresults.format(out, func2);
out = m_cresults.format(out, func1, f);
out = m_cresults.format(out, func1);
m_string += m_cresults.format(func3, f);
m_string += m_cresults.format(func3);
m_string += m_cresults.format(func2, f);
m_string += m_cresults.format(func2);
m_string += m_cresults.format(func1, f);
m_string += m_cresults.format(func1);
out = regex_replace(out, m_in, m_in, ce, func3, f);
out = regex_replace(out, m_in, m_in, ce, func3);
out = regex_replace(out, m_in, m_in, ce, func2, f);
out = regex_replace(out, m_in, m_in, ce, func2);
out = regex_replace(out, m_in, m_in, ce, func1, f);
out = regex_replace(out, m_in, m_in, ce, func1);
functor3<match_results<typename string_type::const_iterator> > func3s;
functor2<match_results<typename string_type::const_iterator> > func2s;
functor1<match_results<typename string_type::const_iterator> > func1s;
m_string += regex_replace(m_string, ce, func3s, f);
m_string += regex_replace(m_string, ce, func3s);
m_string += regex_replace(m_string, ce, func2s, f);
m_string += regex_replace(m_string, ce, func2s);
m_string += regex_replace(m_string, ce, func1s, f);
m_string += regex_replace(m_string, ce, func1s);
}
std::basic_ostream<value_type> m_stream;
@ -893,6 +986,7 @@ struct BoostRegexConcept
const value_type m_char;
match_results_type m_results;
const match_results_type m_cresults;
BidiIterator m_in;
BoostRegexConcept();
BoostRegexConcept(const BoostRegexConcept&);

View File

@ -92,6 +92,12 @@
#if defined(_MSC_VER) && !defined(_MSC_EXTENSIONS)
# define BOOST_REGEX_NO_EXTERNAL_TEMPLATES
#endif
/*
* Shared regex lib will crash without this, frankly it looks a lot like a gcc bug:
*/
#if defined(__MINGW32__)
# define BOOST_REGEX_NO_EXTERNAL_TEMPLATES
#endif
/*
* If there isn't good enough wide character support then there will

View File

@ -376,7 +376,7 @@ inline u32regex make_u32regex(const std::basic_string<C, T, A>& s, boost::regex_
//
// Construction from ICU string type:
//
inline u32regex make_u32regex(const UnicodeString& s, boost::regex_constants::syntax_option_type opt = boost::regex_constants::perl)
inline u32regex make_u32regex(const U_NAMESPACE_QUALIFIER UnicodeString& s, boost::regex_constants::syntax_option_type opt = boost::regex_constants::perl)
{
return re_detail::do_make_u32regex(s.getBuffer(), s.getBuffer() + s.length(), opt, static_cast<boost::mpl::int_<2> const*>(0));
}
@ -498,7 +498,7 @@ inline bool u32regex_match(const std::wstring& s,
return re_detail::do_regex_match(s.begin(), s.end(), m, e, flags, static_cast<mpl::int_<sizeof(wchar_t)> const*>(0));
}
#endif
inline bool u32regex_match(const UnicodeString& s,
inline bool u32regex_match(const U_NAMESPACE_QUALIFIER UnicodeString& s,
match_results<const UChar*>& m,
const u32regex& e,
match_flag_type flags = match_default)
@ -562,7 +562,7 @@ inline bool u32regex_match(const std::wstring& s,
return re_detail::do_regex_match(s.begin(), s.end(), m, e, flags, static_cast<mpl::int_<sizeof(wchar_t)> const*>(0));
}
#endif
inline bool u32regex_match(const UnicodeString& s,
inline bool u32regex_match(const U_NAMESPACE_QUALIFIER UnicodeString& s,
const u32regex& e,
match_flag_type flags = match_default)
{
@ -683,7 +683,7 @@ inline bool u32regex_search(const std::wstring& s,
return re_detail::do_regex_search(s.begin(), s.end(), m, e, flags, s.begin(), static_cast<mpl::int_<sizeof(wchar_t)> const*>(0));
}
#endif
inline bool u32regex_search(const UnicodeString& s,
inline bool u32regex_search(const U_NAMESPACE_QUALIFIER UnicodeString& s,
match_results<const UChar*>& m,
const u32regex& e,
match_flag_type flags = match_default)
@ -744,7 +744,7 @@ inline bool u32regex_search(const std::wstring& s,
return re_detail::do_regex_search(s.begin(), s.end(), m, e, flags, s.begin(), static_cast<mpl::int_<sizeof(wchar_t)> const*>(0));
}
#endif
inline bool u32regex_search(const UnicodeString& s,
inline bool u32regex_search(const U_NAMESPACE_QUALIFIER UnicodeString& s,
const u32regex& e,
match_flag_type flags = match_default)
{
@ -921,7 +921,7 @@ inline OutputIterator u32regex_replace(OutputIterator out,
Iterator first,
Iterator last,
const u32regex& e,
const UnicodeString& fmt,
const U_NAMESPACE_QUALIFIER UnicodeString& fmt,
match_flag_type flags = match_default)
{
return re_detail::extract_output_base
@ -966,9 +966,9 @@ namespace re_detail{
class unicode_string_out_iterator
{
UnicodeString* out;
U_NAMESPACE_QUALIFIER UnicodeString* out;
public:
unicode_string_out_iterator(UnicodeString& s) : out(&s) {}
unicode_string_out_iterator(U_NAMESPACE_QUALIFIER UnicodeString& s) : out(&s) {}
unicode_string_out_iterator& operator++() { return *this; }
unicode_string_out_iterator& operator++(int) { return *this; }
unicode_string_out_iterator& operator*() { return *this; }
@ -986,23 +986,23 @@ public:
}
inline UnicodeString u32regex_replace(const UnicodeString& s,
inline U_NAMESPACE_QUALIFIER UnicodeString u32regex_replace(const U_NAMESPACE_QUALIFIER UnicodeString& s,
const u32regex& e,
const UChar* fmt,
match_flag_type flags = match_default)
{
UnicodeString result;
U_NAMESPACE_QUALIFIER UnicodeString result;
re_detail::unicode_string_out_iterator i(result);
u32regex_replace(i, s.getBuffer(), s.getBuffer()+s.length(), e, fmt, flags);
return result;
}
inline UnicodeString u32regex_replace(const UnicodeString& s,
inline U_NAMESPACE_QUALIFIER UnicodeString u32regex_replace(const U_NAMESPACE_QUALIFIER UnicodeString& s,
const u32regex& e,
const UnicodeString& fmt,
const U_NAMESPACE_QUALIFIER UnicodeString& fmt,
match_flag_type flags = match_default)
{
UnicodeString result;
U_NAMESPACE_QUALIFIER UnicodeString result;
re_detail::unicode_string_out_iterator i(result);
re_detail::do_regex_replace(
re_detail::make_utf32_out(i, static_cast<mpl::int_<2> const*>(0)),

View File

@ -73,7 +73,9 @@ boost::shared_ptr<Object const> object_cache<Key, Object>::get(const Key& k, siz
// for now just throw, but we should never really get here...
//
::boost::throw_exception(std::runtime_error("Error in thread safety code: could not acquire a lock"));
#ifdef BOOST_NO_UNREACHABLE_RETURN_DETECTION
return boost::shared_ptr<Object>();
#endif
#else
return do_get(k, max_cache_size);
#endif

View File

@ -787,7 +787,7 @@ void basic_regex_creator<charT, traits>::fixup_recursions(re_syntax_base* state)
//
if(0 == (this->flags() & regex_constants::no_except))
{
std::string message = this->m_pdata->m_ptraits->error_string(boost::regex_constants::error_bad_pattern);
std::string message = "Encountered a forward reference to a marked sub-expression that does not exist.";
boost::regex_error e(message, boost::regex_constants::error_bad_pattern, 0);
e.raise();
}
@ -828,7 +828,7 @@ void basic_regex_creator<charT, traits>::fixup_recursions(re_syntax_base* state)
//
if(0 == (this->flags() & regex_constants::no_except))
{
std::string message = this->m_pdata->m_ptraits->error_string(boost::regex_constants::error_bad_pattern);
std::string message = "Encountered a forward reference to a recursive sub-expression that does not exist.";
boost::regex_error e(message, boost::regex_constants::error_bad_pattern, 0);
e.raise();
}
@ -893,7 +893,7 @@ void basic_regex_creator<charT, traits>::create_startmaps(re_syntax_base* state)
//
if(0 == (this->flags() & regex_constants::no_except))
{
std::string message = this->m_pdata->m_ptraits->error_string(boost::regex_constants::error_bad_pattern);
std::string message = "Invalid lookbehind assertion encountered in the regular expression.";
boost::regex_error e(message, boost::regex_constants::error_bad_pattern, 0);
e.raise();
}

View File

@ -45,6 +45,11 @@ public:
basic_regex_parser(regex_data<charT, traits>* data);
void parse(const charT* p1, const charT* p2, unsigned flags);
void fail(regex_constants::error_type error_code, std::ptrdiff_t position);
void fail(regex_constants::error_type error_code, std::ptrdiff_t position, std::string message, std::ptrdiff_t start_pos);
void fail(regex_constants::error_type error_code, std::ptrdiff_t position, const std::string& message)
{
fail(error_code, position, message, position);
}
bool parse_all();
bool parse_basic();
@ -141,6 +146,11 @@ void basic_regex_parser<charT, traits>::parse(const charT* p1, const charT* p2,
case regbase::literal:
m_parser_proc = &basic_regex_parser<charT, traits>::parse_literal;
break;
default:
// Ooops, someone has managed to set more than one of the main option flags,
// so this must be an error:
fail(regex_constants::error_unknown, 0, "An invalid combination of regular expression syntax flags was used.");
return;
}
// parse all our characters:
@ -155,7 +165,7 @@ void basic_regex_parser<charT, traits>::parse(const charT* p1, const charT* p2,
// have had an unexpected ')' :
if(!result)
{
fail(regex_constants::error_paren, ::boost::re_detail::distance(m_base, m_position));
fail(regex_constants::error_paren, ::boost::re_detail::distance(m_base, m_position), "Found a closing ) with no corresponding openening parenthesis.");
return;
}
// if an error has been set then give up now:
@ -168,13 +178,40 @@ void basic_regex_parser<charT, traits>::parse(const charT* p1, const charT* p2,
template <class charT, class traits>
void basic_regex_parser<charT, traits>::fail(regex_constants::error_type error_code, std::ptrdiff_t position)
{
// get the error message:
std::string message = this->m_pdata->m_ptraits->error_string(error_code);
fail(error_code, position, message);
}
template <class charT, class traits>
void basic_regex_parser<charT, traits>::fail(regex_constants::error_type error_code, std::ptrdiff_t position, std::string message, std::ptrdiff_t start_pos)
{
if(0 == this->m_pdata->m_status) // update the error code if not already set
this->m_pdata->m_status = error_code;
m_position = m_end; // don't bother parsing anything else
// get the error message:
std::string message = this->m_pdata->m_ptraits->error_string(error_code);
// and raise the exception, this will do nothing if exceptions are disabled:
//
// Augment error message with the regular expression text:
//
if(start_pos == position)
start_pos = (std::max)(static_cast<std::ptrdiff_t>(0), position - 10);
std::ptrdiff_t end_pos = (std::min)(position + 10, m_end - m_base);
if(error_code != regex_constants::error_empty)
{
if((start_pos != 0) || (end_pos != (m_end - m_base)))
message += " The error occured while parsing the regular expression fragment: '";
else
message += " The error occured while parsing the regular expression: '";
if(start_pos != end_pos)
{
message += std::string(m_base + start_pos, m_base + position);
message += ">>>HERE>>>";
message += std::string(m_base + position, m_base + end_pos);
}
message += "'.";
}
#ifndef BOOST_NO_EXCEPTIONS
if(0 == (this->flags() & regex_constants::no_except))
{
@ -282,7 +319,7 @@ bool basic_regex_parser<charT, traits>::parse_extended()
case regex_constants::syntax_star:
if(m_position == this->m_base)
{
fail(regex_constants::error_badrepeat, 0);
fail(regex_constants::error_badrepeat, 0, "The repeat operator \"*\" cannot start a regular expression.");
return false;
}
++m_position;
@ -290,7 +327,7 @@ bool basic_regex_parser<charT, traits>::parse_extended()
case regex_constants::syntax_question:
if(m_position == this->m_base)
{
fail(regex_constants::error_badrepeat, 0);
fail(regex_constants::error_badrepeat, 0, "The repeat operator \"?\" cannot start a regular expression.");
return false;
}
++m_position;
@ -298,7 +335,7 @@ bool basic_regex_parser<charT, traits>::parse_extended()
case regex_constants::syntax_plus:
if(m_position == this->m_base)
{
fail(regex_constants::error_badrepeat, 0);
fail(regex_constants::error_badrepeat, 0, "The repeat operator \"+\" cannot start a regular expression.");
return false;
}
++m_position;
@ -307,7 +344,7 @@ bool basic_regex_parser<charT, traits>::parse_extended()
++m_position;
return parse_repeat_range(false);
case regex_constants::syntax_close_brace:
fail(regex_constants::error_brace, this->m_position - this->m_end);
fail(regex_constants::error_brace, this->m_position - this->m_base, "Found a closing repetition operator } with no corresponding {.");
return false;
case regex_constants::syntax_or:
return parse_alt();
@ -512,7 +549,7 @@ bool basic_regex_parser<charT, traits>::parse_basic_escape()
case regex_constants::syntax_close_brace:
if(this->flags() & regbase::no_intervals)
return parse_literal();
fail(regex_constants::error_brace, this->m_position - this->m_base);
fail(regex_constants::error_brace, this->m_position - this->m_base, "Found a closing repetition operator } with no corresponding {.");
return false;
case regex_constants::syntax_or:
if(this->flags() & regbase::bk_vbar)
@ -607,7 +644,7 @@ bool basic_regex_parser<charT, traits>::parse_basic_escape()
case 'c':
case 'C':
// not supported yet:
fail(regex_constants::error_escape, m_position - m_base);
fail(regex_constants::error_escape, m_position - m_base, "The \\c and \\C escape sequences are not supported by POSIX basic regular expressions: try the Perl syntax instead.");
return false;
default:
break;
@ -705,7 +742,7 @@ escape_type_class_jump:
char_class_type m;
if(m_position == m_end)
{
fail(regex_constants::error_escape, m_position - m_base);
fail(regex_constants::error_escape, m_position - m_base, "Incomplete property escape found.");
return false;
}
// maybe have \p{ddd}
@ -717,7 +754,7 @@ escape_type_class_jump:
++m_position;
if(m_position == m_end)
{
fail(regex_constants::error_escape, m_position - m_base);
fail(regex_constants::error_escape, m_position - m_base, "Closing } missing from property escape sequence.");
return false;
}
m = this->m_traits.lookup_classname(++base, m_position++);
@ -740,7 +777,7 @@ escape_type_class_jump:
}
return true;
}
fail(regex_constants::error_ctype, m_position - m_base);
fail(regex_constants::error_ctype, m_position - m_base, "Escape sequence was neither a valid property nor a valid character class name.");
return false;
}
case regex_constants::escape_type_reset_start_mark:
@ -776,9 +813,10 @@ escape_type_class_jump:
{
bool have_brace = false;
bool negative = false;
static const char* incomplete_message = "Incomplete \\g escape found.";
if(++m_position == m_end)
{
fail(regex_constants::error_escape, m_position - m_base);
fail(regex_constants::error_escape, m_position - m_base, incomplete_message);
return false;
}
// maybe have \g{ddd}
@ -786,7 +824,7 @@ escape_type_class_jump:
{
if(++m_position == m_end)
{
fail(regex_constants::error_escape, m_position - m_base);
fail(regex_constants::error_escape, m_position - m_base, incomplete_message);
return false;
}
have_brace = true;
@ -794,7 +832,7 @@ escape_type_class_jump:
negative = (*m_position == static_cast<charT>('-'));
if((negative) && (++m_position == m_end))
{
fail(regex_constants::error_escape, m_position - m_base);
fail(regex_constants::error_escape, m_position - m_base, incomplete_message);
return false;
}
const charT* pc = m_position;
@ -819,7 +857,7 @@ escape_type_class_jump:
}
else
{
fail(regex_constants::error_backref, m_position - m_end);
fail(regex_constants::error_backref, m_position - m_base);
return false;
}
m_position = pc;
@ -827,7 +865,7 @@ escape_type_class_jump:
{
if((m_position == m_end) || (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_brace))
{
fail(regex_constants::error_escape, m_position - m_base);
fail(regex_constants::error_escape, m_position - m_base, incomplete_message);
return false;
}
++m_position;
@ -894,7 +932,7 @@ bool basic_regex_parser<charT, traits>::parse_repeat(std::size_t low, std::size_
}
if(0 == this->m_last_state)
{
fail(regex_constants::error_badrepeat, ::boost::re_detail::distance(m_base, m_position));
fail(regex_constants::error_badrepeat, ::boost::re_detail::distance(m_base, m_position), "Nothing to repeat.");
return false;
}
if(this->m_last_state->type == syntax_element_endmark)
@ -968,7 +1006,7 @@ bool basic_regex_parser<charT, traits>::parse_repeat(std::size_t low, std::size_
re_brace* pb = static_cast<re_brace*>(this->insert_state(insert_point, syntax_element_startmark, sizeof(re_brace)));
pb->index = -3;
pb->icase = this->flags() & regbase::icase;
re_jump* jmp = static_cast<re_jump*>(this->insert_state(insert_point + sizeof(re_brace), syntax_element_jump, sizeof(re_jump)));
jmp = static_cast<re_jump*>(this->insert_state(insert_point + sizeof(re_brace), syntax_element_jump, sizeof(re_jump)));
this->m_pdata->m_data.align();
jmp->alt.i = this->m_pdata->m_data.size() - this->getoffset(jmp);
pb = static_cast<re_brace*>(this->append_state(syntax_element_endmark, sizeof(re_brace)));
@ -981,6 +1019,7 @@ bool basic_regex_parser<charT, traits>::parse_repeat(std::size_t low, std::size_
template <class charT, class traits>
bool basic_regex_parser<charT, traits>::parse_repeat_range(bool isbasic)
{
static const char* incomplete_message = "Missing } in quantified repetition.";
//
// parse a repeat-range:
//
@ -992,7 +1031,7 @@ bool basic_regex_parser<charT, traits>::parse_repeat_range(bool isbasic)
// fail if at end:
if(this->m_position == this->m_end)
{
fail(regex_constants::error_brace, this->m_position - this->m_base);
fail(regex_constants::error_brace, this->m_position - this->m_base, incomplete_message);
return false;
}
// get min:
@ -1007,7 +1046,7 @@ bool basic_regex_parser<charT, traits>::parse_repeat_range(bool isbasic)
}
else if(this->m_position == this->m_end)
{
fail(regex_constants::error_brace, this->m_position - this->m_base);
fail(regex_constants::error_brace, this->m_position - this->m_base, incomplete_message);
return false;
}
min = v;
@ -1021,7 +1060,7 @@ bool basic_regex_parser<charT, traits>::parse_repeat_range(bool isbasic)
++m_position;
if(this->m_position == this->m_end)
{
fail(regex_constants::error_brace, this->m_position - this->m_base);
fail(regex_constants::error_brace, this->m_position - this->m_base, incomplete_message);
return false;
}
// get the value if any:
@ -1039,7 +1078,7 @@ bool basic_regex_parser<charT, traits>::parse_repeat_range(bool isbasic)
// OK now check trailing }:
if(this->m_position == this->m_end)
{
fail(regex_constants::error_brace, this->m_position - this->m_base);
fail(regex_constants::error_brace, this->m_position - this->m_base, incomplete_message);
return false;
}
if(isbasic)
@ -1049,13 +1088,13 @@ bool basic_regex_parser<charT, traits>::parse_repeat_range(bool isbasic)
++m_position;
if(this->m_position == this->m_end)
{
fail(regex_constants::error_brace, this->m_position - this->m_base);
fail(regex_constants::error_brace, this->m_position - this->m_base, incomplete_message);
return false;
}
}
else
{
fail(regex_constants::error_badbrace, this->m_position - this->m_base);
fail(regex_constants::error_brace, this->m_position - this->m_base, incomplete_message);
return false;
}
}
@ -1063,7 +1102,7 @@ bool basic_regex_parser<charT, traits>::parse_repeat_range(bool isbasic)
++m_position;
else
{
fail(regex_constants::error_badbrace, this->m_position - this->m_base);
fail(regex_constants::error_brace, this->m_position - this->m_base, incomplete_message);
return false;
}
//
@ -1071,7 +1110,11 @@ bool basic_regex_parser<charT, traits>::parse_repeat_range(bool isbasic)
//
if(min > max)
{
fail(regex_constants::error_badbrace, this->m_position - this->m_base);
// Backtrack to error location:
m_position -= 2;
while(this->m_traits.isctype(*m_position, this->m_word_mask)) --m_position;
++m_position;
fail(regex_constants::error_badbrace, m_position - m_base);
return false;
}
return parse_repeat(min, max);
@ -1094,7 +1137,7 @@ bool basic_regex_parser<charT, traits>::parse_alt()
)
)
{
fail(regex_constants::error_empty, this->m_position - this->m_base);
fail(regex_constants::error_empty, this->m_position - this->m_base, "A regular expression can start with the alternation operator |.");
return false;
}
//
@ -1146,10 +1189,11 @@ bool basic_regex_parser<charT, traits>::parse_alt()
template <class charT, class traits>
bool basic_regex_parser<charT, traits>::parse_set()
{
static const char* incomplete_message = "Character set declaration starting with [ terminated prematurely - either no ] was found or the set had no content.";
++m_position;
if(m_position == m_end)
{
fail(regex_constants::error_brack, m_position - m_base);
fail(regex_constants::error_brack, m_position - m_base, incomplete_message);
return false;
}
basic_char_set<charT, traits> char_set;
@ -1182,7 +1226,7 @@ bool basic_regex_parser<charT, traits>::parse_set()
++m_position;
if(0 == this->append_set(char_set))
{
fail(regex_constants::error_range, m_position - m_base);
fail(regex_constants::error_ctype, m_position - m_base);
return false;
}
}
@ -1237,6 +1281,7 @@ bool basic_regex_parser<charT, traits>::parse_set()
template <class charT, class traits>
bool basic_regex_parser<charT, traits>::parse_inner_set(basic_char_set<charT, traits>& char_set)
{
static const char* incomplete_message = "Character class declaration starting with [ terminated prematurely - either no ] was found or the set had no content.";
//
// we have either a character class [:name:]
// a collating element [.name.]
@ -1244,7 +1289,7 @@ bool basic_regex_parser<charT, traits>::parse_inner_set(basic_char_set<charT, tr
//
if(m_end == ++m_position)
{
fail(regex_constants::error_brack, m_position - m_base);
fail(regex_constants::error_brack, m_position - m_base, incomplete_message);
return false;
}
switch(this->m_traits.syntax_type(*m_position))
@ -1269,14 +1314,14 @@ bool basic_regex_parser<charT, traits>::parse_inner_set(basic_char_set<charT, tr
// skip the ':'
if(m_end == ++m_position)
{
fail(regex_constants::error_brack, m_position - m_base);
fail(regex_constants::error_brack, m_position - m_base, incomplete_message);
return false;
}
const charT* name_first = m_position;
// skip at least one character, then find the matching ':]'
if(m_end == ++m_position)
{
fail(regex_constants::error_brack, m_position - m_base);
fail(regex_constants::error_brack, m_position - m_base, incomplete_message);
return false;
}
while((m_position != m_end)
@ -1285,13 +1330,13 @@ bool basic_regex_parser<charT, traits>::parse_inner_set(basic_char_set<charT, tr
const charT* name_last = m_position;
if(m_end == m_position)
{
fail(regex_constants::error_brack, m_position - m_base);
fail(regex_constants::error_brack, m_position - m_base, incomplete_message);
return false;
}
if((m_end == ++m_position)
|| (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_set))
{
fail(regex_constants::error_brack, m_position - m_base);
fail(regex_constants::error_brack, m_position - m_base, incomplete_message);
return false;
}
//
@ -1346,14 +1391,14 @@ bool basic_regex_parser<charT, traits>::parse_inner_set(basic_char_set<charT, tr
// skip the '='
if(m_end == ++m_position)
{
fail(regex_constants::error_brack, m_position - m_base);
fail(regex_constants::error_brack, m_position - m_base, incomplete_message);
return false;
}
const charT* name_first = m_position;
// skip at least one character, then find the matching '=]'
if(m_end == ++m_position)
{
fail(regex_constants::error_brack, m_position - m_base);
fail(regex_constants::error_brack, m_position - m_base, incomplete_message);
return false;
}
while((m_position != m_end)
@ -1362,13 +1407,13 @@ bool basic_regex_parser<charT, traits>::parse_inner_set(basic_char_set<charT, tr
const charT* name_last = m_position;
if(m_end == m_position)
{
fail(regex_constants::error_brack, m_position - m_base);
fail(regex_constants::error_brack, m_position - m_base, incomplete_message);
return false;
}
if((m_end == ++m_position)
|| (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_set))
{
fail(regex_constants::error_brack, m_position - m_base);
fail(regex_constants::error_brack, m_position - m_base, incomplete_message);
return false;
}
string_type m = this->m_traits.lookup_collatename(name_first, name_last);
@ -1558,7 +1603,7 @@ charT basic_regex_parser<charT, traits>::unescape_character()
charT result(0);
if(m_position == m_end)
{
fail(regex_constants::error_escape, m_position - m_base);
fail(regex_constants::error_escape, m_position - m_base, "Escape sequence terminated prematurely.");
return false;
}
switch(this->m_traits.escape_syntax_type(*m_position))
@ -1591,24 +1636,22 @@ charT basic_regex_parser<charT, traits>::unescape_character()
++m_position;
if(m_position == m_end)
{
fail(regex_constants::error_escape, m_position - m_base);
// Rewind to start of escape:
--m_position;
while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_escape) --m_position;
fail(regex_constants::error_escape, m_position - m_base, "ASCII escape sequence terminated prematurely.");
return result;
}
/*
if((*m_position < charT('@'))
|| (*m_position > charT(125)) )
{
fail(regex_constants::error_escape, m_position - m_base);
return result;
}
*/
result = static_cast<charT>(*m_position % 32);
break;
case regex_constants::escape_type_hex:
++m_position;
if(m_position == m_end)
{
fail(regex_constants::error_escape, m_position - m_base);
// Rewind to start of escape:
--m_position;
while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_escape) --m_position;
fail(regex_constants::error_escape, m_position - m_base, "Hexadecimal escape sequence terminated prematurely.");
return result;
}
// maybe have \x{ddd}
@ -1617,7 +1660,10 @@ charT basic_regex_parser<charT, traits>::unescape_character()
++m_position;
if(m_position == m_end)
{
fail(regex_constants::error_escape, m_position - m_base);
// Rewind to start of escape:
--m_position;
while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_escape) --m_position;
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);
@ -1626,7 +1672,10 @@ charT basic_regex_parser<charT, traits>::unescape_character()
|| ((std::numeric_limits<charT>::is_specialized) && (i > (int)(std::numeric_limits<charT>::max)()))
|| (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_brace))
{
fail(regex_constants::error_badbrace, m_position - m_base);
// Rewind to start of escape:
--m_position;
while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_escape) --m_position;
fail(regex_constants::error_badbrace, m_position - m_base, "Hexadecimal escape sequence was invalid.");
return result;
}
++m_position;
@ -1639,7 +1688,10 @@ charT basic_regex_parser<charT, traits>::unescape_character()
if((i < 0)
|| !valid_value(charT(0), i))
{
fail(regex_constants::error_escape, m_position - m_base);
// Rewind to start of escape:
--m_position;
while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_escape) --m_position;
fail(regex_constants::error_escape, m_position - m_base, "Escape sequence did not encode a valid character.");
return result;
}
result = charT(i);
@ -1654,14 +1706,20 @@ charT basic_regex_parser<charT, traits>::unescape_character()
int val = this->m_traits.toi(bp, bp + 1, 8);
if(val != 0)
{
// Rewind to start of escape:
--m_position;
while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_escape) --m_position;
// Oops not an octal escape after all:
fail(regex_constants::error_escape, m_position - m_base);
fail(regex_constants::error_escape, m_position - m_base, "Invalid octal escape sequence.");
return result;
}
val = this->m_traits.toi(m_position, m_position + len, 8);
if(val < 0)
{
fail(regex_constants::error_escape, m_position - m_base);
// Rewind to start of escape:
--m_position;
while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_escape) --m_position;
fail(regex_constants::error_escape, m_position - m_base, "Octal escape sequence is invalid.");
return result;
}
return static_cast<charT>(val);
@ -1671,6 +1729,9 @@ charT basic_regex_parser<charT, traits>::unescape_character()
++m_position;
if(m_position == m_end)
{
// Rewind to start of escape:
--m_position;
while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_escape) --m_position;
fail(regex_constants::error_escape, m_position - m_base);
return false;
}
@ -1683,12 +1744,18 @@ charT basic_regex_parser<charT, traits>::unescape_character()
++m_position;
if(m_position == m_end)
{
// Rewind to start of escape:
--m_position;
while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_escape) --m_position;
fail(regex_constants::error_escape, m_position - m_base);
return false;
}
string_type s = this->m_traits.lookup_collatename(++base, m_position++);
if(s.empty())
{
// Rewind to start of escape:
--m_position;
while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_escape) --m_position;
fail(regex_constants::error_collate, m_position - m_base);
return false;
}
@ -1698,6 +1765,9 @@ charT basic_regex_parser<charT, traits>::unescape_character()
}
}
// fall through is a failure:
// Rewind to start of escape:
--m_position;
while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_escape) --m_position;
fail(regex_constants::error_escape, m_position - m_base);
return false;
}
@ -1733,7 +1803,10 @@ bool basic_regex_parser<charT, traits>::parse_backref()
}
else
{
fail(regex_constants::error_backref, m_position - m_end);
// Rewind to start of escape:
--m_position;
while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_escape) --m_position;
fail(regex_constants::error_backref, m_position - m_base);
return false;
}
return true;
@ -1765,7 +1838,7 @@ bool basic_regex_parser<charT, traits>::parse_QE()
}
if(++m_position == m_end) // skip the escape
{
fail(regex_constants::error_escape, m_position - m_base);
fail(regex_constants::error_escape, m_position - m_base, "Unterminated \\Q...\\E sequence.");
return false;
}
// check to see if it's a \E:
@ -1796,7 +1869,10 @@ bool basic_regex_parser<charT, traits>::parse_perl_extension()
{
if(++m_position == m_end)
{
fail(regex_constants::error_badrepeat, m_position - m_base);
// Rewind to start of (? sequence:
--m_position;
while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
fail(regex_constants::error_perl_extension, m_position - m_base);
return false;
}
//
@ -1855,7 +1931,10 @@ bool basic_regex_parser<charT, traits>::parse_perl_extension()
v = this->m_traits.toi(m_position, m_end, 10);
if((v < 0) || (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark))
{
fail(regex_constants::error_backref, m_position - m_base);
// Rewind to start of (? sequence:
--m_position;
while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
fail(regex_constants::error_perl_extension, m_position - m_base, "The recursive sub-expression refers to an invalid marking group, or is unterminated.");
return false;
}
insert_recursion:
@ -1874,7 +1953,10 @@ insert_recursion:
v = this->m_traits.toi(m_position, m_end, 10);
if((v <= 0) || (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark))
{
fail(regex_constants::error_backref, m_position - m_base);
// Rewind to start of (? sequence:
--m_position;
while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
fail(regex_constants::error_perl_extension, m_position - m_base, "An invalid or unterminated recursive sub-expression.");
return false;
}
v += m_mark_count;
@ -1894,7 +1976,10 @@ insert_recursion:
v = m_mark_count + 1 - v;
if(v <= 0)
{
fail(regex_constants::error_backref, m_position - m_base);
// Rewind to start of (? sequence:
--m_position;
while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
fail(regex_constants::error_perl_extension, m_position - m_base, "An invalid or unterminated recursive sub-expression.");
return false;
}
goto insert_recursion;
@ -1917,7 +2002,10 @@ insert_recursion:
// a lookbehind assertion:
if(++m_position == m_end)
{
fail(regex_constants::error_badrepeat, m_position - m_base);
// Rewind to start of (? sequence:
--m_position;
while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
fail(regex_constants::error_perl_extension, m_position - m_base);
return false;
}
regex_constants::syntax_type t = this->m_traits.syntax_type(*m_position);
@ -1955,15 +2043,21 @@ insert_recursion:
pb->index = markid = -4;
if(++m_position == m_end)
{
fail(regex_constants::error_badrepeat, m_position - m_base);
// Rewind to start of (? sequence:
--m_position;
while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
fail(regex_constants::error_perl_extension, m_position - m_base);
return false;
}
int v = this->m_traits.toi(m_position, m_end, 10);
v = this->m_traits.toi(m_position, m_end, 10);
if(*m_position == charT('R'))
{
if(++m_position == m_end)
{
fail(regex_constants::error_badrepeat, m_position - m_base);
// Rewind to start of (? sequence:
--m_position;
while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
fail(regex_constants::error_perl_extension, m_position - m_base);
return false;
}
if(*m_position == charT('&'))
@ -1973,7 +2067,10 @@ insert_recursion:
++m_position;
if(m_position == m_end)
{
fail(regex_constants::error_badrepeat, m_position - m_base);
// Rewind to start of (? sequence:
--m_position;
while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
fail(regex_constants::error_perl_extension, m_position - m_base);
return false;
}
v = -static_cast<int>(hash_value_from_capture_name(base, m_position));
@ -1986,12 +2083,18 @@ insert_recursion:
br->index = v < 0 ? (v - 1) : 0;
if(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark)
{
fail(regex_constants::error_badrepeat, m_position - m_base);
// Rewind to start of (? sequence:
--m_position;
while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
fail(regex_constants::error_perl_extension, m_position - m_base);
return false;
}
if(++m_position == m_end)
{
fail(regex_constants::error_badrepeat, m_position - m_base);
// Rewind to start of (? sequence:
--m_position;
while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
fail(regex_constants::error_perl_extension, m_position - m_base);
return false;
}
}
@ -2002,7 +2105,10 @@ insert_recursion:
++m_position;
if(m_position == m_end)
{
fail(regex_constants::error_badrepeat, m_position - m_base);
// Rewind to start of (? sequence:
--m_position;
while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
fail(regex_constants::error_perl_extension, m_position - m_base);
return false;
}
v = static_cast<int>(hash_value_from_capture_name(base, m_position));
@ -2010,17 +2116,26 @@ insert_recursion:
br->index = v;
if(((*m_position != charT('>')) && (*m_position != charT('\''))) || (++m_position == m_end))
{
fail(regex_constants::error_badrepeat, m_position - m_base);
// Rewind to start of (? sequence:
--m_position;
while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
fail(regex_constants::error_perl_extension, m_position - m_base, "Unterminated named capture.");
return false;
}
if(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark)
{
fail(regex_constants::error_badrepeat, m_position - m_base);
// Rewind to start of (? sequence:
--m_position;
while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
fail(regex_constants::error_perl_extension, m_position - m_base);
return false;
}
if(++m_position == m_end)
{
fail(regex_constants::error_badrepeat, m_position - m_base);
// Rewind to start of (? sequence:
--m_position;
while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
fail(regex_constants::error_perl_extension, m_position - m_base);
return false;
}
}
@ -2031,19 +2146,28 @@ insert_recursion:
++m_position, ++def;
if((m_position == m_end) || *def)
{
fail(regex_constants::error_badrepeat, m_position - m_base);
// Rewind to start of (? sequence:
--m_position;
while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
fail(regex_constants::error_perl_extension, m_position - m_base);
return false;
}
re_brace* br = static_cast<re_brace*>(this->append_state(syntax_element_assert_backref, sizeof(re_brace)));
br->index = 9999; // special magic value!
if(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark)
{
fail(regex_constants::error_badrepeat, m_position - m_base);
// Rewind to start of (? sequence:
--m_position;
while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
fail(regex_constants::error_perl_extension, m_position - m_base);
return false;
}
if(++m_position == m_end)
{
fail(regex_constants::error_badrepeat, m_position - m_base);
// Rewind to start of (? sequence:
--m_position;
while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
fail(regex_constants::error_perl_extension, m_position - m_base);
return false;
}
}
@ -2053,12 +2177,18 @@ insert_recursion:
br->index = v;
if(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark)
{
fail(regex_constants::error_badrepeat, m_position - m_base);
// Rewind to start of (? sequence:
--m_position;
while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
fail(regex_constants::error_perl_extension, m_position - m_base);
return false;
}
if(++m_position == m_end)
{
fail(regex_constants::error_badrepeat, m_position - m_base);
// Rewind to start of (? sequence:
--m_position;
while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
fail(regex_constants::error_perl_extension, m_position - m_base);
return false;
}
}
@ -2067,25 +2197,37 @@ insert_recursion:
// verify that we have a lookahead or lookbehind assert:
if(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_question)
{
fail(regex_constants::error_badrepeat, m_position - m_base);
// Rewind to start of (? sequence:
--m_position;
while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
fail(regex_constants::error_perl_extension, m_position - m_base);
return false;
}
if(++m_position == m_end)
{
fail(regex_constants::error_badrepeat, m_position - m_base);
// Rewind to start of (? sequence:
--m_position;
while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
fail(regex_constants::error_perl_extension, m_position - m_base);
return false;
}
if(this->m_traits.syntax_type(*m_position) == regex_constants::escape_type_left_word)
{
if(++m_position == m_end)
{
fail(regex_constants::error_badrepeat, m_position - m_base);
// Rewind to start of (? sequence:
--m_position;
while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
fail(regex_constants::error_perl_extension, m_position - m_base);
return false;
}
if((this->m_traits.syntax_type(*m_position) != regex_constants::syntax_equal)
&& (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_not))
{
fail(regex_constants::error_badrepeat, m_position - m_base);
// Rewind to start of (? sequence:
--m_position;
while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
fail(regex_constants::error_perl_extension, m_position - m_base);
return false;
}
m_position -= 3;
@ -2095,7 +2237,10 @@ insert_recursion:
if((this->m_traits.syntax_type(*m_position) != regex_constants::syntax_equal)
&& (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_not))
{
fail(regex_constants::error_paren, m_position - m_base);
// Rewind to start of (? sequence:
--m_position;
while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
fail(regex_constants::error_perl_extension, m_position - m_base);
return false;
}
m_position -= 2;
@ -2104,7 +2249,10 @@ insert_recursion:
break;
}
case regex_constants::syntax_close_mark:
fail(regex_constants::error_badrepeat, m_position - m_base);
// Rewind to start of (? sequence:
--m_position;
while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
fail(regex_constants::error_perl_extension, m_position - m_base);
return false;
case regex_constants::escape_type_end_buffer:
{
@ -2126,14 +2274,20 @@ named_capture_jump:
const charT* base = ++m_position;
if(m_position == m_end)
{
fail(regex_constants::error_paren, m_position - m_base);
// Rewind to start of (? sequence:
--m_position;
while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
fail(regex_constants::error_perl_extension, m_position - m_base);
return false;
}
while((m_position != m_end) && (*m_position != name_delim))
++m_position;
if(m_position == m_end)
{
fail(regex_constants::error_paren, m_position - m_base);
// Rewind to start of (? sequence:
--m_position;
while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
fail(regex_constants::error_perl_extension, m_position - m_base);
return false;
}
this->m_pdata->set_name(base, m_position, markid);
@ -2147,7 +2301,10 @@ named_capture_jump:
v = 0;
if(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark)
{
fail(regex_constants::error_backref, m_position - m_base);
// Rewind to start of (? sequence:
--m_position;
while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
fail(regex_constants::error_perl_extension, m_position - m_base);
return false;
}
goto insert_recursion;
@ -2160,7 +2317,10 @@ named_capture_jump:
++m_position;
if(m_position == m_end)
{
fail(regex_constants::error_backref, m_position - m_base);
// Rewind to start of (? sequence:
--m_position;
while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
fail(regex_constants::error_perl_extension, m_position - m_base);
return false;
}
v = static_cast<int>(hash_value_from_capture_name(base, m_position));
@ -2171,7 +2331,10 @@ named_capture_jump:
++m_position;
if(m_position == m_end)
{
fail(regex_constants::error_backref, m_position - m_base);
// Rewind to start of (? sequence:
--m_position;
while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
fail(regex_constants::error_perl_extension, m_position - m_base);
return false;
}
if(*m_position == charT('>'))
@ -2182,7 +2345,10 @@ named_capture_jump:
++m_position;
if(m_position == m_end)
{
fail(regex_constants::error_backref, m_position - m_base);
// Rewind to start of (? sequence:
--m_position;
while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
fail(regex_constants::error_perl_extension, m_position - m_base);
return false;
}
v = static_cast<int>(hash_value_from_capture_name(base, m_position));
@ -2195,7 +2361,13 @@ named_capture_jump:
option_group_jump:
regex_constants::syntax_option_type opts = parse_options();
if(m_position == m_end)
{
// Rewind to start of (? sequence:
--m_position;
while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
fail(regex_constants::error_perl_extension, m_position - m_base);
return false;
}
// make a note of whether we have a case change:
m_has_case_change = ((opts & regbase::icase) != (this->flags() & regbase::icase));
pb->index = markid = 0;
@ -2214,7 +2386,10 @@ option_group_jump:
}
else
{
fail(regex_constants::error_badrepeat, m_position - m_base);
// Rewind to start of (? sequence:
--m_position;
while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
fail(regex_constants::error_perl_extension, m_position - m_base);
return false;
}
@ -2236,12 +2411,21 @@ option_group_jump:
// Unwind alternatives:
//
if(0 == unwind_alts(last_paren_start))
{
// Rewind to start of (? sequence:
--m_position;
while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
fail(regex_constants::error_perl_extension, m_position - m_base, "Invalid alternation operators within (?...) block.");
return false;
}
//
// we either have a ')' or we have run out of characters prematurely:
//
if(m_position == m_end)
{
// Rewind to start of (? sequence:
--m_position;
while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
this->fail(regex_constants::error_paren, ::boost::re_detail::distance(m_base, m_end));
return false;
}
@ -2272,7 +2456,10 @@ option_group_jump:
if(this->m_last_state == jmp)
{
// Oops... we didn't have anything inside the assertion:
fail(regex_constants::error_empty, m_position - m_base);
// Rewind to start of (? sequence:
--m_position;
while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
fail(regex_constants::error_perl_extension, m_position - m_base, "Invalid or empty zero width assertion.");
return false;
}
}
@ -2292,7 +2479,10 @@ option_group_jump:
else if(this->getaddress(static_cast<re_alt*>(b)->alt.i, b)->type == syntax_element_alt)
{
// Can't have seen more than one alternative:
fail(regex_constants::error_bad_pattern, m_position - m_base);
// Rewind to start of (? sequence:
--m_position;
while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
fail(regex_constants::error_bad_pattern, m_position - m_base, "More than one alternation operator | was encountered inside a conditional expression.");
return false;
}
else
@ -2301,7 +2491,10 @@ option_group_jump:
b = this->getaddress(b->next.i, b);
if((b->type == syntax_element_assert_backref) && (static_cast<re_brace*>(b)->index == 9999))
{
fail(regex_constants::error_bad_pattern, m_position - m_base);
// Rewind to start of (? sequence:
--m_position;
while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
fail(regex_constants::error_bad_pattern, m_position - m_base, "Alternation operators are not allowed inside a DEFINE block.");
return false;
}
}
@ -2311,7 +2504,10 @@ option_group_jump:
if((b->type != syntax_element_assert_backref)
&& (b->type != syntax_element_startmark))
{
fail(regex_constants::error_badrepeat, m_position - m_base);
// Rewind to start of (? sequence:
--m_position;
while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
fail(regex_constants::error_badrepeat, m_position - m_base, "A repetition operator cannot be applied to a zero-width assertion.");
return false;
}
}
@ -2366,6 +2562,9 @@ bool basic_regex_parser<charT, traits>::add_emacs_code(bool negate)
//
if(++m_position == m_end)
{
// Rewind to start of sequence:
--m_position;
while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_escape) --m_position;
fail(regex_constants::error_escape, m_position - m_base);
return false;
}
@ -2466,6 +2665,9 @@ regex_constants::syntax_option_type basic_regex_parser<charT, traits>::parse_opt
}
if(++m_position == m_end)
{
// Rewind to start of (? sequence:
--m_position;
while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
fail(regex_constants::error_paren, m_position - m_base);
return false;
}
@ -2476,6 +2678,9 @@ regex_constants::syntax_option_type basic_regex_parser<charT, traits>::parse_opt
{
if(++m_position == m_end)
{
// Rewind to start of (? sequence:
--m_position;
while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
fail(regex_constants::error_paren, m_position - m_base);
return false;
}
@ -2502,6 +2707,9 @@ regex_constants::syntax_option_type basic_regex_parser<charT, traits>::parse_opt
}
if(++m_position == m_end)
{
// Rewind to start of (? sequence:
--m_position;
while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
fail(regex_constants::error_paren, m_position - m_base);
return false;
}
@ -2528,7 +2736,7 @@ bool basic_regex_parser<charT, traits>::unwind_alts(std::ptrdiff_t last_paren_st
)
)
{
fail(regex_constants::error_empty, this->m_position - this->m_base);
fail(regex_constants::error_empty, this->m_position - this->m_base, "Can't terminate a sub-expression with an alternation operator |.");
return false;
}
//

View File

@ -187,6 +187,7 @@ struct cpp_regex_traits_base
#ifndef BOOST_NO_STD_MESSAGES
if(m_pmessages == b.m_pmessages)
{
return m_pcollate < b.m_pcollate;
}
return m_pmessages < b.m_pmessages;
#else
@ -212,7 +213,7 @@ std::locale cpp_regex_traits_base<charT>::imbue(const std::locale& l)
m_locale = l;
m_pctype = &BOOST_USE_FACET(std::ctype<charT>, l);
#ifndef BOOST_NO_STD_MESSAGES
m_pmessages = &BOOST_USE_FACET(std::messages<charT>, l);
m_pmessages = BOOST_HAS_FACET(std::messages<charT>, l) ? &BOOST_USE_FACET(std::messages<charT>, l) : 0;
#endif
m_pcollate = &BOOST_USE_FACET(std::collate<charT>, l);
return result;
@ -276,7 +277,7 @@ void cpp_regex_traits_char_layer<charT>::init()
typename std::messages<charT>::catalog cat = reinterpret_cast<std::messages<char>::catalog>(-1);
#endif
std::string cat_name(cpp_regex_traits<charT>::get_catalog_name());
if(cat_name.size())
if(cat_name.size() && (this->m_pmessages != 0))
{
cat = this->m_pmessages->open(
cat_name,
@ -309,7 +310,8 @@ void cpp_regex_traits_char_layer<charT>::init()
}
catch(...)
{
this->m_pmessages->close(cat);
if(this->m_pmessages)
this->m_pmessages->close(cat);
throw;
}
#endif
@ -653,7 +655,7 @@ void cpp_regex_traits_implementation<charT>::init()
typename std::messages<charT>::catalog cat = reinterpret_cast<std::messages<char>::catalog>(-1);
#endif
std::string cat_name(cpp_regex_traits<charT>::get_catalog_name());
if(cat_name.size())
if(cat_name.size() && (this->m_pmessages != 0))
{
cat = this->m_pmessages->open(
cat_name,
@ -716,7 +718,7 @@ void cpp_regex_traits_implementation<charT>::init()
cpp_regex_traits_implementation<charT>::mask_unicode,
};
#else
static const char_class_type masks[14] =
static const char_class_type masks[16] =
{
::boost::re_detail::char_class_alnum,
::boost::re_detail::char_class_alpha,
@ -837,8 +839,8 @@ bool cpp_regex_traits_implementation<charT>::isctype(const charT c, char_class_t
|| ((mask & ::boost::re_detail::char_class_blank) && (m_pctype->is(std::ctype<charT>::space, c)) && !::boost::re_detail::is_separator(c))
|| ((mask & ::boost::re_detail::char_class_word) && (c == '_'))
|| ((mask & ::boost::re_detail::char_class_unicode) && ::boost::re_detail::is_extended(c))
|| ((mask & ::boost::re_detail::char_class_vertical) && (is_separator(c) || (c == '\v')))
|| ((mask & ::boost::re_detail::char_class_horizontal) && m_pctype->is(std::ctype<charT>::space, c) && !(is_separator(c) || (c == '\v')));
|| ((mask & ::boost::re_detail::char_class_vertical_space) && (is_separator(c) || (c == '\v')))
|| ((mask & ::boost::re_detail::char_class_horizontal_space) && m_pctype->is(std::ctype<charT>::space, c) && !(is_separator(c) || (c == '\v')));
}
#endif

View File

@ -124,11 +124,11 @@ typedef enum{
REG_STARTEND = 00004
} reg_exec_flags;
//
// POSIX error codes:
//
/*
* POSIX error codes:
*/
typedef unsigned reg_error_t;
typedef reg_error_t reg_errcode_t; // backwards compatibility
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). */
@ -154,8 +154,9 @@ static const reg_error_t REG_EMPTY = 17; /* empty expression */
static const reg_error_t REG_E_MEMORY = 15; /* = REG_ESIZE : out of memory */
static const reg_error_t REG_ECOMPLEXITY = 18; /* complexity too high */
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 = 20; /* = REG_E_UNKNOWN : Reserved. */
static const reg_error_t REG_E_PERL = 20; /* Perl (?...) error */
static const reg_error_t REG_E_UNKNOWN = 21; /* unknown error */
static const reg_error_t REG_ENOSYS = 21; /* = REG_E_UNKNOWN : Reserved. */
BOOST_REGEX_DECL int BOOST_REGEX_CCALL regcompA(regex_tA*, const char*, int);
BOOST_REGEX_DECL regsize_t BOOST_REGEX_CCALL regerrorA(int, const regex_tA*, char*, regsize_t);
@ -195,14 +196,14 @@ BOOST_REGEX_DECL void BOOST_REGEX_CCALL regfreeW(regex_tW*);
#endif
#ifdef __cplusplus
} // extern "C"
} // namespace
} /* extern "C" */
} /* namespace */
#endif
//
// C++ high level wrapper goes here:
//
#if defined(__cplusplus)
/*
* C++ high level wrapper goes here:
*/
#include <string>
#include <vector>
namespace boost{
@ -228,7 +229,7 @@ struct pred2;
struct pred3;
struct pred4;
} // namespace re_detail
} /* namespace re_detail */
#if (defined(BOOST_MSVC) || defined(__BORLANDC__)) && !defined(BOOST_DISABLE_WIN32)
typedef bool (__cdecl *GrepCallback)(const RegEx& expression);
@ -257,9 +258,9 @@ public:
unsigned int SetExpression(const std::string& s, bool icase = false){ return SetExpression(s.c_str(), icase); }
std::string Expression()const;
unsigned int error_code()const;
//
// now matching operators:
//
/*
* now matching operators:
*/
bool Match(const char* p, match_flag_type flags = match_default);
bool Match(const std::string& s, match_flag_type flags = match_default) { return Match(s.c_str(), flags); }
bool Search(const char* p, match_flag_type flags = match_default);
@ -283,9 +284,9 @@ public:
bool copy = true, match_flag_type flags = match_default);
std::size_t Split(std::vector<std::string>& v, std::string& s, match_flag_type flags = match_default, unsigned max_count = ~0);
//
// now operators for returning what matched in more detail:
//
/*
* now operators for returning what matched in more detail:
*/
std::size_t Position(int i = 0)const;
std::size_t Length(int i = 0)const;
bool Matched(int i = 0)const;
@ -312,11 +313,11 @@ public:
#pragma warning(pop)
#endif
} // namespace boost
} /* namespace boost */
#endif
#endif /* __cplusplus */
#endif // include guard
#endif /* include guard */

View File

@ -28,8 +28,8 @@ namespace regex_constants{
enum error_type{
error_ok = 0, // not used
error_no_match = 1, // not used
error_ok = 0, /* not used */
error_no_match = 1, /* not used */
error_bad_pattern = 2,
error_collate = 3,
error_ctype = 4,
@ -42,17 +42,18 @@ enum error_type{
error_range = 11,
error_space = 12,
error_badrepeat = 13,
error_end = 14, // not used
error_end = 14, /* not used */
error_size = 15,
error_right_paren = 16, // not used
error_right_paren = 16, /* not used */
error_empty = 17,
error_complexity = 18,
error_stack = 19,
error_unknown = 20
error_perl_extension = 20,
error_unknown = 21
};
}
}
#endif // __cplusplus
#endif /* __cplusplus */
#endif

View File

@ -31,43 +31,43 @@ namespace boost{
typedef enum _match_flags
{
match_default = 0,
match_not_bol = 1, // first is not start of line
match_not_eol = match_not_bol << 1, // last is not end of line
match_not_bob = match_not_eol << 1, // first is not start of buffer
match_not_eob = match_not_bob << 1, // last is not end of buffer
match_not_bow = match_not_eob << 1, // first is not start of word
match_not_eow = match_not_bow << 1, // last is not end of word
match_not_dot_newline = match_not_eow << 1, // \n is not matched by '.'
match_not_dot_null = match_not_dot_newline << 1, // '\0' is not matched by '.'
match_prev_avail = match_not_dot_null << 1, // *--first is a valid expression
match_init = match_prev_avail << 1, // internal use
match_any = match_init << 1, // don't care what we match
match_not_null = match_any << 1, // string can't be null
match_continuous = match_not_null << 1, // each grep match must continue from
// uninterupted from the previous one
match_partial = match_continuous << 1, // find partial matches
match_not_bol = 1, /* first is not start of line */
match_not_eol = match_not_bol << 1, /* last is not end of line */
match_not_bob = match_not_eol << 1, /* first is not start of buffer */
match_not_eob = match_not_bob << 1, /* last is not end of buffer */
match_not_bow = match_not_eob << 1, /* first is not start of word */
match_not_eow = match_not_bow << 1, /* last is not end of word */
match_not_dot_newline = match_not_eow << 1, /* \n is not matched by '.' */
match_not_dot_null = match_not_dot_newline << 1, /* '\0' is not matched by '.' */
match_prev_avail = match_not_dot_null << 1, /* *--first is a valid expression */
match_init = match_prev_avail << 1, /* internal use */
match_any = match_init << 1, /* don't care what we match */
match_not_null = match_any << 1, /* string can't be null */
match_continuous = match_not_null << 1, /* each grep match must continue from */
/* uninterupted from the previous one */
match_partial = match_continuous << 1, /* find partial matches */
match_stop = match_partial << 1, // stop after first match (grep) V3 only
match_not_initial_null = match_stop, // don't match initial null, V4 only
match_all = match_stop << 1, // must find the whole of input even if match_any is set
match_perl = match_all << 1, // Use perl matching rules
match_posix = match_perl << 1, // Use POSIX matching rules
match_nosubs = match_posix << 1, // don't trap marked subs
match_extra = match_nosubs << 1, // include full capture information for repeated captures
match_single_line = match_extra << 1, // treat text as single line and ignor any \n's when matching ^ and $.
match_unused1 = match_single_line << 1, // unused
match_unused2 = match_unused1 << 1, // unused
match_unused3 = match_unused2 << 1, // unused
match_stop = match_partial << 1, /* stop after first match (grep) V3 only */
match_not_initial_null = match_stop, /* don't match initial null, V4 only */
match_all = match_stop << 1, /* must find the whole of input even if match_any is set */
match_perl = match_all << 1, /* Use perl matching rules */
match_posix = match_perl << 1, /* Use POSIX matching rules */
match_nosubs = match_posix << 1, /* don't trap marked subs */
match_extra = match_nosubs << 1, /* include full capture information for repeated captures */
match_single_line = match_extra << 1, /* treat text as single line and ignor any \n's when matching ^ and $. */
match_unused1 = match_single_line << 1, /* unused */
match_unused2 = match_unused1 << 1, /* unused */
match_unused3 = match_unused2 << 1, /* unused */
match_max = match_unused3,
format_perl = 0, // perl style replacement
format_default = 0, // ditto.
format_sed = match_max << 1, // sed style replacement.
format_all = format_sed << 1, // enable all extentions to sytax.
format_no_copy = format_all << 1, // don't copy non-matching segments.
format_first_only = format_no_copy << 1, // Only replace first occurance.
format_is_if = format_first_only << 1, // internal use only.
format_literal = format_is_if << 1 // treat string as a literal
format_perl = 0, /* perl style replacement */
format_default = 0, /* ditto. */
format_sed = match_max << 1, /* sed style replacement. */
format_all = format_sed << 1, /* enable all extentions to sytax. */
format_no_copy = format_all << 1, /* don't copy non-matching segments. */
format_first_only = format_no_copy << 1, /* Only replace first occurance. */
format_is_if = format_first_only << 1, /* internal use only. */
format_literal = format_is_if << 1 /* treat string as a literal */
} match_flags;
@ -96,10 +96,10 @@ inline match_flags& operator^=(match_flags& m1, match_flags m2)
#endif
#ifdef __cplusplus
} // namespace regex_constants
//
// import names into boost for backwards compatiblity:
//
} /* namespace regex_constants */
/*
* import names into boost for backwards compatiblity:
*/
using regex_constants::match_flag_type;
using regex_constants::match_default;
using regex_constants::match_not_bol;
@ -111,28 +111,28 @@ using regex_constants::match_not_eow;
using regex_constants::match_not_dot_newline;
using regex_constants::match_not_dot_null;
using regex_constants::match_prev_avail;
//using regex_constants::match_init;
/* using regex_constants::match_init; */
using regex_constants::match_any;
using regex_constants::match_not_null;
using regex_constants::match_continuous;
using regex_constants::match_partial;
//using regex_constants::match_stop;
/*using regex_constants::match_stop; */
using regex_constants::match_all;
using regex_constants::match_perl;
using regex_constants::match_posix;
using regex_constants::match_nosubs;
using regex_constants::match_extra;
using regex_constants::match_single_line;
//using regex_constants::match_max;
/*using regex_constants::match_max; */
using regex_constants::format_all;
using regex_constants::format_sed;
using regex_constants::format_perl;
using regex_constants::format_default;
using regex_constants::format_no_copy;
using regex_constants::format_first_only;
//using regex_constants::format_is_if;
/*using regex_constants::format_is_if;*/
} // namespace boost
#endif // __cplusplus
#endif // include guard
} /* namespace boost */
#endif /* __cplusplus */
#endif /* include guard */

View File

@ -1,6 +1,6 @@
/*
*
* Copyright (c) 1998-2002
* Copyright (c) 1998-2009
* John Maddock
*
* Use, modification and distribution are subject to the
@ -74,16 +74,30 @@ public:
// construct/copy/destroy:
explicit match_results(const Allocator& a = Allocator())
#ifndef BOOST_NO_STD_ALLOCATOR
: m_subs(a), m_base(), m_last_closed_paren(0) {}
: m_subs(a), m_base(), m_last_closed_paren(0), m_is_singular(true) {}
#else
: m_subs(), m_base(), m_last_closed_paren(0) { (void)a; }
: m_subs(), m_base(), m_last_closed_paren(0), m_is_singular(true) { (void)a; }
#endif
match_results(const match_results& m)
: m_subs(m.m_subs), m_base(m.m_base) {}
: m_subs(m.m_subs), m_named_subs(m.m_named_subs), m_last_closed_paren(m.m_last_closed_paren), m_is_singular(m.m_is_singular)
{
if(!m_is_singular)
{
m_base = m.m_base;
m_null = m.m_null;
}
}
match_results& operator=(const match_results& m)
{
m_subs = m.m_subs;
m_base = m.m_base;
m_named_subs = m.m_named_subs;
m_last_closed_paren = m.m_last_closed_paren;
m_is_singular = m.m_is_singular;
if(!m_is_singular)
{
m_base = m.m_base;
m_null = m.m_null;
}
return *this;
}
~match_results(){}
@ -98,6 +112,8 @@ public:
// element access:
difference_type length(int sub = 0) const
{
if(m_is_singular)
raise_logic_error();
sub += 2;
if((sub < (int)m_subs.size()) && (sub > 0))
return m_subs[sub].length();
@ -105,16 +121,20 @@ public:
}
difference_type length(const char_type* sub) const
{
const char_type* end = sub;
while(*end) ++end;
return length(named_subexpression_index(sub, end));
if(m_is_singular)
raise_logic_error();
const char_type* sub_end = sub;
while(*sub_end) ++sub_end;
return length(named_subexpression_index(sub, sub_end));
}
template <class charT>
difference_type length(const charT* sub) const
{
const charT* end = sub;
while(*end) ++end;
return length(named_subexpression_index(sub, end));
if(m_is_singular)
raise_logic_error();
const charT* sub_end = sub;
while(*sub_end) ++sub_end;
return length(named_subexpression_index(sub, sub_end));
}
template <class charT, class Traits, class A>
difference_type length(const std::basic_string<charT, Traits, A>& sub) const
@ -123,6 +143,8 @@ public:
}
difference_type position(size_type sub = 0) const
{
if(m_is_singular)
raise_logic_error();
sub += 2;
if(sub < m_subs.size())
{
@ -136,16 +158,16 @@ public:
}
difference_type position(const char_type* sub) const
{
const char_type* end = sub;
while(*end) ++end;
return position(named_subexpression_index(sub, end));
const char_type* sub_end = sub;
while(*sub_end) ++sub_end;
return position(named_subexpression_index(sub, sub_end));
}
template <class charT>
difference_type position(const charT* sub) const
{
const charT* end = sub;
while(*end) ++end;
return position(named_subexpression_index(sub, end));
const charT* sub_end = sub;
while(*sub_end) ++sub_end;
return position(named_subexpression_index(sub, sub_end));
}
template <class charT, class Traits, class A>
difference_type position(const std::basic_string<charT, Traits, A>& sub) const
@ -154,6 +176,8 @@ public:
}
string_type str(int sub = 0) const
{
if(m_is_singular)
raise_logic_error();
sub += 2;
string_type result;
if(sub < (int)m_subs.size() && (sub > 0))
@ -187,6 +211,8 @@ public:
}
const_reference operator[](int sub) const
{
if(m_is_singular && m_subs.empty())
raise_logic_error();
sub += 2;
if(sub < (int)m_subs.size() && (sub >= 0))
{
@ -199,6 +225,8 @@ public:
//
const_reference named_subexpression(const char_type* i, const char_type* j) const
{
if(m_is_singular)
raise_logic_error();
int index = m_named_subs->get_id(i, j);
return index > 0 ? (*this)[index] : m_null;
}
@ -215,6 +243,8 @@ public:
}
int named_subexpression_index(const char_type* i, const char_type* j) const
{
if(m_is_singular)
raise_logic_error();
int index = m_named_subs->get_id(i, j);
return index > 0 ? index : -20;
}
@ -266,11 +296,15 @@ public:
const_reference prefix() const
{
if(m_is_singular)
raise_logic_error();
return (*this)[-1];
}
const_reference suffix() const
{
if(m_is_singular)
raise_logic_error();
return (*this)[-2];
}
const_iterator begin() const
@ -282,44 +316,67 @@ public:
return m_subs.end();
}
// format:
template <class OutputIterator>
template <class OutputIterator, class Functor>
OutputIterator format(OutputIterator out,
const string_type& fmt,
Functor fmt,
match_flag_type flags = format_default) const
{
re_detail::trivial_format_traits<char_type> traits;
return re_detail::regex_format_imp(out, *this, fmt.data(), fmt.data() + fmt.size(), flags, traits);
if(m_is_singular)
raise_logic_error();
typedef typename re_detail::compute_functor_type<Functor, match_results<BidiIterator, Allocator>, OutputIterator>::type F;
F func(fmt);
return func(*this, out, flags);
}
string_type format(const string_type& fmt,
match_flag_type flags = format_default) const
template <class Functor>
string_type format(Functor fmt, match_flag_type flags = format_default) const
{
string_type result;
re_detail::string_out_iterator<string_type> i(result);
re_detail::trivial_format_traits<char_type> traits;
re_detail::regex_format_imp(i, *this, fmt.data(), fmt.data() + fmt.size(), flags, traits);
if(m_is_singular)
raise_logic_error();
std::basic_string<char_type> result;
re_detail::string_out_iterator<std::basic_string<char_type> > i(result);
typedef typename re_detail::compute_functor_type<Functor, match_results<BidiIterator, Allocator>, re_detail::string_out_iterator<std::basic_string<char_type> > >::type F;
F func(fmt);
func(*this, i, flags);
return result;
}
// format with locale:
template <class OutputIterator, class RegexT>
template <class OutputIterator, class Functor, class RegexT>
OutputIterator format(OutputIterator out,
const string_type& fmt,
Functor fmt,
match_flag_type flags,
const RegexT& re) const
{
return ::boost::re_detail::regex_format_imp(out, *this, fmt.data(), fmt.data() + fmt.size(), flags, re.get_traits());
if(m_is_singular)
raise_logic_error();
typedef ::boost::regex_traits_wrapper<typename RegexT::traits_type> traits_type;
typedef typename re_detail::compute_functor_type<Functor, match_results<BidiIterator, Allocator>, OutputIterator, traits_type>::type F;
F func(fmt);
return func(*this, out, flags, re.get_traits());
}
template <class RegexT>
string_type format(const string_type& fmt,
template <class RegexT, class Functor>
string_type format(Functor fmt,
match_flag_type flags,
const RegexT& re) const
{
string_type result;
re_detail::string_out_iterator<string_type> i(result);
::boost::re_detail::regex_format_imp(i, *this, fmt.data(), fmt.data() + fmt.size(), flags, re.get_traits());
if(m_is_singular)
raise_logic_error();
typedef ::boost::regex_traits_wrapper<typename RegexT::traits_type> traits_type;
std::basic_string<char_type> result;
re_detail::string_out_iterator<std::basic_string<char_type> > i(result);
typedef typename re_detail::compute_functor_type<Functor, match_results<BidiIterator, Allocator>, re_detail::string_out_iterator<std::basic_string<char_type> >, traits_type >::type F;
F func(fmt);
func(*this, i, flags, re.get_traits());
return result;
}
const_reference get_last_closed_paren()const
{
if(m_is_singular)
raise_logic_error();
return m_last_closed_paren == 0 ? m_null : (*this)[m_last_closed_paren];
}
@ -334,11 +391,39 @@ public:
void swap(match_results& that)
{
std::swap(m_subs, that.m_subs);
std::swap(m_base, that.m_base);
std::swap(m_named_subs, that.m_named_subs);
std::swap(m_last_closed_paren, that.m_last_closed_paren);
std::swap(m_is_singular, that.m_is_singular);
if(m_is_singular)
{
if(!that.m_is_singular)
{
m_base = that.m_base;
m_null = that.m_null;
}
}
else if(that.m_is_singular)
{
that.m_base = m_base;
that.m_null = m_null;
}
else
{
std::swap(m_base, that.m_base);
std::swap(m_null, that.m_null);
}
}
bool operator==(const match_results& that)const
{
return (m_subs == that.m_subs) && (m_base == that.m_base);
if(m_is_singular)
{
return that.m_is_singular;
}
else if(that.m_is_singular)
{
return false;
}
return (m_subs == that.m_subs) && (m_base == that.m_base) && (m_last_closed_paren == that.m_last_closed_paren);
}
bool operator!=(const match_results& that)const
{ return !(*this == that); }
@ -348,6 +433,8 @@ public:
const capture_sequence_type& captures(int i)const
{
if(m_is_singular)
raise_logic_error();
return (*this)[i].captures();
}
#endif
@ -364,6 +451,7 @@ public:
m_null.first = i;
m_null.second = i;
m_null.matched = false;
m_is_singular = false;
}
void BOOST_REGEX_CALL set_second(BidiIterator i, size_type pos, bool m = true, bool escape_k = false)
@ -381,6 +469,7 @@ public:
m_null.first = i;
m_null.second = i;
m_null.matched = false;
m_is_singular = false;
}
}
void BOOST_REGEX_CALL set_size(size_type n, BidiIterator i, BidiIterator j)
@ -411,6 +500,7 @@ public:
}
void BOOST_REGEX_CALL set_first(BidiIterator i)
{
BOOST_ASSERT(m_subs.size() > 2);
// set up prefix:
m_subs[1].second = i;
m_subs[1].matched = (m_subs[1].first != i);
@ -446,16 +536,32 @@ public:
}
private:
vector_type m_subs; // subexpressions
BidiIterator m_base; // where the search started from
sub_match<BidiIterator> m_null; // a null match
boost::shared_ptr<named_sub_type> m_named_subs;
int m_last_closed_paren;
//
// Error handler called when an uninitialized match_results is accessed:
//
static void raise_logic_error()
{
std::logic_error e("Attempt to access an uninitialzed boost::match_results<> class.");
boost::throw_exception(e);
}
vector_type m_subs; // subexpressions
BidiIterator m_base; // where the search started from
sub_match<BidiIterator> m_null; // a null match
boost::shared_ptr<named_sub_type> m_named_subs; // Shared copy of named subs in the regex object
int m_last_closed_paren; // Last ) to be seen - used for formatting
bool m_is_singular; // True if our stored iterators are singular
};
template <class BidiIterator, class Allocator>
void BOOST_REGEX_CALL match_results<BidiIterator, Allocator>::maybe_assign(const match_results<BidiIterator, Allocator>& m)
{
if(m_is_singular)
{
*this = m;
return;
}
const_iterator p1, p2;
p1 = begin();
p2 = m.begin();

View File

@ -188,7 +188,7 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_all_states()
if(!(this->*proc)())
{
if(state_count > max_state_count)
raise_error(traits_inst, regex_constants::error_space);
raise_error(traits_inst, regex_constants::error_complexity);
if((m_match_flags & match_partial) && (position == last) && (position != search_base))
m_has_partial_match = true;
bool successful_unwind = unwind(false);
@ -219,7 +219,7 @@ void perl_matcher<BidiIterator, Allocator, traits>::extend_stack()
m_backup_state = block;
}
else
raise_error(traits_inst, regex_constants::error_size);
raise_error(traits_inst, regex_constants::error_stack);
}
template <class BidiIterator, class Allocator, class traits>

View File

@ -99,7 +99,7 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_all_states()
};
if(state_count > max_state_count)
raise_error(traits_inst, regex_constants::error_space);
raise_error(traits_inst, regex_constants::error_complexity);
while(pstate)
{
matcher_proc_type proc = s_match_vtable[pstate->type];

View File

@ -1,7 +1,7 @@
/*
*
* Copyright (c) 1998-2002
* John Maddock
* Copyright (c) 1998-2009 John Maddock
* Copyright 2008 Eric Niebler.
*
* Use, modification and distribution are subject to the
* Boost Software License, Version 1.0. (See accompanying file
@ -21,6 +21,19 @@
#ifndef BOOST_REGEX_FORMAT_HPP
#define BOOST_REGEX_FORMAT_HPP
#include <boost/type_traits/is_pointer.hpp>
#include <boost/type_traits/is_function.hpp>
#include <boost/type_traits/is_class.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/type_traits/remove_pointer.hpp>
#include <boost/type_traits/remove_cv.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/and.hpp>
#include <boost/mpl/not.hpp>
#ifndef BOOST_NO_SFINAE
#include <boost/mpl/has_xxx.hpp>
#endif
namespace boost{
@ -76,15 +89,15 @@ struct trivial_format_traits
}
};
template <class OutputIterator, class Results, class traits>
template <class OutputIterator, class Results, class traits, class ForwardIter>
class basic_regex_formatter
{
public:
typedef typename traits::char_type char_type;
basic_regex_formatter(OutputIterator o, const Results& r, const traits& t)
: m_traits(t), m_results(r), m_out(o), m_state(output_copy), m_restore_state(output_copy), m_have_conditional(false) {}
OutputIterator format(const char_type* p1, const char_type* p2, match_flag_type f);
OutputIterator format(const char_type* p1, match_flag_type f)
OutputIterator format(ForwardIter p1, ForwardIter p2, match_flag_type f);
OutputIterator format(ForwardIter p1, match_flag_type f)
{
return format(p1, p1 + m_traits.length(p1), f);
}
@ -109,22 +122,75 @@ private:
void format_until_scope_end();
bool handle_perl_verb(bool have_brace);
const traits& m_traits; // the traits class for localised formatting operations
const Results& m_results; // the match_results being used.
OutputIterator m_out; // where to send output.
const char_type* m_position; // format string, current position
const char_type* m_end; // format string end
match_flag_type m_flags; // format flags to use
output_state m_state; // what to do with the next character
output_state m_restore_state; // what state to restore to.
bool m_have_conditional; // we are parsing a conditional
inline typename Results::value_type const& get_named_sub(ForwardIter i, ForwardIter j, const mpl::false_&)
{
std::vector<char_type> v(i, j);
return (i != j) ? this->m_results.named_subexpression(&v[0], &v[0] + v.size())
: this->m_results.named_subexpression(static_cast<const char_type*>(0), static_cast<const char_type*>(0));
}
inline typename Results::value_type const& get_named_sub(ForwardIter i, ForwardIter j, const mpl::true_&)
{
return this->m_results.named_subexpression(i, j);
}
inline typename Results::value_type const& get_named_sub(ForwardIter i, ForwardIter j)
{
typedef typename boost::is_convertible<ForwardIter, const char_type*>::type tag_type;
return get_named_sub(i, j, tag_type());
}
inline int get_named_sub_index(ForwardIter i, ForwardIter j, const mpl::false_&)
{
std::vector<char_type> v(i, j);
return (i != j) ? this->m_results.named_subexpression_index(&v[0], &v[0] + v.size())
: this->m_results.named_subexpression_index(static_cast<const char_type*>(0), static_cast<const char_type*>(0));
}
inline int get_named_sub_index(ForwardIter i, ForwardIter j, const mpl::true_&)
{
return this->m_results.named_subexpression_index(i, j);
}
inline int get_named_sub_index(ForwardIter i, ForwardIter j)
{
typedef typename boost::is_convertible<ForwardIter, const char_type*>::type tag_type;
return get_named_sub_index(i, j, tag_type());
}
inline int toi(ForwardIter& i, ForwardIter j, int base, const boost::mpl::false_&)
{
if(i != j)
{
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);
std::advance(i, pos - start);
return r;
}
return -1;
}
inline int toi(ForwardIter& i, ForwardIter j, int base, const boost::mpl::true_&)
{
return m_traits.toi(i, j, base);
}
inline int toi(ForwardIter& i, ForwardIter j, int base)
{
typedef typename boost::is_convertible<ForwardIter, const char_type*&>::type tag_type;
return toi(i, j, base, tag_type());
}
const traits& m_traits; // the traits class for localised formatting operations
const Results& m_results; // the match_results being used.
OutputIterator m_out; // where to send output.
ForwardIter m_position; // format string, current position
ForwardIter m_end; // format string end
match_flag_type m_flags; // format flags to use
output_state m_state; // what to do with the next character
output_state m_restore_state; // what state to restore to.
bool m_have_conditional; // we are parsing a conditional
private:
basic_regex_formatter(const basic_regex_formatter&);
basic_regex_formatter& operator=(const basic_regex_formatter&);
};
template <class OutputIterator, class Results, class traits>
OutputIterator basic_regex_formatter<OutputIterator, Results, traits>::format(const char_type* p1, const char_type* p2, match_flag_type f)
template <class OutputIterator, class Results, class traits, class ForwardIter>
OutputIterator basic_regex_formatter<OutputIterator, Results, traits, ForwardIter>::format(ForwardIter p1, ForwardIter p2, match_flag_type f)
{
m_position = p1;
m_end = p2;
@ -133,8 +199,8 @@ OutputIterator basic_regex_formatter<OutputIterator, Results, traits>::format(co
return m_out;
}
template <class OutputIterator, class Results, class traits>
void basic_regex_formatter<OutputIterator, Results, traits>::format_all()
template <class OutputIterator, class Results, class traits, class ForwardIter>
void basic_regex_formatter<OutputIterator, Results, traits, ForwardIter>::format_all()
{
// over and over:
while(m_position != m_end)
@ -211,8 +277,8 @@ void basic_regex_formatter<OutputIterator, Results, traits>::format_all()
}
}
template <class OutputIterator, class Results, class traits>
void basic_regex_formatter<OutputIterator, Results, traits>::format_perl()
template <class OutputIterator, class Results, class traits, class ForwardIter>
void basic_regex_formatter<OutputIterator, Results, traits, ForwardIter>::format_perl()
{
//
// On entry *m_position points to a '$' character
@ -233,7 +299,7 @@ void basic_regex_formatter<OutputIterator, Results, traits>::format_perl()
// OK find out what kind it is:
//
bool have_brace = false;
const char_type* save_position = m_position;
ForwardIter save_position = m_position;
switch(*m_position)
{
case '&':
@ -254,12 +320,12 @@ void basic_regex_formatter<OutputIterator, Results, traits>::format_perl()
case '+':
if((++m_position != m_end) && (*m_position == '{'))
{
const char_type* base = ++m_position;
ForwardIter base = ++m_position;
while((m_position != m_end) && (*m_position != '}')) ++m_position;
if(m_position != m_end)
{
// Named sub-expression:
put(this->m_results.named_subexpression(base, m_position));
put(get_named_sub(base, m_position));
++m_position;
break;
}
@ -279,7 +345,7 @@ void basic_regex_formatter<OutputIterator, Results, traits>::format_perl()
{
std::ptrdiff_t len = ::boost::re_detail::distance(m_position, m_end);
//len = (std::min)(static_cast<std::ptrdiff_t>(2), len);
int v = m_traits.toi(m_position, m_position + len, 10);
int v = this->toi(m_position, m_position + len, 10);
if((v < 0) || (have_brace && ((m_position == m_end) || (*m_position != '}'))))
{
// Look for a Perl-5.10 verb:
@ -300,8 +366,8 @@ void basic_regex_formatter<OutputIterator, Results, traits>::format_perl()
}
}
template <class OutputIterator, class Results, class traits>
bool basic_regex_formatter<OutputIterator, Results, traits>::handle_perl_verb(bool have_brace)
template <class OutputIterator, class Results, class traits, class ForwardIter>
bool basic_regex_formatter<OutputIterator, Results, traits, ForwardIter>::handle_perl_verb(bool have_brace)
{
//
// We may have a capitalised string containing a Perl action:
@ -313,6 +379,8 @@ bool basic_regex_formatter<OutputIterator, Results, traits>::handle_perl_verb(bo
static const char_type LAST_SUBMATCH_RESULT[] = { 'L', 'A', 'S', 'T', '_', 'S', 'U', 'B', 'M', 'A', 'T', 'C', 'H', '_', 'R', 'E', 'S', 'U', 'L', 'T' };
static const char_type LAST_SUBMATCH_RESULT_ALT[] = { '^', 'N' };
if(m_position == m_end)
return false;
if(have_brace && (*m_position == '^'))
++m_position;
@ -323,7 +391,7 @@ bool basic_regex_formatter<OutputIterator, Results, traits>::handle_perl_verb(bo
m_position += 5;
if(have_brace)
{
if(*m_position == '}')
if((m_position != m_end) && (*m_position == '}'))
++m_position;
else
{
@ -339,7 +407,7 @@ bool basic_regex_formatter<OutputIterator, Results, traits>::handle_perl_verb(bo
m_position += 8;
if(have_brace)
{
if(*m_position == '}')
if((m_position != m_end) && (*m_position == '}'))
++m_position;
else
{
@ -355,7 +423,7 @@ bool basic_regex_formatter<OutputIterator, Results, traits>::handle_perl_verb(bo
m_position += 9;
if(have_brace)
{
if(*m_position == '}')
if((m_position != m_end) && (*m_position == '}'))
++m_position;
else
{
@ -371,7 +439,7 @@ bool basic_regex_formatter<OutputIterator, Results, traits>::handle_perl_verb(bo
m_position += 16;
if(have_brace)
{
if(*m_position == '}')
if((m_position != m_end) && (*m_position == '}'))
++m_position;
else
{
@ -387,7 +455,7 @@ bool basic_regex_formatter<OutputIterator, Results, traits>::handle_perl_verb(bo
m_position += 20;
if(have_brace)
{
if(*m_position == '}')
if((m_position != m_end) && (*m_position == '}'))
++m_position;
else
{
@ -403,7 +471,7 @@ bool basic_regex_formatter<OutputIterator, Results, traits>::handle_perl_verb(bo
m_position += 2;
if(have_brace)
{
if(*m_position == '}')
if((m_position != m_end) && (*m_position == '}'))
++m_position;
else
{
@ -417,8 +485,8 @@ bool basic_regex_formatter<OutputIterator, Results, traits>::handle_perl_verb(bo
return false;
}
template <class OutputIterator, class Results, class traits>
void basic_regex_formatter<OutputIterator, Results, traits>::format_escape()
template <class OutputIterator, class Results, class traits, class ForwardIter>
void basic_regex_formatter<OutputIterator, Results, traits, ForwardIter>::format_escape()
{
// skip the escape and check for trailing escape:
if(++m_position == m_end)
@ -463,7 +531,7 @@ void basic_regex_formatter<OutputIterator, Results, traits>::format_escape()
if(*m_position == static_cast<char_type>('{'))
{
++m_position;
int val = m_traits.toi(m_position, m_end, 16);
int val = this->toi(m_position, m_end, 16);
if(val < 0)
{
// invalid value treat everything as literals:
@ -471,8 +539,9 @@ void basic_regex_formatter<OutputIterator, Results, traits>::format_escape()
put(static_cast<char_type>('{'));
return;
}
if(*m_position != static_cast<char_type>('}'))
if((m_position == m_end) || (*m_position != static_cast<char_type>('}')))
{
--m_position;
while(*m_position != static_cast<char_type>('\\'))
--m_position;
++m_position;
@ -487,7 +556,7 @@ void basic_regex_formatter<OutputIterator, Results, traits>::format_escape()
{
std::ptrdiff_t len = ::boost::re_detail::distance(m_position, m_end);
len = (std::min)(static_cast<std::ptrdiff_t>(2), len);
int val = m_traits.toi(m_position, m_position + len, 16);
int val = this->toi(m_position, m_position + len, 16);
if(val < 0)
{
--m_position;
@ -549,7 +618,9 @@ void basic_regex_formatter<OutputIterator, Results, traits>::format_escape()
break;
}
// see if we have a \n sed style backreference:
int v = m_traits.toi(m_position, m_position+1, 10);
std::ptrdiff_t len = ::boost::re_detail::distance(m_position, m_end);
len = (std::min)(static_cast<std::ptrdiff_t>(1), len);
int v = this->toi(m_position, m_position+len, 10);
if((v > 0) || ((v == 0) && (m_flags & ::boost::regex_constants::format_sed)))
{
put(m_results[v]);
@ -559,9 +630,9 @@ void basic_regex_formatter<OutputIterator, Results, traits>::format_escape()
{
// octal ecape sequence:
--m_position;
std::ptrdiff_t len = ::boost::re_detail::distance(m_position, m_end);
len = ::boost::re_detail::distance(m_position, m_end);
len = (std::min)(static_cast<std::ptrdiff_t>(4), len);
v = m_traits.toi(m_position, m_position + len, 8);
v = this->toi(m_position, m_position + len, 8);
BOOST_ASSERT(v >= 0);
put(static_cast<char_type>(v));
break;
@ -572,8 +643,8 @@ void basic_regex_formatter<OutputIterator, Results, traits>::format_escape()
}
}
template <class OutputIterator, class Results, class traits>
void basic_regex_formatter<OutputIterator, Results, traits>::format_conditional()
template <class OutputIterator, class Results, class traits, class ForwardIter>
void basic_regex_formatter<OutputIterator, Results, traits, ForwardIter>::format_conditional()
{
if(m_position == m_end)
{
@ -584,15 +655,15 @@ void basic_regex_formatter<OutputIterator, Results, traits>::format_conditional(
int v;
if(*m_position == '{')
{
const char_type* base = m_position;
ForwardIter base = m_position;
++m_position;
v = m_traits.toi(m_position, m_end, 10);
v = this->toi(m_position, m_end, 10);
if(v < 0)
{
// Try a named subexpression:
while((m_position != m_end) && (*m_position != '}'))
++m_position;
v = m_results.named_subexpression_index(base + 1, m_position);
v = this->get_named_sub_index(base + 1, m_position);
}
if((v < 0) || (*m_position != '}'))
{
@ -608,7 +679,7 @@ void basic_regex_formatter<OutputIterator, Results, traits>::format_conditional(
{
std::ptrdiff_t len = ::boost::re_detail::distance(m_position, m_end);
len = (std::min)(static_cast<std::ptrdiff_t>(2), len);
v = m_traits.toi(m_position, m_position + len, 10);
v = this->toi(m_position, m_position + len, 10);
}
if(v < 0)
{
@ -657,8 +728,8 @@ void basic_regex_formatter<OutputIterator, Results, traits>::format_conditional(
}
}
template <class OutputIterator, class Results, class traits>
void basic_regex_formatter<OutputIterator, Results, traits>::format_until_scope_end()
template <class OutputIterator, class Results, class traits, class ForwardIter>
void basic_regex_formatter<OutputIterator, Results, traits, ForwardIter>::format_until_scope_end()
{
do
{
@ -669,8 +740,8 @@ void basic_regex_formatter<OutputIterator, Results, traits>::format_until_scope_
}while(m_position != m_end);
}
template <class OutputIterator, class Results, class traits>
void basic_regex_formatter<OutputIterator, Results, traits>::put(char_type c)
template <class OutputIterator, class Results, class traits, class ForwardIter>
void basic_regex_formatter<OutputIterator, Results, traits, ForwardIter>::put(char_type c)
{
// write a single character to output
// according to which case translation mode we are in:
@ -699,8 +770,8 @@ void basic_regex_formatter<OutputIterator, Results, traits>::put(char_type c)
++m_out;
}
template <class OutputIterator, class Results, class traits>
void basic_regex_formatter<OutputIterator, Results, traits>::put(const sub_match_type& sub)
template <class OutputIterator, class Results, class traits, class ForwardIter>
void basic_regex_formatter<OutputIterator, Results, traits, ForwardIter>::put(const sub_match_type& sub)
{
typedef typename sub_match_type::iterator iterator_type;
iterator_type i = sub.first;
@ -738,10 +809,10 @@ public:
#endif
};
template <class OutputIterator, class Iterator, class Alloc, class charT, class traits>
template <class OutputIterator, class Iterator, class Alloc, class ForwardIter, class traits>
OutputIterator regex_format_imp(OutputIterator out,
const match_results<Iterator, Alloc>& m,
const charT* p1, const charT* p2,
ForwardIter p1, ForwardIter p2,
match_flag_type flags,
const traits& t
)
@ -754,57 +825,289 @@ OutputIterator regex_format_imp(OutputIterator out,
re_detail::basic_regex_formatter<
OutputIterator,
match_results<Iterator, Alloc>,
traits > f(out, m, t);
traits, ForwardIter> f(out, m, t);
return f.format(p1, p2, flags);
}
#ifndef BOOST_NO_SFINAE
BOOST_MPL_HAS_XXX_TRAIT_DEF(const_iterator)
struct any_type { any_type(...); };
typedef char no_type;
typedef char (&unary_type)[2];
typedef char (&binary_type)[3];
typedef char (&ternary_type)[4];
no_type check_is_formatter(unary_type, binary_type, ternary_type);
template<typename T>
unary_type check_is_formatter(T const &, binary_type, ternary_type);
template<typename T>
binary_type check_is_formatter(unary_type, T const &, ternary_type);
template<typename T, typename U>
binary_type check_is_formatter(T const &, U const &, ternary_type);
template<typename T>
ternary_type check_is_formatter(unary_type, binary_type, T const &);
template<typename T, typename U>
ternary_type check_is_formatter(T const &, binary_type, U const &);
template<typename T, typename U>
ternary_type check_is_formatter(unary_type, T const &, U const &);
template<typename T, typename U, typename V>
ternary_type check_is_formatter(T const &, U const &, V const &);
struct unary_binary_ternary
{
typedef unary_type (*unary_fun)(any_type);
typedef binary_type (*binary_fun)(any_type, any_type);
typedef ternary_type (*ternary_fun)(any_type, any_type, any_type);
operator unary_fun();
operator binary_fun();
operator ternary_fun();
};
template<typename Formatter, bool IsFunction = boost::is_function<Formatter>::value>
struct formatter_wrapper
: Formatter
, unary_binary_ternary
{
formatter_wrapper(){}
};
template<typename Formatter>
struct formatter_wrapper<Formatter, true>
: unary_binary_ternary
{
operator Formatter *();
};
template<typename Formatter>
struct formatter_wrapper<Formatter *, false>
: unary_binary_ternary
{
operator Formatter *();
};
template <class F, class M, class O>
struct format_traits_imp
{
private:
//
// F must be a pointer, a function, or a class with a function call operator:
//
BOOST_STATIC_ASSERT((::boost::is_pointer<F>::value || ::boost::is_function<F>::value || ::boost::is_class<F>::value));
static formatter_wrapper<F> f;
static M m;
static O out;
static boost::regex_constants::match_flag_type flags;
public:
BOOST_STATIC_CONSTANT(int, value = sizeof(check_is_formatter(f(m), f(m, out), f(m, out, flags))));
};
template <class F, class M, class O>
struct format_traits
{
public:
//
// Type is mpl::int_<N> where N is one of:
//
// 0 : F is a pointer to a presumably null-terminated string.
// 1 : F is a character-container such as a std::string.
// 2 : F is a Unary Functor.
// 3 : F is a Binary Functor.
// 4 : F is a Ternary Functor.
//
typedef typename boost::mpl::if_<
boost::mpl::and_<boost::is_pointer<F>, boost::mpl::not_<boost::is_function<typename boost::remove_pointer<F>::type> > >,
boost::mpl::int_<0>,
typename boost::mpl::if_<
has_const_iterator<F>,
boost::mpl::int_<1>,
boost::mpl::int_<format_traits_imp<F, M, O>::value>
>::type
>::type type;
//
// This static assertion will fail if the functor passed does not accept
// the same type of arguments passed.
//
BOOST_STATIC_ASSERT( boost::is_class<F>::value && !has_const_iterator<F>::value ? (type::value > 1) : true);
};
#else // BOOST_NO_SFINAE
template <class F, class M, class O>
struct format_traits
{
public:
//
// Type is mpl::int_<N> where N is one of:
//
// 0 : F is a pointer to a presumably null-terminated string.
// 1 : F is a character-container such as a std::string.
//
// Other options such as F being a Functor are not supported without
// SFINAE support.
//
typedef typename boost::mpl::if_<
boost::is_pointer<F>,
boost::mpl::int_<0>,
boost::mpl::int_<1>
>::type type;
};
#endif // BOOST_NO_SFINAE
template <class Base, class Match>
struct format_functor3
{
format_functor3(Base b) : func(b) {}
template <class OutputIter>
OutputIter operator()(const Match& m, OutputIter i, boost::regex_constants::match_flag_type f)
{
return func(m, i, f);
}
template <class OutputIter, class Traits>
OutputIter operator()(const Match& m, OutputIter i, boost::regex_constants::match_flag_type f, const Traits&)
{
return (*this)(m, i, f);
}
private:
Base func;
format_functor3(const format_functor3&);
format_functor3& operator=(const format_functor3&);
};
template <class Base, class Match>
struct format_functor2
{
format_functor2(Base b) : func(b) {}
template <class OutputIter>
OutputIter operator()(const Match& m, OutputIter i, boost::regex_constants::match_flag_type /*f*/)
{
return func(m, i);
}
template <class OutputIter, class Traits>
OutputIter operator()(const Match& m, OutputIter i, boost::regex_constants::match_flag_type f, const Traits&)
{
return (*this)(m, i, f);
}
private:
Base func;
format_functor2(const format_functor2&);
format_functor2& operator=(const format_functor2&);
};
template <class Base, class Match>
struct format_functor1
{
format_functor1(Base b) : func(b) {}
template <class S, class OutputIter>
OutputIter do_format_string(const S& s, OutputIter i)
{
return re_detail::copy(s.begin(), s.end(), i);
}
template <class S, class OutputIter>
inline OutputIter do_format_string(const S* s, OutputIter i)
{
while(s && *s)
{
*i = *s;
++i;
++s;
}
return i;
}
template <class OutputIter>
OutputIter operator()(const Match& m, OutputIter i, boost::regex_constants::match_flag_type /*f*/)
{
return do_format_string(func(m), i);
}
template <class OutputIter, class Traits>
OutputIter operator()(const Match& m, OutputIter i, boost::regex_constants::match_flag_type f, const Traits&)
{
return (*this)(m, i, f);
}
private:
Base func;
format_functor1(const format_functor1&);
format_functor1& operator=(const format_functor1&);
};
template <class charT, class Match, class Traits>
struct format_functor_c_string
{
format_functor_c_string(const charT* ps) : func(ps) {}
template <class OutputIter>
OutputIter operator()(const Match& m, OutputIter i, boost::regex_constants::match_flag_type f, const Traits& t = Traits())
{
typedef typename Match::char_type char_type;
const charT* end = func;
while(*end) ++end;
return regex_format_imp(i, m, func, end, f, t);
}
private:
const charT* func;
format_functor_c_string(const format_functor_c_string&);
format_functor_c_string& operator=(const format_functor_c_string&);
};
template <class Container, class Match, class Traits>
struct format_functor_container
{
format_functor_container(const Container& c) : func(c) {}
template <class OutputIter>
OutputIter operator()(const Match& m, OutputIter i, boost::regex_constants::match_flag_type f, const Traits& t = Traits())
{
typedef typename Match::char_type char_type;
return re_detail::regex_format_imp(i, m, func.begin(), func.end(), f, t);
}
private:
const Container& func;
format_functor_container(const format_functor_container&);
format_functor_container& operator=(const format_functor_container&);
};
template <class Func, class Match, class OutputIterator, class Traits = re_detail::trivial_format_traits<typename Match::char_type> >
struct compute_functor_type
{
typedef typename format_traits<Func, Match, OutputIterator>::type tag;
typedef typename boost::remove_cv< typename boost::remove_pointer<Func>::type>::type maybe_char_type;
typedef typename mpl::if_<
::boost::is_same<tag, mpl::int_<0> >, format_functor_c_string<maybe_char_type, Match, Traits>,
typename mpl::if_<
::boost::is_same<tag, mpl::int_<1> >, format_functor_container<Func, Match, Traits>,
typename mpl::if_<
::boost::is_same<tag, mpl::int_<2> >, format_functor1<Func, Match>,
typename mpl::if_<
::boost::is_same<tag, mpl::int_<3> >, format_functor2<Func, Match>,
format_functor3<Func, Match>
>::type
>::type
>::type
>::type type;
};
} // namespace re_detail
template <class OutputIterator, class Iterator, class charT>
OutputIterator regex_format(OutputIterator out,
const match_results<Iterator>& m,
const charT* fmt,
template <class OutputIterator, class Iterator, class Allocator, class Functor>
inline OutputIterator regex_format(OutputIterator out,
const match_results<Iterator, Allocator>& m,
Functor fmt,
match_flag_type flags = format_all
)
{
re_detail::trivial_format_traits<charT> traits;
return re_detail::regex_format_imp(out, m, fmt, fmt + traits.length(fmt), flags, traits);
return m.format(out, fmt, flags);
}
template <class OutputIterator, class Iterator, class charT>
OutputIterator regex_format(OutputIterator out,
const match_results<Iterator>& m,
const std::basic_string<charT>& fmt,
match_flag_type flags = format_all
)
{
re_detail::trivial_format_traits<charT> traits;
return re_detail::regex_format_imp(out, m, fmt.data(), fmt.data() + fmt.size(), flags, traits);
}
template <class Iterator, class charT>
std::basic_string<charT> regex_format(const match_results<Iterator>& m,
const charT* fmt,
template <class Iterator, class Allocator, class Functor>
inline std::basic_string<typename match_results<Iterator, Allocator>::char_type> regex_format(const match_results<Iterator, Allocator>& m,
Functor fmt,
match_flag_type flags = format_all)
{
std::basic_string<charT> result;
re_detail::string_out_iterator<std::basic_string<charT> > i(result);
re_detail::trivial_format_traits<charT> traits;
re_detail::regex_format_imp(i, m, fmt, fmt + traits.length(fmt), flags, traits);
return result;
}
template <class Iterator, class charT>
std::basic_string<charT> regex_format(const match_results<Iterator>& m,
const std::basic_string<charT>& fmt,
match_flag_type flags = format_all)
{
std::basic_string<charT> result;
re_detail::string_out_iterator<std::basic_string<charT> > i(result);
re_detail::trivial_format_traits<charT> traits;
re_detail::regex_format_imp(i, m, fmt.data(), fmt.data() + fmt.size(), flags, traits);
return result;
return m.format(fmt, flags);
}
#ifdef BOOST_MSVC

View File

@ -1,6 +1,6 @@
/*
*
* Copyright (c) 1998-2002
* Copyright (c) 1998-2009
* John Maddock
*
* Use, modification and distribution are subject to the
@ -35,12 +35,12 @@ namespace boost{
#pragma warning(pop)
#endif
template <class OutputIterator, class BidirectionalIterator, class traits, class charT>
template <class OutputIterator, class BidirectionalIterator, class traits, class charT, class Formatter>
OutputIterator regex_replace(OutputIterator out,
BidirectionalIterator first,
BidirectionalIterator last,
const basic_regex<charT, traits>& e,
const charT* fmt,
Formatter fmt,
match_flag_type flags = match_default)
{
regex_iterator<BidirectionalIterator, charT, traits> i(first, last, e, flags);
@ -69,21 +69,10 @@ OutputIterator regex_replace(OutputIterator out,
return out;
}
template <class OutputIterator, class Iterator, class traits, class charT>
inline OutputIterator regex_replace(OutputIterator out,
Iterator first,
Iterator last,
const basic_regex<charT, traits>& e,
const std::basic_string<charT>& fmt,
match_flag_type flags = match_default)
{
return regex_replace(out, first, last, e, fmt.c_str(), flags);
}
template <class traits, class charT>
template <class traits, class charT, class Formatter>
std::basic_string<charT> regex_replace(const std::basic_string<charT>& s,
const basic_regex<charT, traits>& e,
const charT* fmt,
Formatter fmt,
match_flag_type flags = match_default)
{
std::basic_string<charT> result;
@ -92,18 +81,6 @@ std::basic_string<charT> regex_replace(const std::basic_string<charT>& s,
return result;
}
template <class traits, class charT>
std::basic_string<charT> regex_replace(const std::basic_string<charT>& s,
const basic_regex<charT, traits>& e,
const std::basic_string<charT>& fmt,
match_flag_type flags = match_default)
{
std::basic_string<charT> result;
re_detail::string_out_iterator<std::basic_string<charT> > i(result);
regex_replace(i, s.begin(), s.end(), e, fmt.c_str(), flags);
return result;
}
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable: 4103)

View File

@ -322,7 +322,7 @@ inline const charT* get_escape_R_string()
{
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable:4309)
# pragma warning(disable:4309 4245)
#endif
static const charT e1[] = { '(', '?', '>', '\x0D', '\x0A', '?',
'|', '[', '\x0A', '\x0B', '\x0C', '\x85', '\\', 'x', '{', '2', '0', '2', '8', '}',

View File

@ -178,7 +178,7 @@ inline u32regex_iterator<typename std::basic_string<charT, Traits, Alloc>::const
typedef typename std::basic_string<charT, Traits, Alloc>::const_iterator iter_type;
return u32regex_iterator<iter_type>(p.begin(), p.end(), e, m);
}
inline u32regex_iterator<const UChar*> make_u32regex_iterator(const UnicodeString& s, const u32regex& e, regex_constants::match_flag_type m = regex_constants::match_default)
inline u32regex_iterator<const UChar*> make_u32regex_iterator(const U_NAMESPACE_QUALIFIER UnicodeString& s, const u32regex& e, regex_constants::match_flag_type m = regex_constants::match_default)
{
return u32regex_iterator<const UChar*>(s.getBuffer(), s.getBuffer() + s.length(), e, m);
}

View File

@ -294,7 +294,7 @@ inline u32regex_token_iterator<typename std::basic_string<charT, Traits, Alloc>:
typedef typename std::basic_string<charT, Traits, Alloc>::const_iterator iter_type;
return u32regex_token_iterator<iter_type>(p.begin(), p.end(), e, m);
}
inline u32regex_token_iterator<const UChar*> make_u32regex_token_iterator(const UnicodeString& s, const u32regex& e, int submatch = 0, regex_constants::match_flag_type m = regex_constants::match_default)
inline u32regex_token_iterator<const UChar*> make_u32regex_token_iterator(const U_NAMESPACE_QUALIFIER UnicodeString& s, const u32regex& e, int submatch = 0, regex_constants::match_flag_type m = regex_constants::match_default)
{
return u32regex_token_iterator<const UChar*>(s.getBuffer(), s.getBuffer() + s.length(), e, submatch, m);
}
@ -327,7 +327,7 @@ inline u32regex_token_iterator<typename std::basic_string<charT, Traits, Alloc>:
return u32regex_token_iterator<iter_type>(p.begin(), p.end(), e, m);
}
template <std::size_t N>
inline u32regex_token_iterator<const UChar*> make_u32regex_token_iterator(const UnicodeString& s, const u32regex& e, const int (&submatch)[N], regex_constants::match_flag_type m = regex_constants::match_default)
inline u32regex_token_iterator<const UChar*> make_u32regex_token_iterator(const U_NAMESPACE_QUALIFIER UnicodeString& s, const u32regex& e, const int (&submatch)[N], regex_constants::match_flag_type m = regex_constants::match_default)
{
return u32regex_token_iterator<const UChar*>(s.getBuffer(), s.getBuffer() + s.length(), e, submatch, m);
}
@ -356,7 +356,7 @@ inline u32regex_token_iterator<typename std::basic_string<charT, Traits, Alloc>:
typedef typename std::basic_string<charT, Traits, Alloc>::const_iterator iter_type;
return u32regex_token_iterator<iter_type>(p.begin(), p.end(), e, m);
}
inline u32regex_token_iterator<const UChar*> make_u32regex_token_iterator(const UnicodeString& s, const u32regex& e, const std::vector<int>& submatch, regex_constants::match_flag_type m = regex_constants::match_default)
inline u32regex_token_iterator<const UChar*> make_u32regex_token_iterator(const U_NAMESPACE_QUALIFIER UnicodeString& s, const u32regex& e, const std::vector<int>& submatch, regex_constants::match_flag_type m = regex_constants::match_default)
{
return u32regex_token_iterator<const UChar*>(s.getBuffer(), s.getBuffer() + s.length(), e, submatch, m);
}