Boost logo

Boost-Commit :

From: eric_at_[hidden]
Date: 2008-03-16 02:49:14


Author: eric_niebler
Date: 2008-03-16 02:49:13 EDT (Sun, 16 Mar 2008)
New Revision: 43647
URL: http://svn.boost.org/trac/boost/changeset/43647

Log:
regex_replace supports formatter functions and function objects
Added:
   trunk/libs/xpressive/test/test_format.cpp (contents, props changed)
Text files modified:
   trunk/boost/xpressive/match_results.hpp | 264 +++++++++++++++++++++++++++++++++------
   trunk/boost/xpressive/regex_algorithms.hpp | 17 +-
   trunk/libs/xpressive/test/Jamfile.v2 | 1
   3 files changed, 235 insertions(+), 47 deletions(-)

Modified: trunk/boost/xpressive/match_results.hpp
==============================================================================
--- trunk/boost/xpressive/match_results.hpp (original)
+++ trunk/boost/xpressive/match_results.hpp 2008-03-16 02:49:13 EDT (Sun, 16 Mar 2008)
@@ -21,6 +21,7 @@
 #endif
 
 #include <map>
+#include <string>
 #include <vector>
 #include <utility>
 #include <iterator>
@@ -29,11 +30,19 @@
 #include <boost/config.hpp>
 #include <boost/assert.hpp>
 #include <boost/integer.hpp>
+#include <boost/mpl/not.hpp>
+#include <boost/mpl/size_t.hpp>
 #include <boost/mpl/assert.hpp>
 #include <boost/intrusive_ptr.hpp>
 #include <boost/throw_exception.hpp>
 #include <boost/iterator_adaptors.hpp>
+#include <boost/utility/enable_if.hpp>
 #include <boost/numeric/conversion/converter.hpp>
+#include <boost/range/end.hpp>
+#include <boost/range/begin.hpp>
+#include <boost/range/as_literal.hpp>
+#include <boost/range/const_iterator.hpp>
+#include <boost/type_traits/is_function.hpp>
 #if BOOST_ITERATOR_ADAPTORS_VERSION >= 0x0200
 # include <boost/iterator/filter_iterator.hpp>
 #endif
@@ -212,6 +221,96 @@
     }
 };
 
+struct any_type { any_type(...); };
+typedef char no_type;
+typedef char (&unary_type)[2];
+typedef char (&binary_type)[3];
+typedef char (&ternary_type)[4];
+
+no_type check_is_formatter(unary_type, binary_type, ternary_type);
+
+template<typename T>
+unary_type check_is_formatter(T const &, binary_type, ternary_type);
+
+template<typename T>
+binary_type check_is_formatter(unary_type, T const &, ternary_type);
+
+template<typename T, typename U>
+binary_type check_is_formatter(T const &, U const &, ternary_type);
+
+template<typename T>
+ternary_type check_is_formatter(unary_type, binary_type, T const &);
+
+template<typename T, typename U>
+ternary_type check_is_formatter(T const &, binary_type, U const &);
+
+template<typename T, typename U>
+ternary_type check_is_formatter(unary_type, T const &, U const &);
+
+template<typename T, typename U, typename V>
+ternary_type check_is_formatter(T const &, U const &, V const &);
+
+struct unary_binary_ternary
+{
+ typedef unary_type (*unary_fun)(any_type);
+ typedef binary_type (*binary_fun)(any_type, any_type);
+ typedef ternary_type (*ternary_fun)(any_type, any_type, any_type);
+ operator unary_fun();
+ operator binary_fun();
+ operator ternary_fun();
+};
+
+template<typename Formatter, bool IsFunction = is_function<Formatter>::value>
+struct formatter_wrapper
+ : Formatter
+ , unary_binary_ternary
+{
+ formatter_wrapper();
+};
+
+template<typename Formatter>
+struct formatter_wrapper<Formatter, true>
+ : unary_binary_ternary
+{
+ operator Formatter *();
+};
+
+template<typename Formatter>
+struct formatter_wrapper<Formatter *, false>
+ : unary_binary_ternary
+{
+ operator Formatter *();
+};
+
+template<typename Formatter, typename What, typename Out>
+struct formatter_arity
+{
+ static formatter_wrapper<Formatter> &formatter;
+ static What &what;
+ static Out &out;
+ BOOST_STATIC_CONSTANT(
+ std::size_t
+ , value = sizeof(
+ check_is_formatter(
+ formatter(what)
+ , formatter(what, out)
+ , formatter(what, out, regex_constants::format_default)
+ )
+ ) - 1
+ );
+ typedef mpl::size_t<value> type;
+};
+
+template<typename T>
+struct is_char_ptr
+ : mpl::false_
+{};
+
+template<typename T>
+struct is_char_ptr<T *>
+ : mpl::not_<is_function<T> >
+{};
+
 } // detail
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -432,21 +531,41 @@
         return this->nested_results_;
     }
 
- /// Copies the character sequence [fmt.begin(), fmt.end()) to OutputIterator out. For each format
- /// specifier or escape sequence in fmt, replace that sequence with either the character(s) it
- /// represents, or the sequence within *this to which it refers. The bitmasks specified in flags
- /// determines what format specifiers or escape sequences are recognized, by default this is the
+ /// If \c Format models \c ForwardRange or is a null-terminated string, this function
+ /// copies the character sequence in \c fmt to \c OutputIterator \c out. For each format
+ /// specifier or escape sequence in \c fmt, replace that sequence with either the character(s) it
+ /// represents, or the sequence within <tt>*this</tt> 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.
- template<typename OutputIterator>
+ ///
+ /// Otherwise, if \c Format models <tt>Callable\<match_results\<BidiIter\>, OutputIterator, regex_constants::match_flag_type\></tt>,
+ /// this function returns <tt>fmt(*this, out, flags)</tt>.
+ ///
+ /// Otherwise, if \c Format models <tt>Callable\<match_results\<BidiIter\>, OutputIterator\></tt>, this function
+ /// returns <tt>fmt(*this, out)</tt>.
+ ///
+ /// Otherwise, if \c Format models <tt>Callable\<match_results\<BidiIter\> \></tt>, this function
+ /// returns <tt>std::copy(x.begin(), x.end(), out)</tt>, where \c x is the result of
+ /// calling <tt>fmt(*this)</tt>.
+ template<typename Format, typename OutputIterator>
     OutputIterator format
     (
         OutputIterator out
- , string_type const &fmt
+ , Format const &fmt
       , regex_constants::match_flag_type flags = regex_constants::format_default
+ , typename disable_if<detail::is_char_ptr<Format> >::type * = 0
     ) const
     {
- char_type const *cur = &*fmt.begin(), *end = &*fmt.begin() + fmt.size();
- return this->format_(out, cur, end, flags);
+ // Is this a formatter object, or a format string?
+ typedef
+ typename detail::formatter_arity<
+ Format
+ , match_results<BidiIter>
+ , OutputIterator
+ >::type
+ arity;
+
+ return this->format_(out, fmt, flags, arity());
     }
 
     /// \overload
@@ -459,23 +578,35 @@
       , 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);
+ return this->format_(out, boost::as_literal(fmt), flags, mpl::size_t<0>());
     }
 
- /// Returns a copy of the string fmt. For each format specifier or escape sequence in fmt,
+ /// If \c Format models \c ForwardRange or is a null-terminated string, this function
+ /// returns a copy of the character sequence \c fmt. For each format specifier or escape sequence in \c fmt,
     /// replace that sequence with either the character(s) it represents, or the sequence within
- /// *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,
+ /// <tt>*this</tt> to which it refers. The bitmasks specified in \c 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.
+ ///
+ /// Otherwise, if \c Format models <tt>Callable\<match_results\<BidiIter\>, OutputIterator, regex_constants::match_flag_type\></tt>,
+ /// this function returns a \c string_type object \c x populated by calling <tt>fmt(*this, out, flags)</tt>,
+ /// where \c out is a \c back_insert_iterator into \c x.
+ ///
+ /// Otherwise, if \c Format models <tt>Callable\<match_results\<BidiIter\>, OutputIterator\></tt>, this function
+ /// returns a \c string_type object \c x populated by calling <tt>fmt(*this, out)</tt>,
+ /// where \c out is a \c back_insert_iterator into \c x.
+ ///
+ /// Otherwise, if \c Format models <tt>Callable\<match_results\<BidiIter\> \></tt>, this function
+ /// returns <tt>fmt(*this)</tt>.
+ template<typename Format, typename OutputIterator>
     string_type format
     (
- string_type const &fmt
+ Format const &fmt
       , regex_constants::match_flag_type flags = regex_constants::format_default
+ , typename disable_if<detail::is_char_ptr<Format> >::type * = 0
     ) const
     {
         string_type result;
- result.reserve(fmt.length() * 2);
         this->format(std::back_inserter(result), fmt, flags);
         return result;
     }
@@ -668,15 +799,26 @@
 
     /// INTERNAL ONLY
     ///
- template<typename OutputIterator>
+ template<typename OutputIterator, typename ForwardRange>
+ OutputIterator format2_(OutputIterator out, ForwardRange const &result) const
+ {
+ return std::copy(boost::begin(result), boost::end(result), out);
+ }
+
+ /// INTERNAL ONLY
+ ///
+ template<typename OutputIterator, typename ForwardRange>
     OutputIterator format_
     (
         OutputIterator out
- , char_type const *cur
- , char_type const *end
- , regex_constants::match_flag_type flags = regex_constants::format_default
+ , ForwardRange const &format
+ , regex_constants::match_flag_type flags
+ , mpl::size_t<0>
     ) const
     {
+ typedef typename range_const_iterator<ForwardRange>::type iterator;
+ iterator cur = boost::begin(format), end = boost::end(format);
+
         if(0 != (regex_constants::format_literal & flags))
         {
             return std::copy(cur, end, out);
@@ -699,8 +841,50 @@
 
     /// INTERNAL ONLY
     ///
- template<typename OutputIterator>
- OutputIterator format_ecma_262_(char_type const *cur, char_type const *end, OutputIterator out) const
+ template<typename OutputIterator, typename ForwardRange>
+ OutputIterator format_
+ (
+ OutputIterator out
+ , ForwardRange const &format
+ , regex_constants::match_flag_type
+ , mpl::size_t<1>
+ ) const
+ {
+ return this->format2_(out, format(*this));
+ }
+
+ /// INTERNAL ONLY
+ ///
+ template<typename OutputIterator, typename ForwardRange>
+ OutputIterator format_
+ (
+ OutputIterator out
+ , ForwardRange const &format
+ , regex_constants::match_flag_type
+ , mpl::size_t<2>
+ ) const
+ {
+ return format(*this, out);
+ }
+
+ /// INTERNAL ONLY
+ ///
+ template<typename OutputIterator, typename ForwardRange>
+ OutputIterator format_
+ (
+ OutputIterator out
+ , ForwardRange const &format
+ , regex_constants::match_flag_type flags
+ , mpl::size_t<3>
+ ) const
+ {
+ return format(*this, out, flags);
+ }
+
+ /// INTERNAL ONLY
+ ///
+ template<typename ForwardIterator, typename OutputIterator>
+ OutputIterator format_ecma_262_(ForwardIterator cur, ForwardIterator end, OutputIterator out) const
     {
         while(cur != end)
         {
@@ -721,8 +905,8 @@
 
     /// INTERNAL ONLY
     ///
- template<typename OutputIterator>
- OutputIterator format_sed_(char_type const *cur, char_type const *end, OutputIterator out) const
+ template<typename ForwardIterator, typename OutputIterator>
+ OutputIterator format_sed_(ForwardIterator cur, ForwardIterator end, OutputIterator out) const
     {
         while(cur != end)
         {
@@ -748,8 +932,8 @@
 
     /// INTERNAL ONLY
     ///
- template<typename OutputIterator>
- OutputIterator format_perl_(char_type const *cur, char_type const *end, OutputIterator out) const
+ template<typename ForwardIterator, typename OutputIterator>
+ OutputIterator format_perl_(ForwardIterator cur, ForwardIterator end, OutputIterator out) const
     {
         detail::case_converting_iterator<OutputIterator, char_type> iout(out, this->traits_.get());
 
@@ -783,8 +967,8 @@
 
     /// INTERNAL ONLY
     ///
- template<typename OutputIterator>
- OutputIterator format_all_(char_type const *cur, char_type const *end, OutputIterator out) const
+ template<typename ForwardIterator, typename OutputIterator>
+ OutputIterator format_all_(ForwardIterator cur, ForwardIterator end, OutputIterator out) const
     {
         detail::case_converting_iterator<OutputIterator, char_type> iout(out, this->traits_.get());
         iout = this->format_all_impl_(cur, end, iout);
@@ -795,8 +979,8 @@
 
     /// INTERNAL ONLY
     ///
- template<typename OutputIterator>
- OutputIterator format_all_impl_(char_type const *&cur, char_type const *end, OutputIterator out, bool metacolon = false) const
+ template<typename ForwardIterator, typename OutputIterator>
+ OutputIterator format_all_impl_(ForwardIterator &cur, ForwardIterator end, OutputIterator out, bool metacolon = false) const
     {
         int max = 0, sub = 0;
         detail::noop_output_iterator<char_type> noop;
@@ -866,11 +1050,11 @@
 
     /// INTERNAL ONLY
     ///
- template<typename OutputIterator>
+ template<typename ForwardIterator, typename OutputIterator>
     OutputIterator format_backref_
     (
- char_type const *&cur
- , char_type const *end
+ ForwardIterator &cur
+ , ForwardIterator end
       , OutputIterator out
     ) const
     {
@@ -916,16 +1100,16 @@
 
     /// INTERNAL ONLY
     ///
- template<typename OutputIterator>
+ template<typename ForwardIterator, typename OutputIterator>
     OutputIterator format_escape_
     (
- char_type const *&cur
- , char_type const *end
+ ForwardIterator &cur
+ , ForwardIterator end
       , OutputIterator out
     ) const
     {
         using namespace regex_constants;
- char_type const *tmp = 0;
+ ForwardIterator tmp;
         // 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));
@@ -1057,18 +1241,18 @@
 
     /// INTERNAL ONLY
     ///
- template<typename OutputIterator>
+ template<typename ForwardIterator, typename OutputIterator>
     OutputIterator format_named_backref_
     (
- char_type const *&cur
- , char_type const *end
+ ForwardIterator &cur
+ , ForwardIterator end
       , OutputIterator out
     ) const
     {
         using namespace regex_constants;
         detail::ensure(cur != end && BOOST_XPR_CHAR_(char_type, '<') == *cur++
             , error_badmark, "invalid named back-reference");
- char_type const *begin = cur;
+ ForwardIterator 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/regex_algorithms.hpp
==============================================================================
--- trunk/boost/xpressive/regex_algorithms.hpp (original)
+++ trunk/boost/xpressive/regex_algorithms.hpp 2008-03-16 02:49:13 EDT (Sun, 16 Mar 2008)
@@ -14,6 +14,7 @@
 # pragma once
 #endif
 
+#include <string>
 #include <iterator>
 #include <boost/mpl/or.hpp>
 #include <boost/range/end.hpp>
@@ -23,6 +24,7 @@
 #include <boost/type_traits/add_const.hpp>
 #include <boost/type_traits/is_pointer.hpp>
 #include <boost/type_traits/remove_const.hpp>
+#include <boost/xpressive/match_results.hpp>
 #include <boost/xpressive/detail/detail_fwd.hpp>
 #include <boost/xpressive/detail/core/state.hpp>
 #include <boost/xpressive/detail/utility/save_restore.hpp>
@@ -550,7 +552,8 @@
 }
 } // namespace detail
 
-/// \brief Build an output sequence given an input sequence, a regex, and a format string.
+/// \brief Build an output sequence given an input sequence, a regex, and a format string or
+/// a formatter object or function.
 ///
 /// 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
@@ -570,7 +573,8 @@
 /// \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 format The format string used to format the replacement sequence,
+/// or a formatter function or function object.
 /// \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.
@@ -583,7 +587,7 @@
   , 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
+ , typename disable_if<detail::is_char_ptr<ForwardRange> >::type * = 0
 )
 {
     BidiIter begin_ = begin, end_ = end;
@@ -616,7 +620,7 @@
   , 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
+ , typename disable_if<mpl::or_<is_pointer<BidiContainer>, detail::is_char_ptr<ForwardRange> > >::type * = 0
 )
 {
     BidiContainer result;
@@ -636,7 +640,7 @@
   , 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
+ , typename disable_if<mpl::or_<is_pointer<BidiContainer>, detail::is_char_ptr<ForwardRange> > >::type * = 0
 )
 {
     BidiContainer result;
@@ -656,12 +660,11 @@
   , 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
+ , typename disable_if<detail::is_char_ptr<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;

Modified: trunk/libs/xpressive/test/Jamfile.v2
==============================================================================
--- trunk/libs/xpressive/test/Jamfile.v2 (original)
+++ trunk/libs/xpressive/test/Jamfile.v2 2008-03-16 02:49:13 EDT (Sun, 16 Mar 2008)
@@ -49,6 +49,7 @@
          [ run test11u.cpp ]
          [ run misc1.cpp ]
          [ run misc2.cpp ]
+ [ run test_format.cpp ]
          [ run test_cycles.cpp ]
          [ run test_non_char.cpp ]
          [ run test_static.cpp ]

Added: trunk/libs/xpressive/test/test_format.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/xpressive/test/test_format.cpp 2008-03-16 02:49:13 EDT (Sun, 16 Mar 2008)
@@ -0,0 +1,133 @@
+///////////////////////////////////////////////////////////////////////////////
+// test_format.hpp
+//
+// Copyright 2008 Eric Niebler. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// Test all the different ways to call regex_replace with a formatter.
+
+#include <map>
+#include <string>
+#include <boost/test/unit_test.hpp>
+#include <boost/xpressive/xpressive.hpp>
+
+using namespace boost::xpressive;
+
+std::map<std::string, std::string> replacements;
+
+struct format1
+{
+ template<typename BidiIter>
+ std::string operator()(match_results<BidiIter> const &what) const
+ {
+ return replacements[what[1].str()];
+ }
+};
+
+struct format2
+{
+ template<typename BidiIter, typename OutIter>
+ OutIter operator()(match_results<BidiIter> const &what, OutIter out) const
+ {
+ std::map<std::string, std::string>::const_iterator where = replacements.find(what[1].str());
+ if(where != replacements.end())
+ out = std::copy((*where).second.begin(), (*where).second.end(), out);
+ return out;
+ }
+};
+
+struct format3
+{
+ template<typename BidiIter, typename OutIter>
+ OutIter operator()(match_results<BidiIter> const &what, OutIter out, regex_constants::match_flag_type) const
+ {
+ std::map<std::string, std::string>::const_iterator where = replacements.find(what[1].str());
+ if(where != replacements.end())
+ out = std::copy((*where).second.begin(), (*where).second.end(), out);
+ return out;
+ }
+};
+
+std::string format_fun(smatch const &what)
+{
+ return replacements[what[1].str()];
+}
+
+std::string c_format_fun(cmatch const &what)
+{
+ return replacements[what[1].str()];
+}
+
+void test_main()
+{
+ replacements["X"] = "this";
+ replacements["Y"] = "that";
+
+ std::string input("\"$(X)\" has the value \"$(Y)\""), output;
+ sregex rx = sregex::compile("\\$\\(([^\\)]+)\\)");
+ cregex crx = cregex::compile("\\$\\(([^\\)]+)\\)");
+
+ std::string result("\"this\" has the value \"that\"");
+
+ output = regex_replace(input, rx, format1());
+ BOOST_CHECK_EQUAL(output, result);
+
+ output = regex_replace(input.c_str(), crx, format1());
+ BOOST_CHECK_EQUAL(output, result);
+
+ output = regex_replace(input, rx, format2());
+ BOOST_CHECK_EQUAL(output, result);
+
+ output = regex_replace(input.c_str(), crx, format2());
+ BOOST_CHECK_EQUAL(output, result);
+
+ output = regex_replace(input, rx, format3());
+ BOOST_CHECK_EQUAL(output, result);
+
+ output = regex_replace(input.c_str(), crx, format3());
+ BOOST_CHECK_EQUAL(output, result);
+
+ output = regex_replace(input, rx, format_fun);
+ BOOST_CHECK_EQUAL(output, result);
+
+ output = regex_replace(input.c_str(), crx, c_format_fun);
+ BOOST_CHECK_EQUAL(output, result);
+
+ output = regex_replace(input, rx, &format_fun);
+ BOOST_CHECK_EQUAL(output, result);
+
+ output = regex_replace(input.c_str(), crx, &c_format_fun);
+ BOOST_CHECK_EQUAL(output, result);
+
+ output.clear();
+ regex_replace(std::back_inserter(output), input.begin(), input.end(), rx, format1());
+ BOOST_CHECK_EQUAL(output, result);
+
+ output.clear();
+ regex_replace(std::back_inserter(output), input.begin(), input.end(), rx, format2());
+ BOOST_CHECK_EQUAL(output, result);
+
+ output.clear();
+ regex_replace(std::back_inserter(output), input.begin(), input.end(), rx, format2());
+ BOOST_CHECK_EQUAL(output, result);
+
+ output.clear();
+ regex_replace(std::back_inserter(output), input.begin(), input.end(), rx, format_fun);
+ BOOST_CHECK_EQUAL(output, result);
+
+ output.clear();
+ regex_replace(std::back_inserter(output), input.begin(), input.end(), rx, &format_fun);
+ BOOST_CHECK_EQUAL(output, result);
+}
+
+using namespace boost::unit_test;
+///////////////////////////////////////////////////////////////////////////////
+// init_unit_test_suite
+//
+test_suite* init_unit_test_suite( int argc, char* argv[] )
+{
+ test_suite *test = BOOST_TEST_SUITE("test_format");
+ test->add(BOOST_TEST_CASE(&test_main));
+ return test;
+}


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