// $Id$
//
-// Copyright (C) 2007
-// Fraunhofer Institute for Open Communication Systems (FOKUS)
-// Competence Center NETwork research (NET), St. Augustin, GERMANY
+// Copyright (C) 2007
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
//
// This program is free software; you can redistribute it and/or modify
/** \file
\brief VariantParser internal header */
-#ifndef IH_VariantParser_
-#define IH_VariantParser_ 1
+#ifndef IH_SENF_Packets_VariantParser_
+#define IH_SENF_Packets_VariantParser_ 1
// Custom includes
#include "PacketParser.hh"
+#include <boost/preprocessor/cat.hpp>
+#include <boost/preprocessor/seq/enum.hpp>
+#include <boost/preprocessor/seq/fold_left.hpp>
+#include <boost/preprocessor/seq/for_each.hpp>
+#include <boost/preprocessor/logical/or.hpp>
+#include <boost/preprocessor/seq/for_each_i.hpp>
+#include <boost/preprocessor/logical/not.hpp>
+#include <boost/preprocessor/expr_if.hpp>
///////////////////////////////ih.p////////////////////////////////////////
namespace senf {
namespace detail {
-# define SENF_PARSE_VARIANT_TPL_ARGS_DFL(n) \
- BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT( SENF_LIMIT_PARSE_VARIANT, \
- n, \
- boost::mpl::na )
-
-# define SENF_PARSE_VARIANT_TPL_ARGS(n) BOOST_PP_ENUM_PARAMS( SENF_LIMIT_PARSE_VARIANT, n )
-
-# ifndef DOXYGEN
+#ifndef DOXYGEN
template <class Variant, unsigned N>
struct VariantBytes {
static PacketParserBase::size_type bytes(Variant const & v, unsigned n);
};
-# endif
-
- /** \brief Internal: Variant Policy used by senf::DirectVariantParser */
- template <class ChooserType, unsigned Distance, class Translator>
- struct DirectVariantParser
+ template <class Transform, class AuxPolicy, class AuxTag>
+ struct VariantParserPolicy;
+
+ template <class AuxPolicy, class AuxTag>
+ struct VariantParserPolicy<void, AuxPolicy, AuxTag>
+ {};
+
+ template <class Transform, class AuxPolicy, class AuxTag>
+ struct VariantParserPolicy
+ : public VariantParserPolicy< void,
+ TransformAuxParserPolicy<AuxPolicy, Transform>, AuxTag >
+ {};
+
+ template <class AuxPolicy>
+ struct VariantParserPolicy<void, AuxPolicy, senf::detail::auxtag::none>
+ {
+ typedef AuxPolicy type;
+ };
+
+ template <class AuxPolicy, class Transform>
+ struct VariantParserPolicy<void,
+ AuxPolicy,
+ senf::detail::auxtag::transform<Transform,
+ senf::detail::auxtag::none> >
+ {
+ typedef TransformAuxParserPolicy<AuxPolicy, Transform> type;
+ };
+
+ template <class Parsers, class Transform>
+ struct VariantParserTraits
+ {
+ template <class AuxPolicy, class AuxTag>
+ struct parser {
+ typedef senf::VariantParser<
+ typename VariantParserPolicy<Transform, AuxPolicy, AuxTag>::type,
+ Parsers> type;
+ };
+ };
+
+ template <class T, T (*KeyFn)()>
+ struct VariantKey
+ {
+ static T key() { return (*KeyFn)(); }
+ };
+
+ template <class T, class Keys>
+ struct VariantKeyTransform
+ {
+ typedef unsigned value_type;
+ typedef T input_type;
+ static unsigned get(input_type v);
+ static input_type set(unsigned v);
+ };
+
+ template <class In, class Out, class Keys, unsigned N>
+ struct VariantKeyTransformCheck
{
- typedef PacketParserBase::data_iterator data_iterator;
- typedef PacketParserBase::state_type state_type;
- typedef PacketParserBase::size_type size_type;
-
- static size_type const init_bytes = 0;
- size_type bytes(data_iterator i, state_type s) const { return 0; }
- data_iterator begin(data_iterator i, state_type s) const { return i; }
-
- ChooserType chooser(data_iterator i, state_type s) const {
- return ChooserType(boost::prior(i, Distance),s);
- }
-
- unsigned variant(data_iterator i, state_type s) const {
- return Translator::fromChooser(chooser(i,s).value());
- }
-
- void variant(unsigned v, data_iterator i, state_type s) {
- chooser(i,s).value(Translator::toChooser(v));
- }
+ static Out get(In v);
+ static In set(Out v);
};
- /** \brief Internal: Identity chooser translator */
- struct VariantParser_IdentityTranslator {
- static unsigned fromChooser(unsigned value) { return value; }
- static unsigned toChooser(unsigned value) { return value; }
+ template <class In, class Out, class Keys>
+ struct VariantKeyTransformCheck<In, Out, Keys, 0>
+ {
+ static Out get(In v);
+ static In set(Out v);
};
+
+# define SENF_PARSER_VARIANT_I(access, name, chooser, types) \
+ SENF_PARSER_REQUIRE_VAR(variant) \
+ private: \
+ typedef boost::mpl::vector< BOOST_PP_SEQ_ENUM(SENF_PARSER_VARIANT_TYPES(types)) > \
+ BOOST_PP_CAT(name, _parsers); \
+ typedef BOOST_PP_CAT(SENF_PARSER_COLLECTION_GETAUX(chooser), _t)::value_type \
+ BOOST_PP_CAT(name,_chooser_value_type); \
+ BOOST_PP_IF( SENF_PARSER_VARIANT_NEEDTRANSFORM(types), \
+ SENF_PARSER_VARIANT_MAKETRANSFORM, \
+ SENF_PARSER_VARIANT_NOTRANSFORM )(name, \
+ types) \
+ typedef senf::detail::VariantParserTraits< BOOST_PP_CAT(name, _parsers), \
+ BOOST_PP_CAT(name, _transform) > \
+ BOOST_PP_CAT(name, _traits); \
+ public: \
+ SENF_PARSER_COLLECTION_I( \
+ BOOST_PP_IIF( SENF_PARSER_VARIANT_NEEDACCESSORS(types), private, access), \
+ name, chooser, BOOST_PP_CAT(name, _traits) ); \
+ access: \
+ BOOST_PP_SEQ_FOR_EACH_I(SENF_PARSER_VARIANT_ACCESSOR, name, types) \
+ public:
+
+# define SENF_PARSER_VARIANT_MAKETRANSFORM(name, types) \
+ BOOST_PP_SEQ_FOR_EACH_I(SENF_PARSER_VARIANT_KEYVALUE, name, types) \
+ template <BOOST_PP_CAT(name, _chooser_value_type) (*KeyFn)()> \
+ struct BOOST_PP_CAT(name, _key_value_template) \
+ : public senf::detail::VariantKey<BOOST_PP_CAT(name, _chooser_value_type), KeyFn> {}; \
+ template <class T, T (*K)()> friend class senf::detail::VariantKey; \
+ typedef senf::detail::VariantKeyTransform< \
+ BOOST_PP_CAT(name,_chooser_value_type), \
+ boost::mpl::vector< \
+ BOOST_PP_SEQ_ENUM(SENF_PARSER_VARIANT_KEYVALUES(name, types)) \
+ > > BOOST_PP_CAT(name, _transform);
+
+# define SENF_PARSER_VARIANT_KEYVALUE(r, name, i, elem) \
+ static BOOST_PP_CAT(name, _chooser_value_type) \
+ BOOST_PP_CAT(BOOST_PP_CAT(name, _key_),i)() \
+ { return SENF_PARSER_VARIANT_GETKEY(elem, i); }
+
+# define SENF_PARSER_VARIANT_NOTRANSFORM(name, types) \
+ typedef void BOOST_PP_CAT(name, _transform);
+
+# define SENF_PARSER_VARIANT_KEYVALUES(name, types) \
+ BOOST_PP_SEQ_FOR_EACH_I(SENF_PARSER_VARIANT_KEYVALUES_, name, types)
+
+# define SENF_PARSER_VARIANT_KEYVALUES_(r, name, i, elem) \
+ (BOOST_PP_CAT(name,_key_value_template)< \
+ & BOOST_PP_CAT(BOOST_PP_CAT(name, _key_), i) >)
-# define SENF_PARSER_VARIANT_(r, data, elem) ,elem
+# define SENF_PARSER_VARIANT_ACCESSOR(r, name, i, elem) \
+ BOOST_PP_IF( SENF_PARSER_VARIANT_HASID(elem), \
+ SENF_PARSER_VARIANT_MAKEACCESSOR, \
+ SENF_PARSER_VARIANT_NOACCESSOR )(name, i, elem)
-# define SENF_PARSER_VARIANT_I(field, name, chooser, translator, types) \
- typedef senf::DirectVariantParser< \
- BOOST_PP_CAT(chooser, _t), \
- SENF_PARSER_CURRENT_FIXED_OFFSET() - SENF_PARSER_FIXED_OFFSET(chooser), \
- translator \
- BOOST_PP_SEQ_FOR_EACH( SENF_PARSER_VARIANT_, _, types ) \
- >::parser BOOST_PP_CAT(name, _variant_t); \
- field( name, BOOST_PP_CAT(name, _variant_t) )
+# define SENF_PARSER_VARIANT_NOACCESSOR(name, i, elem)
+# define SENF_PARSER_VARIANT_MAKEACCESSOR(name, i, elem) \
+ SENF_PARSER_VARIANT_MAKEACCESSOR_VALUE(name, i, elem, SENF_PARSER_VARIANT_GETID(elem)) \
+ SENF_PARSER_VARIANT_MAKEACCESSOR_HAS(name, i, elem, SENF_PARSER_VARIANT_GETHASID(elem)) \
+ SENF_PARSER_VARIANT_MAKEACCESSOR_INIT(name, i, elem, SENF_PARSER_VARIANT_GETINITID(elem))
+
+# define SENF_PARSER_VARIANT_IFNOTNA(id, x) \
+ BOOST_PP_EXPR_IIF( BOOST_PP_NOT( SENF_PARSER_VARIANT_NA(id) ), x )
+
+# define SENF_PARSER_VARIANT_MAKEACCESSOR_VALUE(name, i, elem, id) \
+ SENF_PARSER_VARIANT_IFNOTNA( id, \
+ typedef SENF_PARSER_VARIANT_GETTYPE(elem) \
+ BOOST_PP_CAT(id, _t); \
+ BOOST_PP_CAT(id, _t) id() const \
+ { return name().get<i>(); } \
+ )
+
+# define SENF_PARSER_VARIANT_MAKEACCESSOR_HAS(name, i, elem, id) \
+ SENF_PARSER_VARIANT_IFNOTNA( id, \
+ bool id() const \
+ { return name().variant() == i; } \
+ )
+
+# define SENF_PARSER_VARIANT_MAKEACCESSOR_INIT(name, i, elem, id) \
+ SENF_PARSER_VARIANT_IFNOTNA( id, \
+ void id() const \
+ { name().init<i>(); } \
+ )
+
+# define SENF_PARSER_VARIANT_KEY_GOBBLE__key(key, type)
+# define SENF_PARSER_VARIANT_KEY_GETKEY__key(key, type) key
+# define SENF_PARSER_VARIANT_KEY_GETTYPE__key(key, type) type
+
+# define SENF_PARSER_VARIANT_ID_GOBBLE__id(id, value)
+# define SENF_PARSER_VARIANT_ID_GETID__id(id, value) id
+# define SENF_PARSER_VARIANT_ID_GETVALUE__id(id, value) value
+# define SENF_PARSER_VARIANT_ID_GETHASID__id(id, value) SENF_CAT_RECURS3(has_, id)
+# define SENF_PARSER_VARIANT_ID_GETINITID__id(id, value) SENF_CAT_RECURS3(init_, id)
+
+# define SENF_PARSER_VARIANT_ID_GOBBLE__novalue(id, value)
+# define SENF_PARSER_VARIANT_ID_GETID__novalue(id, value) na
+# define SENF_PARSER_VARIANT_ID_GETVALUE__novalue(id, value) value
+# define SENF_PARSER_VARIANT_ID_GETHASID__novalue(id, value) na
+# define SENF_PARSER_VARIANT_ID_GETINITID__novalue(id, value) id
+
+# define SENF_PARSER_VARIANT_ID_GOBBLE__ids(id, hasid, initid, value)
+# define SENF_PARSER_VARIANT_ID_GETID__ids(id, hasid, initid, value) id
+# define SENF_PARSER_VARIANT_ID_GETVALUE__ids(id, hasid, initid, value) value
+# define SENF_PARSER_VARIANT_ID_GETHASID__ids(id, hasid, initid, value) hasid
+# define SENF_PARSER_VARIANT_ID_GETINITID__ids(id, hasid, initid, value) initid
+
+# define SENF_PARSER_VARIANT_NA_GOBBLE__na
+
+# define SENF_PARSER_VARIANT_NA(x) \
+ BOOST_PP_IS_EMPTY( SENF_CAT_RECURS1(SENF_PARSER_VARIANT_NA_GOBBLE__, x) )
+
+# define SENF_PARSER_VARIANT_HASKEY(x) \
+ SENF_PARSER_VARIANT_HASKEY_( SENF_PARSER_VARIANT_GETVALUE(x) )
+
+# define SENF_PARSER_VARIANT_HASKEY_(x) \
+ BOOST_PP_IS_EMPTY( SENF_CAT_RECURS1(SENF_PARSER_VARIANT_KEY_GOBBLE__, x) )
+
+# define SENF_PARSER_VARIANT_GETKEY(x, default) \
+ SENF_PARSER_VARIANT_GETKEY_( SENF_PARSER_VARIANT_GETVALUE(x), default )
+
+# define SENF_PARSER_VARIANT_GETKEY_(x, default) \
+ BOOST_PP_IF( SENF_PARSER_VARIANT_HASKEY_(x), \
+ BOOST_PP_CAT(SENF_PARSER_VARIANT_KEY_GETKEY__, x), \
+ default )
+
+# define SENF_PARSER_VARIANT_HASID(x) \
+ BOOST_PP_IS_EMPTY( SENF_CAT_RECURS2(SENF_PARSER_VARIANT_ID_GOBBLE__, x) )
+
+# define SENF_PARSER_VARIANT_GETID(x) \
+ BOOST_PP_CAT(SENF_PARSER_VARIANT_ID_GETID__, x)
+
+# define SENF_PARSER_VARIANT_GETHASID(x) \
+ BOOST_PP_CAT(SENF_PARSER_VARIANT_ID_GETHASID__, x)
+
+# define SENF_PARSER_VARIANT_GETINITID(x) \
+ BOOST_PP_CAT(SENF_PARSER_VARIANT_ID_GETINITID__, x)
+
+# define SENF_PARSER_VARIANT_GETVALUE(x) \
+ BOOST_PP_IF( SENF_PARSER_VARIANT_HASID(x), \
+ BOOST_PP_CAT(SENF_PARSER_VARIANT_ID_GETVALUE__, x), \
+ x )
+
+# define SENF_PARSER_VARIANT_GETTYPE(x) \
+ SENF_PARSER_VARIANT_GETTYPE_( SENF_PARSER_VARIANT_GETVALUE(x) )
+
+# define SENF_PARSER_VARIANT_GETTYPE_(x) \
+ BOOST_PP_IF( SENF_PARSER_VARIANT_HASKEY_(x), \
+ BOOST_PP_CAT(SENF_PARSER_VARIANT_KEY_GETTYPE__, x), \
+ x )
+
+# define SENF_PARSER_VARIANT_NEEDTRANSFORM(types) \
+ BOOST_PP_SEQ_FOLD_LEFT(SENF_PARSER_VARIANT_NEEDTRANSFORM_, 0, types)
+
+# define SENF_PARSER_VARIANT_NEEDTRANSFORM_(s, state, elem) \
+ BOOST_PP_OR(state, SENF_PARSER_VARIANT_HASKEY(elem))
+
+# define SENF_PARSER_VARIANT_NEEDACCESSORS(types) \
+ BOOST_PP_SEQ_FOLD_LEFT(SENF_PARSER_VARIANT_NEEDACCESSORS_, 0, types)
+
+# define SENF_PARSER_VARIANT_NEEDACCESSORS_(s, state, elem) \
+ BOOST_PP_OR(state, SENF_PARSER_VARIANT_HASID(elem))
+
+# define SENF_PARSER_VARIANT_TYPES(types) \
+ BOOST_PP_SEQ_FOR_EACH(SENF_PARSER_VARIANT_TYPES_, _, types)
+
+# define SENF_PARSER_VARIANT_TYPES_(r, _, elem) \
+ (SENF_PARSER_VARIANT_GETTYPE(elem))
+
+#endif
}}