LIBS = ['Packets', 'Socket', 'Utils'], no_includes = 1)
SENFSCons.Doxygen(env, extra_sources = [
- env.Dia2Png("TLV.dia", DIA2PNGMAXWIDTH = 600)
+ env.Dia2Png("TLV.dia")
])
value_type operator[](difference_type i) const;
};
+ /** \brief Define array field
+
+ This macro is a special helper to define a senf::Parse_Array type field, a fixed size
+ collection of fixed size elements.
+
+ \param[in] name field name
+ \param[in] elt_type array element type
+ \param[in] size constant number of elements
+ \hideinitializer
+ \ingroup packetparsermacros
+ */
+# define SENF_PARSER_ARRAY(name, elt_type, size) \
+ typedef senf::Parse_Array<size,elt_type> BOOST_PP_CAT(name, _array_t); \
+ SENF_PARSER_FIELD( name, BOOST_PP_CAT(name, _array_t) )
+
}
///////////////////////////////hh.e////////////////////////////////////////
See the documentation of each of these macros for a detailed description of the macro arguments
and usage. Bit-fields are handled in the following section.
+ There also some supplementary macros for defining fields of more complex composite types
+ (e.g. vectors). See the list of 'Defines' further down this page.
+
\subsection parsermacrosbitfields Bit-fields
\par ""
This command will skip the given number of bits within a bitfield group. This command does \e
only affect bitfield commands. Therefore, a SENF_PARSER_SKIP_BITS command which is not followed
by a bitfield command will be ignored.
+
+ \hideinitializer
*/
#define SENF_PARSER_SKIP_BITS(bits)
group covers multiple bytes before the bit field \a name.
\param[in] name field or label to jump to
+ \hideinitializer
*/
#define SENF_PARSER_GOTO(name)
\param[in] offset Depending on the parser type, either single \a bytes value or two arguments \a
bytes and \a init_size.
+ \hideinitializer
*/
#define SENF_PARSER_GOTO_OFFSET(offset)
labeled with \ref SENF_PARSER_LABEL()
\param[in] name label name
+ \hideinitializer
*/
#define SENF_PARSER_LABEL(name)
while defining the parser, normally while defining inline functions.
This macro will return the correct value when defining fixed or dynamically sized parsers.
+
+ \param[in] name field or label name
+ \returns offset of the field from parsers start
+ \hideinitializer
*/
#define SENF_PARSER_OFFSET(name)
+/** \brief Get fixed field offset, if possible
+
+ This macro will return the fixed offset to the field \a name, a compile-time constant
+ expression. This is identical to \ref SENF_PARSER_OFFSET() when defining a fixed size parser.
+
+ Even in dynamically sized parsers this macro will work, if the field \a name is preceded by
+ fixed size fields only. This macro does \e not validate this condition, it will return an
+ arbitrary incorrect value otherwise.
+
+ \pre Field \a name preceded by fixed size fields only
+ \param[in] field or label name
+ \returns compile-time constant offset of the field from parsers start
+ \hideinitializer
+ */
+#define SENF_PARSER_FIXED_OFFSET(name)
+
///@}
#else
#define SENF_PARSER_LABEL BOOST_PP_CAT(SENF_PARSER_LABEL_, SENF_PARSER_TYPE)
#define SENF_PARSER_OFFSET BOOST_PP_CAT(SENF_PARSER_OFFSET_, SENF_PARSER_TYPE)
+#define SENF_PARSER_FIXED_OFFSET BOOST_PP_CAT(SENF_PARSER_FIXED_OFFSET_,SENF_PARSER_TYPE)
+#define SENF_PARSER_CURRENT_FIXED_OFFSET BOOST_PP_CAT(SENF_PARSER_CURRENT_FIXED_OFFSET_, SENF_PARSER_TYPE)
#define SENF_PARSER_FINALIZE BOOST_PP_CAT(SENF_PARSER_FINALIZE_, SENF_PARSER_TYPE)
# define SENF_PARSER_OFFSET_var(name) BOOST_PP_CAT(name, _offset)()
#
# ///////////////////////////////////////////////////////////////////////////
+# // SENF_PARSER_FIXED_OFFSET_*
+#
+# define SENF_PARSER_FIXED_OFFSET_fix(name) BOOST_PP_CAT(name, _offset)
+# define SENF_PARSER_FIXED_OFFSET_var(name) BOOST_PP_CAT(name, _init_bytes)
+#
+# ///////////////////////////////////////////////////////////////////////////
+# // SENF_PARSER_FIXED_OFFSET_*
+#
+# define SENF_PARSER_CURRENT_FIXED_OFFSET_fix() SENF_MPL_SLOT_GET(offset)
+# define SENF_PARSER_CURRENT_FIXED_OFFSET_var() SENF_MPL_SLOT_GET(init_bytes)
+#
+# ///////////////////////////////////////////////////////////////////////////
# // SENF_PARSER_FINALIZE_*
#
# define SENF_PARSER_FINALIZE_var(name) \
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2007
+// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
+// Kompetenzzentrum fuer NETwork research (NET)
+// Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+namespace senf {
+
+ /** \brief Example of a list policy. ONLY FOR EXPOSITION.
+
+ This class shows the interface which must be implemented by a list policy. It is not a list
+ policy only a declaration of the interface:
+ \code
+ struct ExampleListPolicy
+ {
+ // optional typedefs used to simplify all other declarations
+ typedef PacketParserBase::data_iterator data_iterator;
+ typedef PacketParserBase::state_type state_type;
+ typedef PacketParserBase::size_type size_type;
+
+ // mandatory typedefs in the parser and container policy
+ typedef ElementParser element_type;
+ typedef Parse_List< ExampleListPolicy > parser_type;
+ typedef Parse_List_Container< ExampleListPolicy > container_type;
+
+ // mandatory constant in parser and container policy
+ static const size_type init_bytes = 0;
+
+ // Members needed in the parser and the container policy
+ size_type bytes (data_iterator i, state_type s) const;
+ size_type size (data_iterator i, state_type s) const;
+ void init (data_iterator i, state_type s) const;
+
+ // Members needed only in the container policy
+ void erase (data_iterator i, state_type s, iterator p) const;
+ void insert (data_iterator i, state_type s, iterator p) const;
+
+ struct iterator_policy
+ {
+ iterator setBegin (data_iterator i, state_type s);
+ iterator setEnd (data_iterator i, state_type s);
+ void setFromPosition (data_iterator i, state_type s, iterator p);
+ iterator next (data_iterator i, state_type s);
+ iterator raw (data_iterator i, state_type s) const;
+ };
+ };
+ \endcode
+
+ The list policy must be either default constructible or copy constructible. The policy may
+ contain arbitrary additional data members. However, their number and size should be kept at
+ an absolute minimum, since they will increase the size of the list parser.
+
+ If necessary, you may use a different policy in the container_type. The ListPolicy must
+ define the elements bytes(), size() and init(), the container policy needs all these and
+ additionally needs erase() and insert(). The container policy will also need the
+ element_type, parser_type and container_type typedefs.
+
+ \see \ref Parse_List
+ */
+ struct ExampleListPolicy
+ {
+ typedef PacketParserBase::data_iterator iterator;
+ typedef PacketParserBase::state_type state_type;
+ typedef PacketParserBase::size_type size_type;
+
+ typedef void element_type; ///< Type of list elements
+ /**< This is the parser used to parse the list elements. */
+ typedef void parser_type; ///< List parser type
+ /**< parser_type is the list parser used to parse a list of
+ this type,
+ e.g. <tt>senf::Parse_List<ExampleListPolicy></tt>. */
+ typedef void container_type; ///< Type of container wrapper
+ /**< This is the container wrapper of the list, e.g.
+ <tt>Parse_List_Container<ExampleListPolicy></tt>. The
+ container may however use a \e different policy, as
+ long as that policy is constructible from the parser
+ policy. */
+
+ static const size_type init_bytes = 0; ///< Size of a new list of this type
+ /**< Initial size which needs to be allocated to this type
+ of list */
+
+ size_type bytes(iterator i, state_type s) const; ///< Size of list in bytes
+ /**< Return the complete size of the list in
+ bytes. Depending on the type of list, this call may
+ need to completely traverse the list ... */
+
+ size_type size(iterator i, state_type s) const; ///< Number of elements in list
+ /**< Return the number of elements in the list. This
+ operation may be quite inefficient for some lists (the
+ list must be traversed to find that number. */
+
+ void init(iterator i, state_type s) const; ///< Initialize new list
+ /**< Called after init_size bytes have been allocated to
+ initialize the list. After init() is called, the list
+ is traversed to initialize any members (probably
+ none) */
+
+ void erase(iterator i, state_type s, iterator p) const; ///< Erase element from list
+ /**< Delete the list element at p from the List (i,s). When
+ this operation is called, the element is still part of
+ the list. This call must update the meta-data as
+ needed. The data will be removed after this call
+ returns. */
+
+ void insert(iterator i, state_type s, iterator p) const; ///< Insert element into list
+ /**< This is called after an element has been inserted at p
+ into the List (i,s) to update the meta-data. */
+
+ /** \brief Example of a list iterator policy. ONLY FOR EXPOSITION.
+
+ \see \ref ExampleListPolicy \n
+ \ref Parse_List
+ */
+ struct iterator_policy
+ {
+ iterator setBegin(iterator i, state_type s); ///< Initialize iterator to begin()
+ /**< Initialize the policy from the given List (i,s). Set
+ the iterator to the beginning iterator. Return
+ data_iterator to the first element.
+
+ \warning if the list is empty, the returned iterator
+ \e must be the same as the one returned by setEnd. */
+
+ iterator setEnd(iterator i, state_type s); ///< Initialize iterator to end()
+ /**< Initialize the policy from the given List (i,s). Set
+ the iterator to the end iterator. Return data_iterator
+ used to mark the end of the range. This may be a
+ special sentinel value (e.g. data().end()) if
+ needed. */
+
+ void setFromPosition(iterator i, state_type s, iterator p);
+ ///< Initialize iterator from the given raw position
+ /**< Set the iterator to the Element at raw position p. This
+ operation can potentially be very inefficient if the
+ list needs to be traversed from the beginning until the
+ iterator is found. */
+
+ iterator next(iterator i, state_type s); ///< Advance to next element
+ /**< given an iterator to an element, go to the next
+ element. */
+
+ iterator raw(iterator i, state_type s); ///< Return raw position of element
+ /**< Given the iterator state (i,s), return the raw iterator
+ to the datum. This will be i in almost all cases EXCEPT
+ if a special sentinel value is used as end() value. In
+ this case, this member must return the real position
+ after the last element. */
+ };
+
+ /** \brief Example of a list container policy. ONLY FOR EXPOSITION
+
+ \see \ref ExampleListPolicy \n
+ \ref Parse_List
+ */
+ struct container_policy
+ {
+ void init(iterator i, state_type s); ///< Initialize new container
+ void update(iterator i, state_type s); ///< Called before every container access
+ };
+ };
+
+}
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// mode: flyspell
+// mode: auto-fill
+// End:
template <class Policy> friend class Parse_List_Container;
};
- /** \brief Example of a list policy. ONLY FOR EXPOSITION.
-
- This class shows the interface which must be implemented by a list policy. It is not a list
- policy only a declaration of the interface:
- \code
- struct ExampleListPolicy
- {
- // optional typedefs used to simplify all other declarations
- typedef PacketParserBase::data_iterator data_iterator;
- typedef PacketParserBase::state_type state_type;
- typedef PacketParserBase::size_type size_type;
-
- // mandatory typedefs in the parser and container policy
- typedef ElementParser element_type;
- typedef Parse_List< ExampleListPolicy > parser_type;
- typedef Parse_List_Container< ExampleListPolicy > container_type;
-
- // mandatory constant in parser and container policy
- static const size_type init_bytes = 0;
-
- // Members needed in the parser and the container policy
- size_type bytes (data_iterator i, state_type s) const;
- size_type size (data_iterator i, state_type s) const;
- void init (data_iterator i, state_type s) const;
-
- // Members needed only in the container policy
- void erase (data_iterator i, state_type s, iterator p) const;
- void insert (data_iterator i, state_type s, iterator p) const;
-
- struct iterator_policy
- {
- iterator setBegin (data_iterator i, state_type s);
- iterator setEnd (data_iterator i, state_type s);
- void setFromPosition (data_iterator i, state_type s, iterator p);
- iterator next (data_iterator i, state_type s);
- iterator raw (data_iterator i, state_type s) const;
- };
- };
- \endcode
-
- If necessary, you may use a different policy in the container_type. The ListPolicy must
- define the elements bytes(), size() and init(), the container policy needs all these and
- additionally needs erase() and insert(). The container policy will also need the
- element_type, parser_type and container_type typedefs.
-
- \see \ref Parse_List
- */
- struct ExampleListPolicy
- {
- typedef PacketParserBase::data_iterator iterator;
- typedef PacketParserBase::state_type state_type;
- typedef PacketParserBase::size_type size_type;
-
- typedef void element_type; ///< Type of list elements
- /**< This is the parser used to parse the list elements. */
- typedef void parser_type; ///< List parser type
- /**< parser_type is the list parser used to parse a list of
- this type,
- e.g. <tt>senf::Parse_List<ExampleListPolicy></tt>. */
- typedef void container_type; ///< Type of container wrapper
- /**< This is the container wrapper of the list, e.g.
- <tt>Parse_List_Container<ExampleListPolicy></tt>. The
- container may however use a \e different policy, as
- long as that policy is constructible from the parser
- policy. */
-
- static const size_type init_bytes = 0; ///< Size of a new list of this type
- /**< Initial size which needs to be allocated to this type
- of list */
-
- size_type bytes(iterator i, state_type s) const; ///< Size of list in bytes
- /**< Return the complete size of the list in
- bytes. Depending on the type of list, this call may
- need to completely traverse the list ... */
-
- size_type size(iterator i, state_type s) const; ///< Number of elements in list
- /**< Return the number of elements in the list. This
- operation may be quite inefficient for some lists (the
- list must be traversed to find that number. */
-
- void init(iterator i, state_type s) const; ///< Initialize new list
- /**< Called after init_size bytes have been allocated to
- initialize the list. After init() is called, the list
- is traversed to initialize any members (probably
- none) */
-
- void erase(iterator i, state_type s, iterator p) const; ///< Erase element from list
- /**< Delete the list element at p from the List (i,s). When
- this operation is called, the element is still part of
- the list. This call must update the meta-data as
- needed. The data will be removed after this call
- returns. */
-
- void insert(iterator i, state_type s, iterator p) const; ///< Insert element into list
- /**< This is called after an element has been inserted at p
- into the List (i,s) to update the meta-data. */
-
- /** \brief Example of a list iterator policy. ONLY FOR EXPOSITION.
-
- \see \ref ExampleListPolicy \n
- \ref Parse_List
- */
- struct iterator_policy
- {
- iterator setBegin(iterator i, state_type s); ///< Initialize iterator to begin()
- /**< Initialize the policy from the given List (i,s). Set
- the iterator to the beginning iterator. Return
- data_iterator to the first element.
-
- \warning if the list is empty, the returned iterator
- \e must be the same as the one returned by setEnd. */
-
- iterator setEnd(iterator i, state_type s); ///< Initialize iterator to end()
- /**< Initialize the policy from the given List (i,s). Set
- the iterator to the end iterator. Return data_iterator
- used to mark the end of the range. This may be a
- special sentinel value (e.g. data().end()) if
- needed. */
-
- void setFromPosition(iterator i, state_type s, iterator p);
- ///< Initialize iterator from the given raw position
- /**< Set the iterator to the Element at raw position p. This
- operation can potentially be very inefficient if the
- list needs to be traversed from the beginning until the
- iterator is found. */
-
- iterator next(iterator i, state_type s); ///< Advance to next element
- /**< given an iterator to an element, go to the next
- element. */
-
- iterator raw(iterator i, state_type s); ///< Return raw position of element
- /**< Given the iterator state (i,s), return the raw iterator
- to the datum. This will be i in almost all cases EXCEPT
- if a special sentinel value is used as end() value. In
- this case, this member must return the real position
- after the last element. */
- };
-
- /** \brief Example of a list container policy. ONLY FOR EXPOSITION
-
- \see \ref ExampleListPolicy \n
- \ref Parse_List
- */
- struct container_policy
- {
- void init(iterator i, state_type s); ///< Initialize new container
- void update(iterator i, state_type s); ///< Called before every container access
- };
- };
-
/** \brief Parse_List container wrapper
This is the container wrapper used for list parsers. The container wrapper will stay valid
typedef Parse_List< detail::Parse_ListB_Policy<ElementParser,BytesParser> > parser;
};
+ /** \brief Define Parse_ListB field
+
+ This macro is a special helper to define a senf::Parse_ListB type field, a list of elements
+ of type \a elt_type (a parser type) directly preceded by a numeric size field of type \a
+ size_type (another parser type) giving the total number of bytes of the list (not the
+ element count).
+
+ \param[in] name field name
+ \param[in] elt_type list element type
+ \param[in] size_type size type
+ \hideinitializer
+ \ingroup packetparsermacros
+ */
+# define SENF_PARSER_LIST_B(name, elt_type, size_type) \
+ typedef senf::Parse_ListB<elt_type, size_type>::parser BOOST_PP_CAT(name, _list_t); \
+ SENF_PARSER_FIELD( name, BOOST_PP_CAT(name, _list_t) )
+
}
///////////////////////////////hh.e////////////////////////////////////////
typedef Parse_List< detail::Parse_ListN_Policy<ElementParser,SizeParser> > parser;
};
+ /** \brief Define Parse_ListN field
+
+ This macro is a special helper to define a senf::Parse_ListN type field, a list of elements
+ of type \a elt_type (a parser type) directly preceded by a numeric size field of type \a
+ size_type (another parser type).
+
+ \param[in] name field name
+ \param[in] elt_type list element type
+ \param[in] size_type size type
+ \hideinitializer
+ \ingroup packetparsermacros
+ */
+# define SENF_PARSER_LIST_N(name, elt_type, size_type) \
+ typedef senf::Parse_ListN<elt_type, size_type>::parser BOOST_PP_CAT(name, _list_t); \
+ SENF_PARSER_FIELD( name, BOOST_PP_CAT(name, _list_t) )
+
}
///////////////////////////////hh.e////////////////////////////////////////
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2007
+// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
+// Kompetenzzentrum fuer NETwork research (NET)
+// Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+/** \file
+ \brief ParseVariant non-inline template implementation */
+
+#include "ParseVariant.ih"
+
+// Custom includes
+#include <algorithm>
+
+#define prefix_
+///////////////////////////////ct.p////////////////////////////////////////
+
+template <class VariantPolicy, SENF_PARSE_VARIANT_TPL_ARGS(class P)>
+template <unsigned N>
+prefix_ void senf::Parse_Variant<VariantPolicy,SENF_PARSE_VARIANT_TPL_ARGS(P)>::init()
+{
+ unsigned oldSize( bytes() );
+ typedef typename boost::mpl::at<parsers, boost::mpl::int_<N> >::type NewParser;
+
+ if (oldSize < senf::init_bytes<NewParser>::value) {
+ data_iterator j (i());
+ std::advance(j, oldSize);
+ std::fill(i(), j, 0u);
+ safe_data_iterator safe_i (*this);
+ data().insert(j, senf::init_bytes<NewParser>::value - oldSize, 0u);
+ VariantPolicy::variant(N, safe_i, state());
+ NewParser( VariantPolicy::begin(safe_i, state()), state() ).init();
+ } else {
+ data_iterator j (i());
+ std::advance(j, senf::init_bytes<NewParser>::value);
+ data().erase(j, boost::next(i(), oldSize));
+ std::fill(i(), j, 0u);
+ VariantPolicy::variant(N, i(), state());
+ NewParser(VariantPolicy::begin(i(), state()), state()).init();
+ }
+}
+
+///////////////////////////////ct.e////////////////////////////////////////
+#undef prefix_
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2007
+// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
+// Kompetenzzentrum fuer NETwork research (NET)
+// Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+/** \file
+ \brief ParseVariant inline template implementation */
+
+#include "ParseVariant.ih"
+
+// Custom includes
+#include <boost/mpl/size.hpp>
+
+#define prefix_ inline
+///////////////////////////////cti.p///////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////
+// senf::Parse_Variant<VariantPolicy,SENF_PARSE_VARIANT_TPL_ARGS(P)>
+
+template <class VariantPolicy, SENF_PARSE_VARIANT_TPL_ARGS(class P)>
+prefix_ senf::Parse_Variant<VariantPolicy,SENF_PARSE_VARIANT_TPL_ARGS(P)>::
+Parse_Variant(data_iterator i, state_type s)
+ : PacketParserBase(i,s)
+{}
+
+template <class VariantPolicy, SENF_PARSE_VARIANT_TPL_ARGS(class P)>
+prefix_ senf::Parse_Variant<VariantPolicy,SENF_PARSE_VARIANT_TPL_ARGS(P)>::
+Parse_Variant(VariantPolicy policy, data_iterator i, state_type s)
+ : PacketParserBase(i,s), VariantPolicy(policy)
+{}
+
+template <class VariantPolicy, SENF_PARSE_VARIANT_TPL_ARGS(class P)>
+prefix_ senf::PacketParserBase::size_type
+senf::Parse_Variant<VariantPolicy,SENF_PARSE_VARIANT_TPL_ARGS(P)>::bytes()
+ const
+{
+ return detail::VariantBytes< Parse_Variant, boost::mpl::size<parsers>::value - 1 >
+ ::bytes(*this, variant()) + VariantPolicy::bytes(i(),state());
+}
+
+template <class VariantPolicy, SENF_PARSE_VARIANT_TPL_ARGS(class P)>
+prefix_ void
+senf::Parse_Variant<VariantPolicy,SENF_PARSE_VARIANT_TPL_ARGS(P)>::init()
+{
+ VariantPolicy::variant(0,i(),state());
+ get<0>().init();
+}
+
+template <class VariantPolicy, SENF_PARSE_VARIANT_TPL_ARGS(class P)>
+prefix_ unsigned senf::Parse_Variant<VariantPolicy,SENF_PARSE_VARIANT_TPL_ARGS(P)>::variant()
+ const
+{
+ return VariantPolicy::variant(i(),state());
+}
+
+template <class VariantPolicy, SENF_PARSE_VARIANT_TPL_ARGS(class P)>
+template <unsigned N>
+prefix_ typename boost::mpl::at<
+ typename senf::Parse_Variant<VariantPolicy,SENF_PARSE_VARIANT_TPL_ARGS(P)>::parsers,
+ boost::mpl::int_<N> >::type
+senf::Parse_Variant<VariantPolicy,SENF_PARSE_VARIANT_TPL_ARGS(P)>::get()
+ const
+{
+ BOOST_ASSERT( variant() == N );
+ return typename boost::mpl::at<parsers, boost::mpl::int_<N> >::type(
+ VariantPolicy::begin(i(), state()), state() );
+}
+
+/////////////////////////////////////////////////////////////////////////
+// senf::detail::VariantBytes<Variant,N>
+
+template <class Variant, unsigned N>
+prefix_ senf::PacketParserBase::size_type
+senf::detail::VariantBytes<Variant,N>::bytes(Variant const & v, unsigned n)
+{
+ if (n == N)
+ return senf::bytes(v.template get<N>());
+ else
+ return VariantBytes<Variant, N-1>::bytes(v, n);
+}
+
+template <class Variant>
+prefix_ senf::PacketParserBase::size_type
+senf::detail::VariantBytes<Variant,0>::bytes(Variant const & v, unsigned n)
+{
+ return senf::bytes(v.template get<0>());
+}
+
+///////////////////////////////cti.e///////////////////////////////////////
+#undef prefix_
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2007
+// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
+// Kompetenzzentrum fuer NETwork research (NET)
+// Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+namespace senf {
+
+ struct ExampleVariantPolicy
+ {
+ // optional typedefs used to simplify all other declarations
+ 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;
+ data_iterator begin(data_iterator i, state_type s) const;
+
+ unsigned variant (data_iterator i, state_type s) const;
+ void variant (unsigned v, data_iterator i, state_type s);
+ };
+
+}
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// mode: flyspell
+// mode: auto-fill
+// End:
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2007
+// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
+// Kompetenzzentrum fuer NETwork research (NET)
+// Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+/** \file
+ \brief ParseVariant public header */
+
+#ifndef HH_ParseVariant_
+#define HH_ParseVariant_ 1
+
+#ifndef HH_Packets_
+#error "Don't include 'ParseVariant.hh' directly, include 'Packets.hh'"
+#endif
+
+// Custom includes
+#include <boost/mpl/vector.hpp>
+#include <boost/mpl/at.hpp>
+#include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
+#include <boost/preprocessor/repetition/enum_params.hpp>
+#include <boost/preprocessor/seq/for_each.hpp>
+#include "PacketParser.hh"
+
+//#include "ParseVariant.mpp"
+#include "ParseVariant.ih"
+///////////////////////////////hh.p////////////////////////////////////////
+
+namespace senf {
+
+# ifndef SENF_LIMIT_PARSER_VARIANT
+# define SENF_LIMIT_PARSE_VARIANT 10
+# endif
+
+# 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 )
+
+ template <class VariantPolicy, SENF_PARSE_VARIANT_TPL_ARGS_DFL(class P)>
+ class Parse_Variant
+ : public PacketParserBase, private VariantPolicy
+ {
+ typedef boost::mpl::vector< SENF_PARSE_VARIANT_TPL_ARGS(P) > parsers;
+
+ public:
+ Parse_Variant(data_iterator i, state_type s);
+ Parse_Variant(VariantPolicy policy, data_iterator i, state_type s);
+
+ size_type bytes() const;
+ void init();
+
+ static const size_type init_bytes =
+ senf::init_bytes<P0>::value + VariantPolicy::init_bytes;
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ unsigned variant() const;
+
+ template <unsigned N>
+ typename boost::mpl::at< parsers, boost::mpl::int_<N> >::type get() const;
+
+ template <unsigned N>
+ void init();
+
+ private:
+ };
+
+ template <class ChooserType, unsigned Distance, SENF_PARSE_VARIANT_TPL_ARGS_DFL(class P)>
+ struct Parse_Variant_Direct
+ {
+ typedef Parse_Variant< detail::Parse_Variant_Direct<ChooserType, Distance>,
+ SENF_PARSE_VARIANT_TPL_ARGS(P) > parser;
+ };
+
+# define SENF_PARSER_VARIANT_(r, data, elem) ,elem
+
+# define SENF_PARSER_VARIANT(name, chooser, types) \
+ typedef senf::Parse_Variant_Direct< \
+ BOOST_PP_CAT(chooser, _t), \
+ SENF_PARSER_CURRENT_FIXED_OFFSET() - SENF_PARSER_FIXED_OFFSET(chooser) \
+ BOOST_PP_SEQ_FOR_EACH( SENF_PARSER_VARIANT_, _, types ) \
+ >::parser BOOST_PP_CAT(name, _variant_t); \
+ SENF_PARSER_FIELD( name, BOOST_PP_CAT(name, _variant_t) )
+
+# define SENF_PARSER_PRIVATE_VARIANT(name, chooser, types) \
+ typedef senf::Parse_Variant_Direct< \
+ BOOST_PP_CAT(chooser, _t), \
+ SENF_PARSER_CURRENT_FIXED_OFFSET() - SENF_PARSER_FIXED_OFFSET(chooser) \
+ BOOST_PP_SEQ_FOR_EACH( SENF_PARSER_VARIANT_, _, types ) \
+ >::parser BOOST_PP_CAT(name, _variant_t); \
+ SENF_PARSER_PRIVATE_FIELD( name, BOOST_PP_CAT(name, _variant_t) )
+
+}
+
+///////////////////////////////hh.e////////////////////////////////////////
+#endif
+#if !defined(HH_Packets__decls_) && !defined(HH_ParseVariant_i_)
+#define HH_ParseVariant_i_
+//#include "ParseVariant.cci"
+#include "ParseVariant.ct"
+#include "ParseVariant.cti"
+#endif
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2007
+// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
+// Kompetenzzentrum fuer NETwork research (NET)
+// Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+/** \file
+ \brief ParseVariant internal header */
+
+#ifndef IH_ParseVariant_
+#define IH_ParseVariant_ 1
+
+// Custom includes
+#include "PacketParser.hh"
+
+///////////////////////////////ih.p////////////////////////////////////////
+
+namespace senf {
+namespace detail {
+
+ template <class Variant, unsigned N>
+ struct VariantBytes {
+ static PacketParserBase::size_type bytes(Variant const & v, unsigned n);
+ };
+
+ template <class Variant>
+ struct VariantBytes<Variant,0> {
+ static PacketParserBase::size_type bytes(Variant const & v, unsigned n);
+ };
+
+ template <class ChooserType, unsigned Distance>
+ struct Parse_Variant_Direct
+ {
+ 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 chooser(i,s).value();
+ }
+
+ void variant(unsigned v, data_iterator i, state_type s) {
+ chooser(i,s).value(v);
+ }
+ };
+
+}}
+
+///////////////////////////////ih.e////////////////////////////////////////
+#endif
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2007
+// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
+// Kompetenzzentrum fuer NETwork research (NET)
+// Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+/** \file
+ \brief ParseVariant.test unit tests */
+
+//#include "ParseVariant.test.hh"
+//#include "ParseVariant.test.ih"
+
+// Custom includes
+#include "Packets.hh"
+
+#include <boost/test/auto_unit_test.hpp>
+#include <boost/test/test_tools.hpp>
+
+#define prefix_
+///////////////////////////////cc.p////////////////////////////////////////
+
+BOOST_AUTO_UNIT_TEST(parseVariant)
+{
+ typedef senf::Parse_Array<10, senf::Parse_UInt8> Array10;
+ typedef senf::Parse_Variant_Direct< senf::Parse_UInt8, 1,
+ senf::VoidPacketParser,
+ Array10,
+ senf:: Parse_UInt32
+ >::parser Variant;
+
+ unsigned char data[] = { 0x01, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
+ 0x19, 0x1A, 0x1B };
+ senf::DataPacket p (senf::DataPacket::create(data));
+ {
+ Variant v ( boost::next(p.data().begin()), & p.data() );
+ BOOST_REQUIRE_EQUAL( v.variant(), 1u );
+ BOOST_CHECK_EQUAL( senf::bytes(v), 10u );
+ BOOST_CHECK_EQUAL_COLLECTIONS( v.get<1>().begin(), v.get<1>().end(),
+ data+1, data+11 );
+ v.init();
+ // The container size should not change in this case but now variant should be 0 ...
+ BOOST_REQUIRE_EQUAL( p.data().size(), 11u );
+ BOOST_REQUIRE_EQUAL( v.variant(), 0u );
+ BOOST_CHECK_EQUAL( senf::bytes(v), 0u );
+
+ v.init<2>();
+ // v invalidated
+ }
+ {
+ Variant v ( boost::next(p.data().begin()), & p.data() );
+
+ BOOST_CHECK_EQUAL( p.data()[0], 2u );
+ BOOST_REQUIRE_EQUAL( v.variant(), 2u );
+ BOOST_CHECK_EQUAL( senf::bytes(v), 4u );
+
+ unsigned char data2[] = { 0x02, 0x00, 0x00, 0x00, 0x00,
+ 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
+ 0x19, 0x1A, 0x1B };
+ BOOST_CHECK_EQUAL_COLLECTIONS( p.data().begin(), p.data().end(),
+ data2, data2+sizeof(data2) );
+ BOOST_CHECK_EQUAL( v.get<2>().value(), 0u );
+ BOOST_CHECK_EQUAL( p.data().size(), 15u );
+ p.data()[4] = 0x01u;
+ BOOST_CHECK_EQUAL( v.get<2>().value(), 1u );
+ };
+}
+
+namespace {
+
+ struct SubParser : public senf::PacketParserBase
+ {
+# include SENF_FIXED_PARSER()
+
+ SENF_PARSER_FIELD( foo, senf::Parse_UInt32 );
+ SENF_PARSER_FIELD( bar, senf::Parse_Int16 );
+
+ SENF_PARSER_FINALIZE(SubParser);
+ };
+
+ struct TestParser : public senf::PacketParserBase
+ {
+# include SENF_PARSER()
+
+ SENF_PARSER_SKIP_BITS( 4 );
+ SENF_PARSER_PRIVATE_BITFIELD( type_, 4, unsigned );
+ SENF_PARSER_PRIVATE_VARIANT( content_, type_, (senf::VoidPacketParser)(SubParser) );
+
+ bool hasContent() const { return content_().variant() == 1; }
+ void hasContent(bool v) const { if (v) content_().init<1>(); else content_().init<0>(); }
+ SubParser content() const { return content_().get<1>(); }
+
+ SENF_PARSER_FINALIZE(TestParser);
+ };
+
+}
+
+BOOST_AUTO_UNIT_TEST(parseVariantMacro)
+{
+ senf::DataPacket p (senf::DataPacket::create(senf::init_bytes<TestParser>::value));
+
+ {
+ TestParser v (p.data().begin(), & p.data());
+
+ BOOST_CHECK( ! v.hasContent() );
+ BOOST_CHECK_EQUAL( senf::bytes(v), 1u );
+ v.hasContent(true);
+ }
+ {
+ TestParser v (p.data().begin(), & p.data());
+ BOOST_CHECK( v.hasContent() );
+ BOOST_CHECK_EQUAL( senf::bytes(v), 7u );
+ BOOST_CHECK_EQUAL( v.content().foo(), 0u );
+ }
+}
+
+///////////////////////////////cc.e////////////////////////////////////////
+#undef prefix_
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2007
+// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
+// Kompetenzzentrum fuer NETwork research (NET)
+// Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+namespace senf {
+
+ /** \brief Example vector sizer. ONLY FOR EXPOSITION
+
+ This class shows the interface which must be implemented by a vector sizer policy. It is not
+ a vector sizer, it is only a declaration of the interface:
+ \code
+ struct ExampleVectorPolicy
+ {
+ // optional typedefs used to simplify all other declarations
+ typedef PacketParserBase::size_type size_type;
+ typedef PacketParserBase::data_iterator iterator;
+ typedef PacketParserBase::state_type state_type;
+
+ // mandatory members
+ static const size_type init_bytes = 0;
+ size_type size (iterator i, state_type s) const;
+ void size (iterator i, state_type s, size_type v) const;
+ iterator begin (iterator i, state_type s) const;
+ size_type bytes (iterator i, state_type s) const;
+ void init (iterator i, state_type s) const;
+ };
+ \endcode
+
+ A sizer may if needed define additional data members.
+ */
+ struct ExampleVectorPolicy
+ {
+ typedef PacketParserBase::size_type size_type;
+ typedef PacketParserBase::data_iterator iterator;
+ typedef PacketParserBase::state_type state_type;
+
+ static const size_type init_bytes = 0; ///< Size of a new vector of this size
+ /**< Initial size which needs to be allocated to this type
+ of list */
+
+ size_type size (iterator i, state_type s) const; ///< Get current vector size
+ /**< Return the current number of elements in the
+ vector. */
+ void size (iterator i, state_type s, size_type v) const; ///< Change vector size
+ /**< Set the size of the vector to \a v. */
+ iterator begin (iterator i, state_type s) const;
+ ///< Return data_iterator to first element
+ /**< The returned data_iterator must point to the beginning
+ of the first vector element. The last iterator can than
+ automatically be calculated from the fixed element size
+ and the number of vector elements. */
+ size_type bytes (iterator i, state_type s) const; ///< Bytes taken by the vector size
+ /**< Return the additional size which needs to be added to
+ the size of the vector data (calculated form \c size()
+ * <em>ElementType::fixed_bytes</em>) to get the size of
+ the complete vector. This may be zero if the size is
+ not considered part of the vector. */
+ void init (iterator i, state_type s) const; ///< Initialize new vector
+ /** Called to initialize a new vector after allocating
+ init_bytes number of bytes for the vector. */
+ };
+
+}
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// mode: flyspell
+// mode: auto-fill
+// End:
detail::Parse_VectorN_Sizer<SizeParser> > parser;
};
- /** \brief Example vector sizer. ONLY FOR EXPOSITION
-
- This class shows the interface which must be implemented by a vector sizer policy. It is not
- a vector sizer, it is only a declaration of the interface:
- \code
- struct ExampleVectorPolicy
- {
- // optional typedefs used to simplify all other declarations
- typedef PacketParserBase::size_type size_type;
- typedef PacketParserBase::data_iterator iterator;
- typedef PacketParserBase::state_type state_type;
-
- // mandatory members
- static const size_type init_bytes = 0;
- size_type size (iterator i, state_type s) const;
- void size (iterator i, state_type s, size_type v) const;
- iterator begin (iterator i, state_type s) const;
- size_type bytes (iterator i, state_type s) const;
- void init (iterator i, state_type s) const;
- };
- \endcode
-
- A sizer may if needed define additional data members.
+ /** \brief Define Parse_VectorN field
+
+ This macro is a special helper to define a senf::Parse_VectorN type field, a vector of
+ elements of type \a elt_type (a parser) directly preceded by a numeric size field of type \a
+ size_type (another parser).
+
+ \param[in] name field name
+ \param[in] elt_type vector element type
+ \param[in] size_type size type
+ \hideinitializer
+ \ingroup packetparsermacros
*/
- struct ExampleVectorPolicy
- {
- typedef PacketParserBase::size_type size_type;
- typedef PacketParserBase::data_iterator iterator;
- typedef PacketParserBase::state_type state_type;
-
- static const size_type init_bytes = 0; ///< Size of a new vector of this size
- /**< Initial size which needs to be allocated to this type
- of list */
-
- size_type size (iterator i, state_type s) const; ///< Get current vector size
- /**< Return the current number of elements in the
- vector. */
- void size (iterator i, state_type s, size_type v) const; ///< Change vector size
- /**< Set the size of the vector to \a v. */
- iterator begin (iterator i, state_type s) const;
- ///< Return data_iterator to first element
- /**< The returned data_iterator must point to the beginning
- of the first vector element. The last iterator can than
- automatically be calculated from the fixed element size
- and the number of vector elements. */
- size_type bytes (iterator i, state_type s) const; ///< Size of vector parser
- /**< Return the size of the complete vector in bytes. This
- is not necessarily the same as \c size() * \e
- fixed_element_bytes. */
- void init (iterator i, state_type s) const; ///< Initialize new vector
- /** Called to initialize a new vector after allocating
- init_bytes number of bytes for the vector. */
- };
+# define SENF_PARSER_VEC_N(name, elt_type, size_type) \
+ typedef senf::Parse_VectorN<elt_type, size_type>::parser BOOST_PP_CAT(name, _vec_t); \
+ SENF_PARSER_FIELD( name, BOOST_PP_CAT(name, _vec_t) )
/** \brief Parse_Vector container wrapper