Boost logo

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