mirror of
https://github.com/boostorg/regex.git
synced 2025-07-16 13:52:17 +02:00
Added support for function objects as well as strings when formatting.
Updated and regenerated docs. [SVN r57250]
This commit is contained in:
@ -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& 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& 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&);
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 1998-2002
|
||||
* Copyright (c) 1998-2009
|
||||
* John Maddock
|
||||
*
|
||||
* Use, modification and distribution are subject to the
|
||||
@ -282,42 +282,55 @@ 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);
|
||||
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);
|
||||
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());
|
||||
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());
|
||||
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
|
||||
{
|
||||
return m_last_closed_paren == 0 ? m_null : (*this)[m_last_closed_paren];
|
||||
|
@ -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]);
|
||||
@ -561,7 +632,7 @@ void basic_regex_formatter<OutputIterator, Results, traits>::format_escape()
|
||||
--m_position;
|
||||
std::ptrdiff_t 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,279 @@ 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;
|
||||
};
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
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
|
||||
|
@ -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)
|
||||
|
Reference in New Issue
Block a user