$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
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 ¶meter)
     {
         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 ¶meter, 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