summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '3rdParty/Boost/src/boost/regex/v4/regex_format.hpp')
-rw-r--r--3rdParty/Boost/src/boost/regex/v4/regex_format.hpp640
1 files changed, 555 insertions, 85 deletions
diff --git a/3rdParty/Boost/src/boost/regex/v4/regex_format.hpp b/3rdParty/Boost/src/boost/regex/v4/regex_format.hpp
index d114c2e..0ca9baa 100644
--- a/3rdParty/Boost/src/boost/regex/v4/regex_format.hpp
+++ b/3rdParty/Boost/src/boost/regex/v4/regex_format.hpp
@@ -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);
}
@@ -107,23 +120,77 @@ private:
void format_escape();
void format_conditional();
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;
@@ -132,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)
@@ -210,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
@@ -232,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 '&':
@@ -250,6 +317,25 @@ void basic_regex_formatter<OutputIterator, Results, traits>::format_perl()
case '$':
put(*m_position++);
break;
+ case '+':
+ if((++m_position != m_end) && (*m_position == '{'))
+ {
+ ForwardIter base = ++m_position;
+ while((m_position != m_end) && (*m_position != '}')) ++m_position;
+ if(m_position != m_end)
+ {
+ // Named sub-expression:
+ put(get_named_sub(base, m_position));
+ ++m_position;
+ break;
+ }
+ else
+ {
+ m_position = --base;
+ }
+ }
+ put((this->m_results)[this->m_results.size() > 1 ? this->m_results.size() - 1 : 1]);
+ break;
case '{':
have_brace = true;
++m_position;
@@ -258,14 +344,18 @@ void basic_regex_formatter<OutputIterator, Results, traits>::format_perl()
// see if we have a number:
{
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);
+ //len = (std::min)(static_cast<std::ptrdiff_t>(2), len);
+ int v = this->toi(m_position, m_position + len, 10);
if((v < 0) || (have_brace && ((m_position == m_end) || (*m_position != '}'))))
{
- // leave the $ as is, and carry on:
- m_position = --save_position;
- put(*m_position);
- ++m_position;
+ // Look for a Perl-5.10 verb:
+ if(!handle_perl_verb(have_brace))
+ {
+ // leave the $ as is, and carry on:
+ m_position = --save_position;
+ put(*m_position);
+ ++m_position;
+ }
break;
}
// otherwise output sub v:
@@ -276,8 +366,127 @@ void basic_regex_formatter<OutputIterator, Results, traits>::format_perl()
}
}
-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>
+bool basic_regex_formatter<OutputIterator, Results, traits, ForwardIter>::handle_perl_verb(bool have_brace)
+{
+ //
+ // We may have a capitalised string containing a Perl action:
+ //
+ static const char_type MATCH[] = { 'M', 'A', 'T', 'C', 'H' };
+ static const char_type PREMATCH[] = { 'P', 'R', 'E', 'M', 'A', 'T', 'C', 'H' };
+ static const char_type POSTMATCH[] = { 'P', 'O', 'S', 'T', 'M', 'A', 'T', 'C', 'H' };
+ static const char_type LAST_PAREN_MATCH[] = { 'L', 'A', 'S', 'T', '_', 'P', 'A', 'R', 'E', 'N', '_', 'M', 'A', 'T', 'C', 'H' };
+ 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;
+
+ int max_len = m_end - m_position;
+
+ if((max_len >= 5) && std::equal(m_position, m_position + 5, MATCH))
+ {
+ m_position += 5;
+ if(have_brace)
+ {
+ if((m_position != m_end) && (*m_position == '}'))
+ ++m_position;
+ else
+ {
+ m_position -= 5;
+ return false;
+ }
+ }
+ put(this->m_results[0]);
+ return true;
+ }
+ if((max_len >= 8) && std::equal(m_position, m_position + 8, PREMATCH))
+ {
+ m_position += 8;
+ if(have_brace)
+ {
+ if((m_position != m_end) && (*m_position == '}'))
+ ++m_position;
+ else
+ {
+ m_position -= 8;
+ return false;
+ }
+ }
+ put(this->m_results.prefix());
+ return true;
+ }
+ if((max_len >= 9) && std::equal(m_position, m_position + 9, POSTMATCH))
+ {
+ m_position += 9;
+ if(have_brace)
+ {
+ if((m_position != m_end) && (*m_position == '}'))
+ ++m_position;
+ else
+ {
+ m_position -= 9;
+ return false;
+ }
+ }
+ put(this->m_results.suffix());
+ return true;
+ }
+ if((max_len >= 16) && std::equal(m_position, m_position + 16, LAST_PAREN_MATCH))
+ {
+ m_position += 16;
+ if(have_brace)
+ {
+ if((m_position != m_end) && (*m_position == '}'))
+ ++m_position;
+ else
+ {
+ m_position -= 16;
+ return false;
+ }
+ }
+ put((this->m_results)[this->m_results.size() > 1 ? this->m_results.size() - 1 : 1]);
+ return true;
+ }
+ if((max_len >= 20) && std::equal(m_position, m_position + 20, LAST_SUBMATCH_RESULT))
+ {
+ m_position += 20;
+ if(have_brace)
+ {
+ if((m_position != m_end) && (*m_position == '}'))
+ ++m_position;
+ else
+ {
+ m_position -= 20;
+ return false;
+ }
+ }
+ put(this->m_results.get_last_closed_paren());
+ return true;
+ }
+ if((max_len >= 2) && std::equal(m_position, m_position + 2, LAST_SUBMATCH_RESULT_ALT))
+ {
+ m_position += 2;
+ if(have_brace)
+ {
+ if((m_position != m_end) && (*m_position == '}'))
+ ++m_position;
+ else
+ {
+ m_position -= 2;
+ return false;
+ }
+ }
+ put(this->m_results.get_last_closed_paren());
+ return true;
+ }
+ return false;
+}
+
+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)
@@ -322,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:
@@ -330,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;
@@ -346,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;
@@ -408,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]);
@@ -418,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;
@@ -431,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)
{
@@ -440,9 +652,35 @@ void basic_regex_formatter<OutputIterator, Results, traits>::format_conditional(
put(static_cast<char_type>('?'));
return;
}
- 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;
+ if(*m_position == '{')
+ {
+ ForwardIter base = m_position;
+ ++m_position;
+ 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 = this->get_named_sub_index(base + 1, m_position);
+ }
+ if((v < 0) || (*m_position != '}'))
+ {
+ m_position = base;
+ // oops trailing '?':
+ put(static_cast<char_type>('?'));
+ return;
+ }
+ // Skip trailing '}':
+ ++m_position;
+ }
+ else
+ {
+ std::ptrdiff_t len = ::boost::re_detail::distance(m_position, m_end);
+ len = (std::min)(static_cast<std::ptrdiff_t>(2), len);
+ v = this->toi(m_position, m_position + len, 10);
+ }
if(v < 0)
{
// oops not a number:
@@ -490,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
{
@@ -502,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:
@@ -532,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;
@@ -571,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
)
@@ -587,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
-} // namespace re_detail
+BOOST_MPL_HAS_XXX_TRAIT_DEF(const_iterator)
-template <class OutputIterator, class Iterator, class charT>
-OutputIterator regex_format(OutputIterator out,
- const match_results<Iterator>& m,
- const charT* fmt,
- match_flag_type flags = format_all
- )
+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
{
- re_detail::trivial_format_traits<charT> traits;
- return re_detail::regex_format_imp(out, m, fmt, fmt + traits.length(fmt), flags, traits);
-}
+ 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 <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
- )
+template<typename Formatter, bool IsFunction = boost::is_function<Formatter>::value>
+struct formatter_wrapper
+ : Formatter
+ , unary_binary_ternary
{
- re_detail::trivial_format_traits<charT> traits;
- return re_detail::regex_format_imp(out, m, fmt.data(), fmt.data() + fmt.size(), flags, traits);
-}
+ formatter_wrapper(){}
+};
-template <class Iterator, class charT>
-std::basic_string<charT> regex_format(const match_results<Iterator>& m,
- const charT* fmt,
- match_flag_type flags = format_all)
+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 Allocator, class Functor>
+inline OutputIterator regex_format(OutputIterator out,
+ 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;
+ return m.format(out, fmt, flags);
}
-template <class Iterator, class charT>
-std::basic_string<charT> regex_format(const match_results<Iterator>& m,
- const std::basic_string<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.data(), fmt.data() + fmt.size(), flags, traits);
- return result;
+ return m.format(fmt, flags);
}
#ifdef BOOST_MSVC