Skip to content
Snippets Groups Projects
Commit 8684f3f4 authored by g0dil's avatar g0dil
Browse files

Packets: Add container helper macros

Packets: Move example policies into .dox files
Packets: Implement variant parser
parent 119825b7
No related branches found
No related tags found
No related merge requests found
......@@ -15,5 +15,5 @@ SENFSCons.Lib(env, library = 'Packets_MPEGDVBBundle', sources = sources[0],
LIBS = ['Packets', 'Socket', 'Utils'], no_includes = 1)
SENFSCons.Doxygen(env, extra_sources = [
env.Dia2Png("TLV.dia", DIA2PNGMAXWIDTH = 600)
env.Dia2Png("TLV.dia")
])
No preview for this file type
......@@ -95,6 +95,21 @@ namespace senf {
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////////////////////////////////////////
......
......@@ -214,6 +214,9 @@
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 ""
......@@ -580,6 +583,8 @@
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)
......@@ -595,6 +600,7 @@
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)
......@@ -612,6 +618,7 @@
\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)
......@@ -626,6 +633,7 @@
labeled with \ref SENF_PARSER_LABEL()
\param[in] name label name
\hideinitializer
*/
#define SENF_PARSER_LABEL(name)
......@@ -635,9 +643,29 @@
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
......@@ -662,6 +690,8 @@
#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)
......
......@@ -368,6 +368,18 @@
# 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) \
......
// $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
};
};
}
// 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:
......@@ -103,156 +103,6 @@ namespace senf {
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
......
......@@ -65,6 +65,23 @@ namespace senf {
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////////////////////////////////////////
......
......@@ -55,6 +55,22 @@ namespace senf {
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////////////////////////////////////////
......
// $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_
// 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:
// $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_
// 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:
// $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);
};
}
// 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:
// $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
// 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:
// $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
// 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:
// $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_
// 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:
// $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. */
};
}
// 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:
......@@ -137,59 +137,21 @@ namespace senf {
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
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment