|
Boost-Commit : |
From: eric_at_[hidden]
Date: 2008-03-15 19:43:23
Author: eric_niebler
Date: 2008-03-15 19:43:21 EDT (Sat, 15 Mar 2008)
New Revision: 43641
URL: http://svn.boost.org/trac/boost/changeset/43641
Log:
range-based regex_replace, address LWG issues #726 and #727, misc. feedback about proto and docs
Text files modified:
trunk/boost/xpressive/match_results.hpp | 122 +++++++++++++++-------
trunk/boost/xpressive/proto/context/callable.hpp | 2
trunk/boost/xpressive/proto/debug.hpp | 3
trunk/boost/xpressive/proto/deep_copy.hpp | 2
trunk/boost/xpressive/proto/domain.hpp | 1
trunk/boost/xpressive/proto/expr.hpp | 3
trunk/boost/xpressive/proto/extends.hpp | 3
trunk/boost/xpressive/proto/fusion.hpp | 11 -
trunk/boost/xpressive/proto/matches.hpp | 1
trunk/boost/xpressive/proto/transform/fold_tree.hpp | 2
trunk/boost/xpressive/proto/transform/make.hpp | 15 --
trunk/boost/xpressive/proto/transform/pass_through.hpp | 20 +-
trunk/boost/xpressive/regex_algorithms.hpp | 220 ++++++++++++++++++++++++++++++++-------
trunk/libs/xpressive/proto/doc/construction.qbk | 18 +-
trunk/libs/xpressive/proto/doc/transforms.qbk | 2
trunk/libs/xpressive/proto/example/calc1.cpp | 12 +-
trunk/libs/xpressive/proto/example/calc2.cpp | 12 +-
trunk/libs/xpressive/proto/example/lambda.cpp | 14 +-
trunk/libs/xpressive/proto/example/mixed.cpp | 18 +-
trunk/libs/xpressive/proto/test/examples.cpp | 4
trunk/libs/xpressive/test/regress.ipp | 15 ++
21 files changed, 340 insertions(+), 160 deletions(-)
Modified: trunk/boost/xpressive/match_results.hpp
==============================================================================
--- trunk/boost/xpressive/match_results.hpp (original)
+++ trunk/boost/xpressive/match_results.hpp 2008-03-15 19:43:21 EDT (Sat, 15 Mar 2008)
@@ -441,30 +441,26 @@
OutputIterator format
(
OutputIterator out
- , const string_type &fmt
+ , string_type const &fmt
, regex_constants::match_flag_type flags = regex_constants::format_default
) const
{
- typename string_type::const_iterator cur = fmt.begin(), end = fmt.end();
-
- if(0 != (regex_constants::format_literal & flags))
- {
- return std::copy(cur, end, out);
- }
- else if(0 != (regex_constants::format_perl & flags))
- {
- return this->format_perl_(cur, end, out);
- }
- else if(0 != (regex_constants::format_sed & flags))
- {
- return this->format_sed_(cur, end, out);
- }
- else if(0 != (regex_constants::format_all & flags))
- {
- return this->format_all_(cur, end, out);
- }
+ char_type const *cur = &*fmt.begin(), *end = &*fmt.begin() + fmt.size();
+ return this->format_(out, cur, end, flags);
+ }
- return this->format_ecma_262_(cur, end, out);
+ /// \overload
+ ///
+ template<typename OutputIterator>
+ OutputIterator format
+ (
+ OutputIterator out
+ , char_type const *fmt
+ , regex_constants::match_flag_type flags = regex_constants::format_default
+ ) const
+ {
+ char_type const *end = fmt + std::char_traits<char_type>::length(fmt);
+ return this->format_(out, fmt, end, flags);
}
/// Returns a copy of the string fmt. For each format specifier or escape sequence in fmt,
@@ -472,7 +468,11 @@
/// *this to which it refers. The bitmasks specified in flags determines what format specifiers
/// or escape sequences are recognized, by default this is the format used by ECMA-262,
/// ECMAScript Language Specification, Chapter 15 part 5.4.11 String.prototype.replace.
- string_type format(string_type const &fmt, regex_constants::match_flag_type flags = regex_constants::format_default) const
+ string_type format
+ (
+ string_type const &fmt
+ , regex_constants::match_flag_type flags = regex_constants::format_default
+ ) const
{
string_type result;
result.reserve(fmt.length() * 2);
@@ -480,6 +480,19 @@
return result;
}
+ /// \overload
+ ///
+ string_type format
+ (
+ char_type const *fmt
+ , regex_constants::match_flag_type flags = regex_constants::format_default
+ ) const
+ {
+ string_type result;
+ this->format(std::back_inserter(result), fmt, flags);
+ return result;
+ }
+
/// Swaps the contents of two match_results objects. Guaranteed not to throw.
/// \param that The match_results object to swap with.
/// \post *this contains the sequence of matched sub-expressions that were in that,
@@ -655,8 +668,39 @@
/// INTERNAL ONLY
///
- template<typename ForwardIterator, typename OutputIterator>
- OutputIterator format_ecma_262_(ForwardIterator cur, ForwardIterator end, OutputIterator out) const
+ template<typename OutputIterator>
+ OutputIterator format_
+ (
+ OutputIterator out
+ , char_type const *cur
+ , char_type const *end
+ , regex_constants::match_flag_type flags = regex_constants::format_default
+ ) const
+ {
+ if(0 != (regex_constants::format_literal & flags))
+ {
+ return std::copy(cur, end, out);
+ }
+ else if(0 != (regex_constants::format_perl & flags))
+ {
+ return this->format_perl_(cur, end, out);
+ }
+ else if(0 != (regex_constants::format_sed & flags))
+ {
+ return this->format_sed_(cur, end, out);
+ }
+ else if(0 != (regex_constants::format_all & flags))
+ {
+ return this->format_all_(cur, end, out);
+ }
+
+ return this->format_ecma_262_(cur, end, out);
+ }
+
+ /// INTERNAL ONLY
+ ///
+ template<typename OutputIterator>
+ OutputIterator format_ecma_262_(char_type const *cur, char_type const *end, OutputIterator out) const
{
while(cur != end)
{
@@ -677,8 +721,8 @@
/// INTERNAL ONLY
///
- template<typename ForwardIterator, typename OutputIterator>
- OutputIterator format_sed_(ForwardIterator cur, ForwardIterator end, OutputIterator out) const
+ template<typename OutputIterator>
+ OutputIterator format_sed_(char_type const *cur, char_type const *end, OutputIterator out) const
{
while(cur != end)
{
@@ -704,8 +748,8 @@
/// INTERNAL ONLY
///
- template<typename ForwardIterator, typename OutputIterator>
- OutputIterator format_perl_(ForwardIterator cur, ForwardIterator end, OutputIterator out) const
+ template<typename OutputIterator>
+ OutputIterator format_perl_(char_type const *cur, char_type const *end, OutputIterator out) const
{
detail::case_converting_iterator<OutputIterator, char_type> iout(out, this->traits_.get());
@@ -739,8 +783,8 @@
/// INTERNAL ONLY
///
- template<typename ForwardIterator, typename OutputIterator>
- OutputIterator format_all_(ForwardIterator cur, ForwardIterator end, OutputIterator out) const
+ template<typename OutputIterator>
+ OutputIterator format_all_(char_type const *cur, char_type const *end, OutputIterator out) const
{
detail::case_converting_iterator<OutputIterator, char_type> iout(out, this->traits_.get());
iout = this->format_all_impl_(cur, end, iout);
@@ -751,8 +795,8 @@
/// INTERNAL ONLY
///
- template<typename ForwardIterator, typename OutputIterator>
- OutputIterator format_all_impl_(ForwardIterator &cur, ForwardIterator end, OutputIterator out, bool metacolon = false) const
+ template<typename OutputIterator>
+ OutputIterator format_all_impl_(char_type const *&cur, char_type const *end, OutputIterator out, bool metacolon = false) const
{
int max = 0, sub = 0;
detail::noop_output_iterator<char_type> noop;
@@ -825,8 +869,8 @@
template<typename OutputIterator>
OutputIterator format_backref_
(
- typename string_type::const_iterator &cur
- , typename string_type::const_iterator end
+ char_type const *&cur
+ , char_type const *end
, OutputIterator out
) const
{
@@ -875,13 +919,13 @@
template<typename OutputIterator>
OutputIterator format_escape_
(
- typename string_type::const_iterator &cur
- , typename string_type::const_iterator end
+ char_type const *&cur
+ , char_type const *end
, OutputIterator out
) const
{
using namespace regex_constants;
- typename string_type::const_iterator tmp;
+ char_type const *tmp = 0;
// define an unsigned type the same size as char_type
typedef typename boost::uint_t<CHAR_BIT * sizeof(char_type)>::least uchar_t;
BOOST_MPL_ASSERT_RELATION(sizeof(uchar_t), ==, sizeof(char_type));
@@ -1016,15 +1060,15 @@
template<typename OutputIterator>
OutputIterator format_named_backref_
(
- typename string_type::const_iterator &cur
- , typename string_type::const_iterator end
+ char_type const *&cur
+ , char_type const *end
, OutputIterator out
) const
{
using namespace regex_constants;
detail::ensure(cur != end && BOOST_XPR_CHAR_(char_type, '<') == *cur++
, error_badmark, "invalid named back-reference");
- typename string_type::const_iterator begin = cur;
+ char_type const *begin = cur;
for(; cur != end && BOOST_XPR_CHAR_(char_type, '>') != *cur; ++cur)
{}
detail::ensure(cur != begin && cur != end && BOOST_XPR_CHAR_(char_type, '>') == *cur
Modified: trunk/boost/xpressive/proto/context/callable.hpp
==============================================================================
--- trunk/boost/xpressive/proto/context/callable.hpp (original)
+++ trunk/boost/xpressive/proto/context/callable.hpp 2008-03-15 19:43:21 EDT (Sat, 15 Mar 2008)
@@ -67,7 +67,7 @@
/// tag and children as expressions, as follows:
///
/// \code
- /// context(Expr::proto_tag(), arg_c\<0\>(expr), arg_c\<1\>(expr), ...)
+ /// context(Expr::proto_tag(), arg_c<0>(expr), arg_c<1>(expr), ...)
/// \endcode
template<
typename Expr
Modified: trunk/boost/xpressive/proto/debug.hpp
==============================================================================
--- trunk/boost/xpressive/proto/debug.hpp (original)
+++ trunk/boost/xpressive/proto/debug.hpp 2008-03-15 19:43:21 EDT (Sat, 15 Mar 2008)
@@ -193,7 +193,8 @@
/// \note Equivalent to <tt>functional::display_expr(0, sout)(expr)</tt>
/// \param expr The Proto expression tree to pretty-print
/// \param sout The \c ostream to which the output should be
- /// written.
+ /// written. If not specified, defaults to
+ /// <tt>std::cout</tt>.
template<typename Expr>
void display_expr(Expr const &expr, std::ostream &sout)
{
Modified: trunk/boost/xpressive/proto/deep_copy.hpp
==============================================================================
--- trunk/boost/xpressive/proto/deep_copy.hpp (original)
+++ trunk/boost/xpressive/proto/deep_copy.hpp 2008-03-15 19:43:21 EDT (Sat, 15 Mar 2008)
@@ -14,10 +14,10 @@
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/repetition/enum.hpp>
#include <boost/preprocessor/iteration/iterate.hpp>
+ #include <boost/mpl/if.hpp>
#include <boost/type_traits/is_function.hpp>
#include <boost/xpressive/proto/proto_fwd.hpp>
#include <boost/xpressive/proto/expr.hpp>
- #include <boost/xpressive/proto/generate.hpp>
#include <boost/xpressive/proto/detail/suffix.hpp>
namespace boost { namespace proto
Modified: trunk/boost/xpressive/proto/domain.hpp
==============================================================================
--- trunk/boost/xpressive/proto/domain.hpp (original)
+++ trunk/boost/xpressive/proto/domain.hpp 2008-03-15 19:43:21 EDT (Sat, 15 Mar 2008)
@@ -12,6 +12,7 @@
#define BOOST_PROTO_DOMAIN_HPP_EAN_02_13_2007
#include <boost/xpressive/proto/detail/prefix.hpp>
+#include <boost/ref.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/xpressive/proto/proto_fwd.hpp>
#include <boost/xpressive/proto/generate.hpp>
Modified: trunk/boost/xpressive/proto/expr.hpp
==============================================================================
--- trunk/boost/xpressive/proto/expr.hpp (original)
+++ trunk/boost/xpressive/proto/expr.hpp 2008-03-15 19:43:21 EDT (Sat, 15 Mar 2008)
@@ -12,11 +12,9 @@
#include <boost/xpressive/proto/detail/prefix.hpp>
#include <boost/preprocessor/cat.hpp>
- #include <boost/preprocessor/arithmetic/inc.hpp>
#include <boost/preprocessor/arithmetic/dec.hpp>
#include <boost/preprocessor/selection/max.hpp>
#include <boost/preprocessor/iteration/iterate.hpp>
- #include <boost/preprocessor/facilities/intercept.hpp>
#include <boost/preprocessor/repetition/repeat.hpp>
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
#include <boost/preprocessor/repetition/enum_trailing.hpp>
@@ -24,7 +22,6 @@
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
#include <boost/preprocessor/repetition/enum_trailing_binary_params.hpp>
- #include <boost/utility/result_of.hpp>
#include <boost/utility/addressof.hpp>
#include <boost/xpressive/proto/proto_fwd.hpp>
#include <boost/xpressive/proto/ref.hpp>
Modified: trunk/boost/xpressive/proto/extends.hpp
==============================================================================
--- trunk/boost/xpressive/proto/extends.hpp (original)
+++ trunk/boost/xpressive/proto/extends.hpp 2008-03-15 19:43:21 EDT (Sat, 15 Mar 2008)
@@ -15,9 +15,10 @@
#include <boost/preprocessor/arithmetic/inc.hpp>
#include <boost/preprocessor/arithmetic/dec.hpp>
#include <boost/preprocessor/iteration/local.hpp>
-#include <boost/preprocessor/facilities/intercept.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
+#include <boost/preprocessor/repetition/repeat_from_to.hpp>
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
+#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
#include <boost/preprocessor/repetition/enum_trailing_binary_params.hpp>
#include <boost/mpl/apply_wrap.hpp>
#include <boost/xpressive/proto/proto_fwd.hpp>
Modified: trunk/boost/xpressive/proto/fusion.hpp
==============================================================================
--- trunk/boost/xpressive/proto/fusion.hpp (original)
+++ trunk/boost/xpressive/proto/fusion.hpp 2008-03-15 19:43:21 EDT (Sat, 15 Mar 2008)
@@ -13,6 +13,7 @@
#include <boost/config.hpp>
#include <boost/version.hpp>
#include <boost/type_traits/remove_reference.hpp>
+#include <boost/mpl/if.hpp>
#include <boost/mpl/long.hpp>
#if BOOST_VERSION >= 103500
#include <boost/fusion/include/is_view.hpp>
@@ -303,7 +304,7 @@
template<>
struct is_view_impl<proto::tag::proto_flat_view>
{
- template<typename Iterator>
+ template<typename Sequence>
struct apply
: mpl::true_
{};
@@ -312,7 +313,7 @@
template<>
struct is_view_impl<proto::tag::proto_expr>
{
- template<typename Iterator>
+ template<typename Sequence>
struct apply
: mpl::false_
{};
@@ -341,12 +342,6 @@
{
typedef Expr &type;
};
-
- template<typename Iterator, typename Expr>
- struct apply<Iterator, Expr &>
- {
- typedef Expr &type;
- };
};
#if BOOST_VERSION < 103500
Modified: trunk/boost/xpressive/proto/matches.hpp
==============================================================================
--- trunk/boost/xpressive/proto/matches.hpp (original)
+++ trunk/boost/xpressive/proto/matches.hpp 2008-03-15 19:43:21 EDT (Sat, 15 Mar 2008)
@@ -31,6 +31,7 @@
#include <boost/mpl/aux_/template_arity.hpp>
#include <boost/mpl/aux_/lambda_arity_param.hpp>
#include <boost/utility/enable_if.hpp>
+ #include <boost/type_traits/is_array.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/type_traits/is_reference.hpp>
#include <boost/type_traits/is_pointer.hpp>
Modified: trunk/boost/xpressive/proto/transform/fold_tree.hpp
==============================================================================
--- trunk/boost/xpressive/proto/transform/fold_tree.hpp (original)
+++ trunk/boost/xpressive/proto/transform/fold_tree.hpp 2008-03-15 19:43:21 EDT (Sat, 15 Mar 2008)
@@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////////
-/// \file fold.hpp
+/// \file fold_tree.hpp
/// Contains definition of the fold_tree<> and reverse_fold_tree<> transforms.
//
// Copyright 2008 Eric Niebler. Distributed under the Boost
Modified: trunk/boost/xpressive/proto/transform/make.hpp
==============================================================================
--- trunk/boost/xpressive/proto/transform/make.hpp (original)
+++ trunk/boost/xpressive/proto/transform/make.hpp 2008-03-15 19:43:21 EDT (Sat, 15 Mar 2008)
@@ -141,21 +141,6 @@
#undef TMP
};
- template<typename T, typename A, long N>
- struct construct_<proto::expr<T, A, N>, true>
- {
- typedef proto::expr<T, A, N> result_type;
-
- #define TMP(Z, N, DATA) \
- template<BOOST_PP_ENUM_PARAMS_Z(Z, N, typename A)> \
- result_type operator ()(BOOST_PP_ENUM_BINARY_PARAMS_Z(Z, N, A, &a)) const \
- { \
- return result_type::make(BOOST_PP_ENUM_PARAMS_Z(Z, N, a)); \
- }
- BOOST_PP_REPEAT_FROM_TO(1, BOOST_PP_INC(BOOST_PROTO_MAX_ARITY), TMP, ~)
- #undef TMP
- };
-
#define TMP(Z, N, DATA) \
template<typename Type BOOST_PP_ENUM_TRAILING_PARAMS_Z(Z, N, typename A)> \
Type construct(BOOST_PP_ENUM_BINARY_PARAMS_Z(Z, N, A, &a)) \
Modified: trunk/boost/xpressive/proto/transform/pass_through.hpp
==============================================================================
--- trunk/boost/xpressive/proto/transform/pass_through.hpp (original)
+++ trunk/boost/xpressive/proto/transform/pass_through.hpp 2008-03-15 19:43:21 EDT (Sat, 15 Mar 2008)
@@ -71,13 +71,13 @@
/// of an expression node according to the corresponding children of
/// a Grammar.
///
- /// Given a Grammar such as <tt>posit\<T0, T1\></tt>, an expression type
- /// that matches the grammar such as <tt>posit\<E0, E1\>::::type</tt>, a
+ /// Given a Grammar such as <tt>plus\<T0, T1\></tt>, an expression type
+ /// that matches the grammar such as <tt>plus\<E0, E1\>::::type</tt>, a
/// state \c S and a visitor \c V, the result of applying the
- /// <tt>pass_through\<posit\<T0, T1\> \></tt> transform is:
+ /// <tt>pass_through\<plus\<T0, T1\> \></tt> transform is:
///
/// \code
- /// posit<
+ /// plus<
/// T0::result<void(E0, S, V)>::type
/// , T1::result<void(E1, S, V)>::type
/// >::type
@@ -89,16 +89,16 @@
///
/// The explicit use of <tt>pass_through\<\></tt> is not usually needed,
/// since the expression generator metafunctions such as
- /// <tt>posit\<\></tt> have <tt>pass_through\<\></tt> as their default
+ /// <tt>plus\<\></tt> have <tt>pass_through\<\></tt> as their default
/// transform. So, for instance, these are equivalent:
///
/// \code
/// // Within a grammar definition, these are equivalent:
- /// when< posit<X, Y>, pass_through< posit<X, Y> > >
- /// when< posit<X, Y>, posit<X, Y> >
- /// when< posit<X, Y> > // because of when<class X, class Y=X>
- /// posit<X, Y> // because posit<> is both a
- /// // grammar and a transform
+ /// when< plus<X, Y>, pass_through< plus<X, Y> > >
+ /// when< plus<X, Y>, plus<X, Y> >
+ /// when< plus<X, Y> > // because of when<class X, class Y=X>
+ /// plus<X, Y> // because plus<> is both a
+ /// // grammar and a transform
/// \endcode
///
/// For example, consider the following transform that promotes all
Modified: trunk/boost/xpressive/regex_algorithms.hpp
==============================================================================
--- trunk/boost/xpressive/regex_algorithms.hpp (original)
+++ trunk/boost/xpressive/regex_algorithms.hpp 2008-03-15 19:43:21 EDT (Sat, 15 Mar 2008)
@@ -15,10 +15,12 @@
#endif
#include <iterator>
+#include <boost/mpl/or.hpp>
#include <boost/range/end.hpp>
#include <boost/range/begin.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/utility/enable_if.hpp>
+#include <boost/type_traits/add_const.hpp>
#include <boost/type_traits/is_pointer.hpp>
#include <boost/type_traits/remove_const.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
@@ -486,39 +488,18 @@
// regex_replace
///////////////////////////////////////////////////////////////////////////////
-
-/// \brief Build an output sequence given an input sequence, a regex, and a format string.
-///
-/// Constructs a regex_iterator object: regex_iterator\< BidiIter \> i(begin, end, re, flags),
-/// and uses i to enumerate through all of the matches m of type match_results\< BidiIter \> that
-/// occur within the sequence [begin, end). If no such matches are found and !(flags \& format_no_copy)
-/// then calls std::copy(begin, end, out). Otherwise, for each match found, if !(flags \& format_no_copy)
-/// calls std::copy(m.prefix().first, m.prefix().second, out), and then calls m.format(out, fmt, flags).
-/// Finally if !(flags \& format_no_copy) calls std::copy(last_m.suffix().first, last_m.suffix().second, out)
-/// where last_m is a copy of the last match found. If flags \& format_first_only is non-zero then only
-/// the first match found is replaced.
-///
-/// \pre Types BidiIter and OtherBidiIter meet the requirements of a Bidirectional Iterator (24.1.4).
-/// \pre Type OutIter meets the requirements of an Output Iterator (24.1.2).
-/// \pre OtherBidiIter is convertible to BidiIter.
-/// \pre [begin,end) denotes a valid iterator range.
-///
-/// \param out An output iterator into which the output sequence is written.
-/// \param begin The beginning of the input sequence.
-/// \param end The end of the input sequence.
-/// \param re The regular expression object to use.
-/// \param fmt The format string used to format the replacement sequence.
-/// \param flags Optional match flags, used to control how the expression is matched against the sequence. (See match_flag_type.)
-/// \return The value of the output iterator after the output sequence has been written to it.
-/// \throw regex_error on stack exhaustion or invalid format string.
-template<typename OutIter, typename OtherBidiIter, typename BidiIter>
-inline OutIter regex_replace
+namespace detail
+{
+///////////////////////////////////////////////////////////////////////////////
+// regex_replace_impl
+template<typename OutIter, typename BidiIter, typename ForwardRangeOrNTBS>
+inline OutIter regex_replace_impl
(
OutIter out
- , OtherBidiIter begin
- , OtherBidiIter end
+ , BidiIter begin
+ , BidiIter end
, basic_regex<BidiIter> const &re
- , std::basic_string<typename iterator_value<BidiIter>::type> const &fmt
+ , ForwardRangeOrNTBS const &format
, regex_constants::match_flag_type flags = regex_constants::match_default
)
{
@@ -537,7 +518,7 @@
out = std::copy(cur, what[0].first, out);
}
- out = what.format(out, fmt, flags);
+ out = what.format(out, format, flags);
cur = state.cur_ = state.next_search_ = what[0].second;
if(0 == (flags & format_first_only))
@@ -552,7 +533,7 @@
}
access::set_prefix_suffix(what, begin, end);
- out = what.format(out, fmt, flags);
+ out = what.format(out, format, flags);
cur = state.cur_ = state.next_search_ = what[0].second;
not_null = (0 == what.length());
state.reset(what, *access::get_regex_impl(re));
@@ -562,26 +543,185 @@
if(yes_copy)
{
- out = std::copy(cur, static_cast<BidiIter>(end), out);
+ out = std::copy(cur, end, out);
}
return out;
}
+} // namespace detail
+
+/// \brief Build an output sequence given an input sequence, a regex, and a format string.
+///
+/// Constructs a regex_iterator object: regex_iterator\< BidiIter \> i(begin, end, re, flags),
+/// and uses i to enumerate through all of the matches m of type match_results\< BidiIter \> that
+/// occur within the sequence [begin, end). If no such matches are found and !(flags \& format_no_copy)
+/// then calls std::copy(begin, end, out). Otherwise, for each match found, if !(flags \& format_no_copy)
+/// calls std::copy(m.prefix().first, m.prefix().second, out), and then calls m.format(out, format, flags).
+/// Finally if !(flags \& format_no_copy) calls std::copy(last_m.suffix().first, last_m.suffix().second, out)
+/// where last_m is a copy of the last match found. If flags \& format_first_only is non-zero then only
+/// the first match found is replaced.
+///
+/// \pre Types BidiIter and OtherBidiIter meet the requirements of a Bidirectional Iterator (24.1.4).
+/// \pre Type OutIter meets the requirements of an Output Iterator (24.1.2).
+/// \pre OtherBidiIter is convertible to BidiIter.
+/// \pre [begin,end) denotes a valid iterator range.
+///
+/// \param out An output iterator into which the output sequence is written.
+/// \param begin The beginning of the input sequence.
+/// \param end The end of the input sequence.
+/// \param re The regular expression object to use.
+/// \param format The format string used to format the replacement sequence.
+/// \param flags Optional match flags, used to control how the expression is matched against the sequence. (See match_flag_type.)
+/// \return The value of the output iterator after the output sequence has been written to it.
+/// \throw regex_error on stack exhaustion or invalid format string.
+template<typename OutIter, typename OtherBidiIter, typename BidiIter, typename ForwardRange>
+inline OutIter regex_replace
+(
+ OutIter out
+ , OtherBidiIter begin
+ , OtherBidiIter end
+ , basic_regex<BidiIter> const &re
+ , ForwardRange const &format
+ , regex_constants::match_flag_type flags = regex_constants::match_default
+ , typename disable_if<is_pointer<ForwardRange> >::type * = 0
+)
+{
+ BidiIter begin_ = begin, end_ = end;
+ return detail::regex_replace_impl(out, begin_, end_, re, format, flags);
+}
+
+/// \overload
+///
+template<typename OutIter, typename OtherBidiIter, typename BidiIter>
+inline OutIter regex_replace
+(
+ OutIter out
+ , OtherBidiIter begin
+ , OtherBidiIter end
+ , basic_regex<BidiIter> const &re
+ , typename iterator_value<BidiIter>::type const *format
+ , regex_constants::match_flag_type flags = regex_constants::match_default
+)
+{
+ BidiIter begin_ = begin, end_ = end;
+ return detail::regex_replace_impl(out, begin_, end_, re, format, flags);
+}
+
+/// \overload
+///
+template<typename BidiContainer, typename BidiIter, typename ForwardRange>
+inline BidiContainer regex_replace
+(
+ BidiContainer &str
+ , basic_regex<BidiIter> const &re
+ , ForwardRange const &format
+ , regex_constants::match_flag_type flags = regex_constants::match_default
+ , typename disable_if<mpl::or_<is_pointer<BidiContainer>, is_pointer<ForwardRange> > >::type * = 0
+)
+{
+ BidiContainer result;
+ // Note that the result iterator of the range must be convertible
+ // to BidiIter here.
+ BidiIter begin = boost::begin(str), end = boost::end(str);
+ regex_replace(std::back_inserter(result), begin, end, re, format, flags);
+ return result;
+}
+
+/// \overload
+///
+template<typename BidiContainer, typename BidiIter, typename ForwardRange>
+inline BidiContainer regex_replace
+(
+ BidiContainer const &str
+ , basic_regex<BidiIter> const &re
+ , ForwardRange const &format
+ , regex_constants::match_flag_type flags = regex_constants::match_default
+ , typename disable_if<mpl::or_<is_pointer<BidiContainer>, is_pointer<ForwardRange> > >::type * = 0
+)
+{
+ BidiContainer result;
+ // Note that the result iterator of the range must be convertible
+ // to BidiIter here.
+ BidiIter begin = boost::begin(str), end = boost::end(str);
+ regex_replace(std::back_inserter(result), begin, end, re, format, flags);
+ return result;
+}
+
+/// \overload
+///
+template<typename Char, typename ForwardRange>
+inline std::basic_string<typename remove_const<Char>::type> regex_replace
+(
+ BOOST_XPR_NONDEDUCED_TYPE_(Char) *str
+ , basic_regex<Char *> const &re
+ , ForwardRange const &format
+ , regex_constants::match_flag_type flags = regex_constants::match_default
+ , typename disable_if<is_pointer<ForwardRange> >::type * = 0
+)
+{
+ typedef typename remove_const<Char>::type char_type;
+ std::basic_string<char_type> result;
+ result.reserve(boost::size(format) * 2);
+ Char *end = str + std::char_traits<char_type>::length(str);
+ regex_replace(std::back_inserter(result), str, end, re, format, flags);
+ return result;
+}
+
+/// \overload
+///
+template<typename BidiContainer, typename BidiIter>
+inline BidiContainer regex_replace
+(
+ BidiContainer &str
+ , basic_regex<BidiIter> const &re
+ , typename iterator_value<BidiIter>::type const *format
+ , regex_constants::match_flag_type flags = regex_constants::match_default
+ , typename disable_if<is_pointer<BidiContainer> >::type * = 0
+)
+{
+ BidiContainer result;
+ // Note that the result iterator of the range must be convertible
+ // to BidiIter here.
+ BidiIter begin = boost::begin(str), end = boost::end(str);
+ regex_replace(std::back_inserter(result), begin, end, re, format, flags);
+ return result;
+}
+
+/// \overload
+///
+template<typename BidiContainer, typename BidiIter>
+inline BidiContainer regex_replace
+(
+ BidiContainer const &str
+ , basic_regex<BidiIter> const &re
+ , typename iterator_value<BidiIter>::type const *format
+ , regex_constants::match_flag_type flags = regex_constants::match_default
+ , typename disable_if<is_pointer<BidiContainer> >::type * = 0
+)
+{
+ BidiContainer result;
+ // Note that the result iterator of the range must be convertible
+ // to BidiIter here.
+ BidiIter begin = boost::begin(str), end = boost::end(str);
+ regex_replace(std::back_inserter(result), begin, end, re, format, flags);
+ return result;
+}
/// \overload
///
template<typename Char>
-inline std::basic_string<Char> regex_replace
+inline std::basic_string<typename remove_const<Char>::type> regex_replace
(
- std::basic_string<Char> const &str
- , basic_regex<typename std::basic_string<Char>::const_iterator> const &re
- , std::basic_string<BOOST_XPR_NONDEDUCED_TYPE_(Char)> const &fmt
+ BOOST_XPR_NONDEDUCED_TYPE_(Char) *str
+ , basic_regex<Char *> const &re
+ , typename add_const<Char>::type *format
, regex_constants::match_flag_type flags = regex_constants::match_default
)
{
- std::basic_string<Char> result;
- result.reserve(fmt.length() * 2);
- regex_replace(std::back_inserter(result), str.begin(), str.end(), re, fmt, flags);
+ typedef typename remove_const<Char>::type char_type;
+ std::basic_string<char_type> result;
+ Char *end = str + std::char_traits<char_type>::length(str);
+ regex_replace(std::back_inserter(result), str, end, re, format, flags);
return result;
}
Modified: trunk/libs/xpressive/proto/doc/construction.qbk
==============================================================================
--- trunk/libs/xpressive/proto/doc/construction.qbk (original)
+++ trunk/libs/xpressive/proto/doc/construction.qbk 2008-03-15 19:43:21 EDT (Sat, 15 Mar 2008)
@@ -922,10 +922,10 @@
>::type
In the above, `TheFunctionToCall` might be an ordinary function object, so
-let's define a `construct_<>` function object that constructs an object.
+let's define a `construct_helper<>` function object that constructs an object.
template<typename T>
- struct construct_
+ struct construct_helper
{
typedef T result_type; // for TR1 result_of
@@ -937,13 +937,13 @@
// ... other overloads ...
};
-With such a function object, we can say `construct_<S>()(1, 'a')` to
+With such a function object, we can say `construct_helper<S>()(1, 'a')` to
immediately construct an `S` object using `1` and `'a'` as constructor
-arguments. We want this to be lazy, so we can wrap `construct_<S>` in
+arguments. We want this to be lazy, so we can wrap `construct_helper<S>` in
a Proto terminal.
// A lazy S constructor
- terminal<construct_<S> >::type const construct_S = {{}};
+ terminal<construct_helper<S> >::type const construct_S = {{}};
// OK, make a lazy function invocation but don't call it.
construct_S(1, 'a');
@@ -961,14 +961,14 @@
template<typename T, typename A0, typename A1>
typename proto::result_of::make_expr<
proto::tag::function
- , construct_<T> const
+ , construct_helper<T> const
, A0 const &
, A1 const &
>::type const
construct(A0 const &a0, A1 const &a1)
{
return proto::make_expr<proto::tag::function>(
- construct_<T>()
+ construct_helper<T>()
, boost::ref(a0)
, boost::ref(a1)
);
@@ -988,12 +988,12 @@
construct \
, MyLambdaDomain \
, (proto::tag::function) \
- , ((construct_)(typename)) \
+ , ((construct_helper)(typename)) \
)
What is new in this case is the fourth macro argument, which specifies
that there is an implicit first argument to `construct()` of type
-`construct_<X>`, where `X` is a template parameter of the function.
+`construct_helper<X>`, where `X` is a template parameter of the function.
The fourth argument to the macro is actually a PP sequence of PP
sequences. Each sequence describes one implicit argument.
Modified: trunk/libs/xpressive/proto/doc/transforms.qbk
==============================================================================
--- trunk/libs/xpressive/proto/doc/transforms.qbk (original)
+++ trunk/libs/xpressive/proto/doc/transforms.qbk 2008-03-15 19:43:21 EDT (Sat, 15 Mar 2008)
@@ -900,7 +900,7 @@
`when<>` associates a grammar rule with a transform. It can be used
in a grammar in place of the rule; that is, it behaves as a grammar
rule. Expression tree nodes that match the grammar rule are processed
-with the associated transform; that it, `when<>` also behaves like
+with the associated transform; that is, `when<>` also behaves like
a transform.
When no transform is specified, as with `when< posit<Calculator> >`,
Modified: trunk/libs/xpressive/proto/example/calc1.cpp
==============================================================================
--- trunk/libs/xpressive/proto/example/calc1.cpp (original)
+++ trunk/libs/xpressive/proto/example/calc1.cpp 2008-03-15 19:43:21 EDT (Sat, 15 Mar 2008)
@@ -12,11 +12,11 @@
#include <boost/xpressive/proto/context.hpp>
using namespace boost;
-template<typename I> struct arg {};
+template<int I> struct placeholder {};
// Define some placeholders
-proto::terminal< arg< mpl::int_<1> > >::type const _1 = {{}};
-proto::terminal< arg< mpl::int_<2> > >::type const _2 = {{}};
+proto::terminal< placeholder< 1 > >::type const _1 = {{}};
+proto::terminal< placeholder< 2 > >::type const _2 = {{}};
// Define a calculator context, for evaluating arithmetic expressions
struct calculator_context
@@ -35,10 +35,10 @@
}
// Handle the evaluation of the placeholder terminals
- template<typename I>
- double operator ()(proto::tag::terminal, arg<I>) const
+ template<int I>
+ double operator ()(proto::tag::terminal, placeholder<I>) const
{
- return d[ I() - 1 ];
+ return d[ I - 1 ];
}
};
Modified: trunk/libs/xpressive/proto/example/calc2.cpp
==============================================================================
--- trunk/libs/xpressive/proto/example/calc2.cpp (original)
+++ trunk/libs/xpressive/proto/example/calc2.cpp 2008-03-15 19:43:21 EDT (Sat, 15 Mar 2008)
@@ -15,7 +15,7 @@
using namespace boost;
// Will be used to define the placeholders _1 and _2
-template<typename I> struct arg {};
+template<int I> struct placeholder {};
// For expressions in the calculator domain, operator ()
// will be special; it will evaluate the expression.
@@ -39,10 +39,10 @@
}
// Handle the evaluation of the placeholder terminals
- template<typename I>
- double operator ()(proto::tag::terminal, arg<I>) const
+ template<int I>
+ double operator ()(proto::tag::terminal, placeholder<I>) const
{
- return d[ I() - 1 ];
+ return d[ I - 1 ];
}
};
@@ -88,8 +88,8 @@
{};
// Define some placeholders (notice they're wrapped in calculator_expression<>)
-calculator_expression<proto::terminal< arg< mpl::int_<1> > >::type> const _1;
-calculator_expression<proto::terminal< arg< mpl::int_<2> > >::type> const _2;
+calculator_expression<proto::terminal< placeholder< 1 > >::type> const _1;
+calculator_expression<proto::terminal< placeholder< 2 > >::type> const _2;
// Now, our arithmetic expressions are immediately executable function objects:
int main()
Modified: trunk/libs/xpressive/proto/example/lambda.cpp
==============================================================================
--- trunk/libs/xpressive/proto/example/lambda.cpp (original)
+++ trunk/libs/xpressive/proto/example/lambda.cpp 2008-03-15 19:43:21 EDT (Sat, 15 Mar 2008)
@@ -158,14 +158,14 @@
struct construct_helper
{
typedef T result_type; // for TR1 result_of
-
+
T operator()() const
{ return T(); }
-
+
template<typename A0>
T operator()(A0 const &a0) const
{ return T(a0); }
-
+
template<typename A0, typename A1>
T operator()(A0 const &a0, A1 const &a1) const
{ return T(a0, a1); }
@@ -194,11 +194,11 @@
// Create some lambda objects and immediately
// invoke them by applying their operator():
int i = ( (_1 + 2) / 4 )(42);
- std::cout << i << std::endl; // prints -11
-
+ std::cout << i << std::endl; // prints 11
+
int j = ( (-(_1 + 2)) / 4 )(42);
std::cout << j << std::endl; // prints -11
-
+
double d = ( (4 - _2) * 3 )(42, 3.14);
std::cout << d << std::endl; // prints 2.58
@@ -209,7 +209,7 @@
// "Nullary" lambdas work too
int k = (val(1) + val(2))();
std::cout << k << std::endl; // prints 3
-
+
// check array indexing for kicks
int integers[5] = {0};
(var(integers)[2] = 2)();
Modified: trunk/libs/xpressive/proto/example/mixed.cpp
==============================================================================
--- trunk/libs/xpressive/proto/example/mixed.cpp (original)
+++ trunk/libs/xpressive/proto/example/mixed.cpp 2008-03-15 19:43:21 EDT (Sat, 15 Mar 2008)
@@ -76,14 +76,14 @@
// terminals.
struct DereferenceCtx
{
- // Unless this is a vector terminal, use the
+ // Unless this is an iterator terminal, use the
// default evaluation context
template<typename Expr, typename Arg = typename proto::result_of::arg<Expr>::type>
struct eval
: proto::default_eval<Expr, DereferenceCtx const>
{};
- // Index vector terminals with our subscript.
+ // Dereference iterator terminals.
template<typename Expr, typename Iter>
struct eval<Expr, iterator_wrapper<Iter> >
{
@@ -100,14 +100,14 @@
// terminals.
struct IncrementCtx
{
- // Unless this is a vector terminal, use the
+ // Unless this is an iterator terminal, use the
// default evaluation context
template<typename Expr, typename Arg = typename proto::result_of::arg<Expr>::type>
struct eval
: proto::null_eval<Expr, IncrementCtx const>
{};
- // Index vector terminals with our subscript.
+ // advance iterator terminals.
template<typename Expr, typename Iter>
struct eval<Expr, iterator_wrapper<Iter> >
{
@@ -191,7 +191,7 @@
: mpl::true_
{};
-namespace VectorOps
+namespace MixedOps
{
// This defines all the overloads to make expressions involving
// std::vector to build expression templates.
@@ -317,7 +317,7 @@
int main()
{
- using namespace VectorOps;
+ using namespace MixedOps;
int n = 10;
std::vector<int> a,b,c,d;
@@ -335,11 +335,11 @@
f.push_back(std::complex<double>(1.0, 1.0));
}
- VectorOps::assign(b, 2);
- VectorOps::assign(d, a + b * c);
+ MixedOps::assign(b, 2);
+ MixedOps::assign(d, a + b * c);
a += if_else(d < 30, b, c);
- VectorOps::assign(e, c);
+ MixedOps::assign(e, c);
e += e - 4 / (c + 1);
f -= sin(0.1 * e * std::complex<double>(0.2, 1.2));
Modified: trunk/libs/xpressive/proto/test/examples.cpp
==============================================================================
--- trunk/libs/xpressive/proto/test/examples.cpp (original)
+++ trunk/libs/xpressive/proto/test/examples.cpp 2008-03-15 19:43:21 EDT (Sat, 15 Mar 2008)
@@ -269,7 +269,7 @@
function<terminal<make_pair_tag>, terminal<_>, terminal<_> >
/*<< Return `std::pair<F,S>(f,s)` where `f` and `s` are the
first and second arguments to the lazy `make_pair_()` function.
- (This uses `proto:::make<>` under the covers to evaluate the
+ (This uses `proto::make<>` under the covers to evaluate the
transform.)>>*/
, std::pair<_arg(_arg1), _arg(_arg2)>(_arg(_arg1), _arg(_arg2))
>
@@ -313,7 +313,7 @@
function<terminal<make_pair_tag>, terminal<_>, terminal<_> >
/*<< Return `make_pair()(f,s)` where `f` and `s` are the
first and second arguments to the lazy `make_pair_()` function.
- (This uses `proto:::call<>` under the covers to evaluate the
+ (This uses `proto::call<>` under the covers to evaluate the
transform.)>>*/
, make_pair(_arg(_arg1), _arg(_arg2))
>
Modified: trunk/libs/xpressive/test/regress.ipp
==============================================================================
--- trunk/libs/xpressive/test/regress.ipp (original)
+++ trunk/libs/xpressive/test/regress.ipp 2008-03-15 19:43:21 EDT (Sat, 15 Mar 2008)
@@ -272,11 +272,26 @@
typedef typename std::basic_string<Char>::const_iterator iterator;
basic_regex<iterator> rx = basic_regex<iterator>::compile(test.pat, test.syntax_flags);
+ // Build the same regex for use with C strings
+ basic_regex<Char const *> c_rx = basic_regex<Char const *>::compile(test.pat, test.syntax_flags);
+
if(!test.res.empty())
{
// test regex_replace
std::basic_string<Char> res = regex_replace(test.str, rx, test.sub, test.match_flags);
BOOST_CHECK_MESSAGE(res == test.res, case_ << res << " != " << test.res );
+
+ // test regex_replace with NTBS format string
+ std::basic_string<Char> res2 = regex_replace(test.str, rx, test.sub.c_str(), test.match_flags);
+ BOOST_CHECK_MESSAGE(res2 == test.res, case_ << res2 << " != " << test.res );
+
+ // test regex_replace with NTBS input string
+ std::basic_string<Char> res3 = regex_replace(test.str.c_str(), c_rx, test.sub, test.match_flags);
+ BOOST_CHECK_MESSAGE(res3 == test.res, case_ << res3 << " != " << test.res );
+
+ // test regex_replace with NTBS input string and NTBS format string
+ std::basic_string<Char> res4 = regex_replace(test.str.c_str(), c_rx, test.sub.c_str(), test.match_flags);
+ BOOST_CHECK_MESSAGE(res4 == test.res, case_ << res4 << " != " << test.res );
}
if(0 == (test.match_flags & regex_constants::format_first_only))
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk