|
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 ¶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
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