X-Git-Url: http://g0dil.de/git?a=blobdiff_plain;f=Packets%2FListParser.hh;h=8807578ed0217016cb1450891e082a42b5dcea05;hb=b89e3166f7680755683dccee5e48cb3a820185c0;hp=d0d30e88ece6966a470f62981cbd357e4bbc3306;hpb=a1001797645cc68c869ef296f5e9ba13aa8e80c4;p=senf.git diff --git a/Packets/ListParser.hh b/Packets/ListParser.hh index d0d30e8..8807578 100644 --- a/Packets/ListParser.hh +++ b/Packets/ListParser.hh @@ -1,8 +1,8 @@ // $Id$ // -// Copyright (C) 2007 -// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) -// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Copyright (C) 2007 +// Fraunhofer Institute for Open Communication Systems (FOKUS) +// Competence Center NETwork research (NET), St. Augustin, GERMANY // Stefan Bund // // This program is free software; you can redistribute it and/or modify @@ -23,8 +23,8 @@ /** \file \brief ListParser public header */ -#ifndef HH_ListParser_ -#define HH_ListParser_ 1 +#ifndef HH_SENF_Packets_ListParser_ +#define HH_SENF_Packets_ListParser_ 1 // Custom includes #include @@ -35,8 +35,7 @@ namespace senf { - namespace detail { template - class ListParser_Iterator; } + namespace detail { template class ListParser_Iterator; } template class ListParser_Container; @@ -45,26 +44,40 @@ namespace senf { A List is a sequential collection of elements. The element type is given as an arbitrary parser. The list is more flexible than a vector: It is not limited to fixed-size elements - and it might not have direct access to the size of the collection. + and it might not have direct access to the size of the collection. The cost is however, that a List is only a model of an STL forward sequence. The parser provides a reduced interface to this sequence, the container wrapper provides the complete interface. - Pare_List makes use of a policy template argument, \a ListPolicy, to customize the way the - list is laid out. This policy is given quite some freedom in the list - implementation. It is however important, that list elements always follow each other - without padding (if padding is needed, it needs to be part of the element parser). + ListParser makes use of a policy template argument, \a ListPolicy, to customize the way the + list is laid out. This policy is given quite some freedom in the list implementation. It is + however important, that list elements always follow each other without padding (if + padding is needed, it needs to be part of the element parser). + + You will normally not instantiate ListParser directly, you will use the \ref + SENF_PARSER_LIST() helper macro. + + Some basic list access methods are defined as parser members. To access the complete list + API however you will need to instantiate a container wrapper for the list. See \ref + packet_usage_fields_collection. + + \see + \ref How to access \ref packet_usage_fields_collection + SENF_PARSER_LIST() macro used to define list fields \n + ListParser_Container list container wrapper API \n + ExampleListPolicy - \see ExampleListPolicy \ingroup parsecollection */ template - class ListParser + class ListParser : public PacketParserBase, private ListPolicy { public: + typedef ListPolicy policy; + ListParser(data_iterator i, state_type s); ListParser(ListPolicy policy, data_iterator i, state_type s); ///< Additional policy specific constructor @@ -80,20 +93,14 @@ namespace senf { // Container interface typedef typename ListPolicy::element_type value_type; - typedef detail::ListParser_Iterator< - value_type, typename ListPolicy::iterator_policy > iterator; - typedef iterator const_iterator; typedef typename ListPolicy::container_type container; size_type size() const; bool empty() const; - - iterator begin() const; - iterator end() const; value_type front() const; value_type back() const; - + template void push_back (Value value, size_type n=1) const; void push_back_space (size_type n=1) const; template void push_front (Value value, size_type n=1) const; @@ -101,6 +108,9 @@ namespace senf { void resize (size_type n) const; template void resize (size_type n, Value value) const; + static ListParser & get(ListPolicy & p); + static ListParser const & get(ListPolicy const & p); + private: template friend class ListParser_Container; }; @@ -114,7 +124,7 @@ namespace senf { the vector in the packet data). The vector container wrapper provides a complete STL random-access sequence interface. - + \code SomePacket p (...); SomePacket::aListCollection_t::container c (p->aListCollection()); @@ -131,16 +141,16 @@ namespace senf { /////////////////////////////////////////////////////////////////////////// // Types + typedef ListPolicy policy; typedef typename ListPolicy::parser_type parser_type; typedef PacketParserBase::data_iterator data_iterator; typedef PacketParserBase::size_type size_type; typedef PacketParserBase::difference_type difference_type; typedef typename ListPolicy::element_type value_type; - typedef detail::ListParser_Iterator< - value_type, typename ListPolicy::iterator_policy> iterator; + typedef detail::ListParser_Iterator iterator; typedef iterator const_iterator; typedef PacketParserBase::state_type state_type; - + /////////////////////////////////////////////////////////////////////////// ///\name Structors and default members ///@{ @@ -152,7 +162,7 @@ namespace senf { ListParser_Container(parser_type const & list); ~ListParser_Container(); - + ///@} /////////////////////////////////////////////////////////////////////////// @@ -209,21 +219,111 @@ namespace senf { size_type bytes() const; void init() const; - + ///@} private: + friend class detail::ListParser_Iterator; + state_type state_; size_type i_; }; + /** \brief Define ListParser field + + This macro is a special helper to define a senf::ListParser type field, a list of elements + of type \a elt_type (a parser) which size is determined by \a size. + + \code + // The size field should be declared private or read-only (size is accessible via the list) + SENF_PARSER_PRIVATE_FIELD ( list_size_, senf::UInt16Parser ); + // Define the list + SENF_PARSER_LIST ( list, list_size_, EltParser ); + \endcode + Here \c EltParser can be an arbitrary parser and need not have a fixed size. + + \warning Realize, that the \a size field is controlled by the list parser. This field + should therefore be declared either read-only or private and must be changed only via + the list parser. + + Further additional tags are supported which modify the type of list created: + + + + + + + + + +
\c bytes(\a size)\a size gives the size of the list in bytes not the + number of contained elements
\c packetSize()Use the size of the packet to get the list size. The + list will occupy all space up to the end of the packet.
\c transform(\a transform, \a size)The \a transform is applied to the \a + size value, the value is not used directly
\c transform(\a transform, \c bytes(\a size))The \a transform is applied to + the \a size value. The value is then interpreted containing the list size in bytes not + number of elements
+ + The optional \a transform is a class with the following layout + \code + struct MyTransform + { + typedef ... value_type; + static value_type get(other_type v); + static other_type set(value_type v); + }; + \endcode + + \c other_type is \a size ::\c value_type, the type of the value returned by the \a size + field, whereas the \c value_type typedef is the arbitrary return type of the transform. + + The tags are applied to the \a size parameter: + \code + SENF_PARSER_LIST ( list, transform(MyTransform, list_size_), EltParser ); + \endcode + + \warning There are some caveats when working with \c bytes() type lists: + \li You may only change the size of a contained element from a container wrapper. + \li While you hold a container wrapper, only access the packet through this wrapper + or a nested wrapper either for reading or writing. + + \warning If lists are nested, you need to allocate a container wrapper for each level and + may only access the packet through the lowest-level active container wrapper. + + \implementation These restrictions are necessary to ensure correct recalculation of the + bytes field. For more info, see the comments in \ref ListBParser.ih + + \param[in] name field name + \param[in] size name of field giving the list size + \param[in] elt_type list element type + + \see + How to use \ref packet_usage_fields_collection \n + senf::ListParser the list parser API for list field access + senf::ListParser_Container the list parser container API for list field access + + \hideinitializer + \ingroup packetparsermacros + */ +# define SENF_PARSER_LIST(name, size, elt_type) \ + SENF_PARSER_LIST_I(public, name, size, elt_type) + + /** \brief Define private ListParser field + + \see \ref SENF_PARSER_LIST() + + \hideinitializer + \ingroup packetparsermacros + */ +# define SENF_PARSER_PRIVATE_LIST(name, size, elt_type) \ + SENF_PARSER_LIST_I(private, name, size, elt_type) + } ///////////////////////////////hh.e//////////////////////////////////////// #endif -#if !defined(HH_Packets__decls_) && !defined(HH_ListParser_i_) -#define HH_ListParser_i_ +#if !defined(HH_SENF_Packets_Packets__decls_) && !defined(HH_SENF_Packets_ListParser_i_) +#define HH_SENF_Packets_ListParser_i_ //#include "ListParser.cci" #include "ListParser.ct" #include "ListParser.cti"