Boost logo

Boost-Commit :

From: hartmut.kaiser_at_[hidden]
Date: 2008-05-06 19:58:26


Author: hkaiser
Date: 2008-05-06 19:58:25 EDT (Tue, 06 May 2008)
New Revision: 45183
URL: http://svn.boost.org/trac/boost/changeset/45183

Log:
Spirit.Karma: Added binary padding generator
Added:
   trunk/boost/spirit/home/karma/binary/padding.hpp (contents, props changed)
Text files modified:
   trunk/boost/spirit/home/karma/binary.hpp | 1
   trunk/boost/spirit/home/karma/binary/meta_grammar.hpp | 5 ++++
   trunk/boost/spirit/home/karma/detail/output_iterator.hpp | 46 ++++++++++++++++++++++++++++++++++++++-
   trunk/boost/spirit/home/support/placeholders.hpp | 9 ++++++-
   trunk/libs/spirit/test/karma/binary.cpp | 20 ++++++++++++++++
   trunk/libs/spirit/test/karma/test.hpp | 44 ++++++++++++++++++++++++++++++++++++-
   6 files changed, 118 insertions(+), 7 deletions(-)

Modified: trunk/boost/spirit/home/karma/binary.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/binary.hpp (original)
+++ trunk/boost/spirit/home/karma/binary.hpp 2008-05-06 19:58:25 EDT (Tue, 06 May 2008)
@@ -11,6 +11,7 @@
 #endif
 
 #include <boost/spirit/home/karma/binary/binary.hpp>
+#include <boost/spirit/home/karma/binary/padding.hpp>
 #include <boost/spirit/home/karma/binary/meta_grammar.hpp>
 
 #endif

Modified: trunk/boost/spirit/home/karma/binary/meta_grammar.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/binary/meta_grammar.hpp (original)
+++ trunk/boost/spirit/home/karma/binary/meta_grammar.hpp 2008-05-06 19:58:25 EDT (Tue, 06 May 2008)
@@ -29,6 +29,8 @@
     template <integer::endianness endian, int bits>
     struct binary_lit_director;
 
+ struct binary_padding_director;
+
     struct main_meta_grammar;
 
     template <typename Expr, typename Enable>
@@ -223,6 +225,9 @@
>,
                 karma::domain,
                 mpl::identity<extract_binary_lit_director<mpl::_, mpl::_> >
+ >,
+ meta_grammar::function1_rule<
+ karma::domain, tag::pad, binary_padding_director
>
>
     {

Added: trunk/boost/spirit/home/karma/binary/padding.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/spirit/home/karma/binary/padding.hpp 2008-05-06 19:58:25 EDT (Tue, 06 May 2008)
@@ -0,0 +1,57 @@
+// Copyright (c) 2001-2008 Hartmut Kaiser
+//
+// 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)
+
+#if !defined(BOOST_SPIRIT_KARMA_PADDING_MAY_06_2008_0436PM)
+#define BOOST_SPIRIT_KARMA_PADDING_MAY_06_2008_0436PM
+
+#include <boost/spirit/home/karma/domain.hpp>
+#include <boost/spirit/home/karma/delimit.hpp>
+#include <boost/spirit/home/support/unused.hpp>
+#include <boost/fusion/include/at.hpp>
+#include <boost/spirit/home/karma/detail/generate_to.hpp>
+
+namespace boost { namespace spirit { namespace karma
+{
+ struct binary_padding_director
+ {
+ template <typename Component, typename Context, typename Unused>
+ struct attribute
+ {
+ typedef unused_type type;
+ };
+
+ template <typename Component, typename OutputIterator,
+ typename Context, typename Delimiter, typename Parameter>
+ static bool
+ generate(Component const& component, OutputIterator& sink,
+ Context& ctx, Delimiter const& d, Parameter const&)
+ {
+ std::size_t padbytes = fusion::at_c<0>(component.elements);
+ std::size_t count = sink.get_out_count() % padbytes;
+
+ if (count)
+ count = padbytes - count;
+
+ bool result = true;
+ while (result && count-- != 0)
+ result = detail::generate_to(sink, 0);
+
+ karma::delimit(sink, d); // always do post-delimiting
+ return result;
+ }
+
+ template <typename Component>
+ static std::string what(Component const&)
+ {
+ return std::string("pad(") +
+ boost::lexical_cast<std::string>(
+ fusion::at_c<0>(component.elements)) +
+ ")";
+ }
+ };
+
+}}}
+
+#endif

Modified: trunk/boost/spirit/home/karma/detail/output_iterator.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/detail/output_iterator.hpp (original)
+++ trunk/boost/spirit/home/karma/detail/output_iterator.hpp 2008-05-06 19:58:25 EDT (Tue, 06 May 2008)
@@ -20,6 +20,37 @@
 namespace boost { namespace spirit { namespace karma { namespace detail
 {
     ///////////////////////////////////////////////////////////////////////////
+ // This class is used to keep track of the current position in the output.
+ ///////////////////////////////////////////////////////////////////////////
+ class position_sink
+ {
+ public:
+ position_sink() : count(0), line(1), column(0) {}
+ void tidy() { count = 0; line = 1; column = 0; }
+
+ template <typename T>
+ void output(T const& value)
+ {
+ ++count;
+ if (value == '\n') {
+ ++line;
+ column = 1;
+ }
+ else {
+ ++column;
+ }
+ }
+ std::size_t get_count() const { return count; }
+ std::size_t get_line() const { return line; }
+ std::size_t get_column() const { return column; }
+
+ private:
+ std::size_t count;
+ std::size_t line;
+ std::size_t column;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
     // This class is used to count the umber of characters streamed into the
     // output.
     ///////////////////////////////////////////////////////////////////////////
@@ -233,6 +264,10 @@
             if (mode & count_characters) // count characters, if appropriate
                 count_data.output();
 
+ // always track position in the output (this is needed by different
+ // generators, such as indent, pad, etc.)
+ track_position_data.output(value);
+
             if (mode & buffer_characters) // buffer output, if appropriate
                 buffer_data.output(value);
             else
@@ -255,6 +290,12 @@
             buffer_data.copy(sink);
         }
         
+ // return the current count in the output
+ std::size_t get_out_count() const
+ {
+ return track_position_data.get_count();
+ }
+
     protected:
         // this is the wrapped user supplied output iterator
         OutputIterator& sink;
@@ -263,8 +304,9 @@
         // these are the hooks providing optional functionality
         counting_sink count_data; // for counting
         buffer_sink<OutputIterator> buffer_data; // for buffering
- output_mode mode;
-
+ position_sink track_position_data; // for position tracking
+ int mode;
+
         // suppress warning about assignment operator not being generated
         output_iterator& operator=(output_iterator const&);
     };

Modified: trunk/boost/spirit/home/support/placeholders.hpp
==============================================================================
--- trunk/boost/spirit/home/support/placeholders.hpp (original)
+++ trunk/boost/spirit/home/support/placeholders.hpp 2008-05-06 19:58:25 EDT (Tue, 06 May 2008)
@@ -10,6 +10,7 @@
 
 #include <boost/xpressive/proto/proto.hpp>
 #include <boost/mpl/bool.hpp>
+#include <boost/type_traits/is_enum.hpp>
 
 namespace boost { namespace spirit
 {
@@ -42,7 +43,8 @@
         struct big_qword {};
         struct little_qword {};
 #endif
-
+ struct pad {};
+
         struct ushort {};
         struct ulong {};
         struct uint {};
@@ -101,6 +103,7 @@
     typedef proto::terminal<tag::big_qword>::type big_qword_type;
     typedef proto::terminal<tag::little_qword>::type little_qword_type;
 #endif
+ typedef proto::terminal<tag::pad>::type pad_type;
 
     typedef proto::terminal<tag::ushort>::type ushort_type;
     typedef proto::terminal<tag::ulong>::type ulong_type;
@@ -159,6 +162,7 @@
     proto::terminal<tag::big_qword>::type const big_qword = {{}};
     proto::terminal<tag::little_qword>::type const little_qword = {{}};
 #endif
+ proto::terminal<tag::pad>::type const pad = {{}};
 
     proto::terminal<tag::ushort>::type const ushort = {{}};
     proto::terminal<tag::ulong>::type const ulong = {{}};
@@ -214,6 +218,7 @@
         (void) qword; (void) little_qword; (void) big_qword;
         (void) ulong_long; (void) long_long;
 #endif
+ (void) pad;
         (void) float_; (void) double_; (void) long_double;
         (void) left_align; (void) right_align; (void) center;
         (void) delimit; (void) verbatim;
@@ -270,7 +275,7 @@
     // test if a tag is an integer type
     ///////////////////////////////////////////////////////////////////////////
     template <typename T, typename Domain>
- struct is_int_lit_tag : mpl::false_ {};
+ struct is_int_lit_tag : is_enum<T> {};
 
     template <typename Domain>
     struct is_int_lit_tag<short, Domain> : mpl::true_ {};

Modified: trunk/libs/spirit/test/karma/binary.cpp
==============================================================================
--- trunk/libs/spirit/test/karma/binary.cpp (original)
+++ trunk/libs/spirit/test/karma/binary.cpp 2008-05-06 19:58:25 EDT (Tue, 06 May 2008)
@@ -31,7 +31,17 @@
         BOOST_TEST(binary_test("\x01\x02\x03\x04\x05\x06\x07\x08", 8, qword,
             0x0807060504030201LL));
 #endif
-#else
+
+ BOOST_TEST(binary_test_delimited("\x01\x00\x00\x00", 4, byte, 0x01, pad(4)));
+ BOOST_TEST(binary_test_delimited("\x01\x02\x00\x00", 4, word, 0x0201, pad(4)));
+ BOOST_TEST(binary_test_delimited("\x01\x02\x03\x04", 4, dword, 0x04030201, pad(4)));
+#ifdef BOOST_HAS_LONG_LONG
+ BOOST_TEST(binary_test_delimited("\x01\x02\x03\x04\x05\x06\x07\x08\x00\x00", 10,
+ qword, 0x0807060504030201LL, pad(10)));
+#endif
+
+#else // BOOST_LITTLE_ENDIAN
+
         BOOST_TEST(binary_test("\x01", 1, byte, 0x01));
         BOOST_TEST(binary_test("\x01\x02", 2, word, 0x0102));
         BOOST_TEST(binary_test("\x01\x02\x03\x04", 4, dword, 0x01020304));
@@ -39,6 +49,14 @@
         BOOST_TEST(binary_test("\x01\x02\x03\x04\x05\x06\x07\x08", 8, qword,
             0x0102030405060708LL));
 #endif
+
+ BOOST_TEST(binary_test_delimited("\x01\x00\x00\x00", 4, byte, 0x01, pad(4)));
+ BOOST_TEST(binary_test_delimited("\x01\x02\x00\x00", 4, word, 0x0102, pad(4)));
+ BOOST_TEST(binary_test_delimited("\x01\x02\x03\x04", 4, dword, 0x01020304, pad(4)));
+#ifdef BOOST_HAS_LONG_LONG
+ BOOST_TEST(binary_test_delimited("\x01\x02\x03\x04\x05\x06\x07\x08\x00\x00", 10,
+ qword, 0x0102030405060708LL, pad(10)));
+#endif
 #endif
     }
 

Modified: trunk/libs/spirit/test/karma/test.hpp
==============================================================================
--- trunk/libs/spirit/test/karma/test.hpp (original)
+++ trunk/libs/spirit/test/karma/test.hpp 2008-05-06 19:58:25 EDT (Tue, 06 May 2008)
@@ -184,7 +184,7 @@
         Generator const& g)
     {
         namespace karma = boost::spirit::karma;
- typedef std::basic_string<Char> string_type;
+ typedef std::basic_string<char> string_type;
         
         // we don't care about the result of the "what" function.
         // we only care that all generators have it:
@@ -203,7 +203,7 @@
         Generator const& g, Parameter const &parameter)
     {
         namespace karma = boost::spirit::karma;
- typedef std::basic_string<Char> string_type;
+ typedef std::basic_string<char> string_type;
         
         // we don't care about the result of the "what" function.
         // we only care that all generators have it:
@@ -215,6 +215,46 @@
         return result && !std::memcmp(generated.c_str(), expected, size);
     }
 
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Generator, typename Delimiter>
+ inline bool
+ binary_test_delimited(char const *expected, std::size_t size,
+ Generator const& g, Delimiter const& d)
+ {
+ namespace karma = boost::spirit::karma;
+ typedef std::basic_string<char> string_type;
+
+ // we don't care about the result of the "what" function.
+ // we only care that all generators have it:
+ karma::what(g);
+
+ string_type generated;
+ bool result = karma::generate_delimited(std::back_inserter(generated),
+ g, d);
+
+ return result && !std::memcmp(generated.c_str(), expected, size);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Generator, typename Parameter, typename Delimiter>
+ inline bool
+ binary_test_delimited(char const *expected, std::size_t size,
+ Generator const& g, Parameter const &parameter, Delimiter const& d)
+ {
+ namespace karma = boost::spirit::karma;
+ typedef std::basic_string<char> string_type;
+
+ // we don't care about the result of the "what" function.
+ // we only care that all generators have it:
+ karma::what(g);
+
+ string_type generated;
+ bool result = karma::generate_delimited(std::back_inserter(generated),
+ g, parameter, d);
+
+ return result && !std::memcmp(generated.c_str(), expected, size);
+ }
+
 } // namespace spirit_test
 
 #endif // !BOOST_SPIRIT_KARMA_TEST_FEB_23_2007_1221PM


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