4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
6 // The contents of this file are subject to the Fraunhofer FOKUS Public License
7 // Version 1.0 (the "License"); you may not use this file except in compliance
8 // with the License. You may obtain a copy of the License at
9 // http://senf.berlios.de/license.html
11 // The Fraunhofer FOKUS Public License Version 1.0 is based on,
12 // but modifies the Mozilla Public License Version 1.1.
13 // See the full license text for the amendments.
15 // Software distributed under the License is distributed on an "AS IS" basis,
16 // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
17 // for the specific language governing rights and limitations under the License.
19 // The Original Code is Fraunhofer FOKUS code.
21 // The Initial Developer of the Original Code is Fraunhofer-Gesellschaft e.V.
22 // (registered association), Hansastraße 27 c, 80686 Munich, Germany.
23 // All Rights Reserved.
26 // Stefan Bund <g0dil@berlios.de>
29 \brief ListParser public header */
31 #ifndef HH_SENF_Packets_ListParser_
32 #define HH_SENF_Packets_ListParser_ 1
35 #include <boost/utility.hpp>
36 #include "PacketParser.hh"
38 //#include "ListParser.mpp"
39 //-/////////////////////////////////////////////////////////////////////////////////////////////////
43 namespace detail { template <class Container> class ListParser_Iterator; }
45 template <class ListPolicy>
46 class ListParser_Container;
48 /** \brief Arbitrary sequential element collection
50 A List is a sequential collection of elements. The element type is given as an arbitrary
51 parser. The list is more flexible than a vector: It is not limited to fixed-size elements
52 and it might not have direct access to the size of the collection.
54 The cost is however, that a List is only a model of an STL forward sequence. The parser
55 provides a reduced interface to this sequence, the container wrapper provides the complete
58 ListParser makes use of a policy template argument, \a ListPolicy, to customize the way the
59 list is laid out. This policy is given quite some freedom in the list implementation. It is
60 however important, that list elements <em>always follow each other without padding</em> (if
61 padding is needed, it needs to be part of the element parser).
63 You will normally not instantiate ListParser directly, you will use the \ref
64 SENF_PARSER_LIST() helper macro.
66 Some basic list access methods are defined as parser members. To access the complete list
67 API however you will need to instantiate a container wrapper for the list. See \ref
68 packet_usage_fields_collection.
71 How to access \ref packet_usage_fields_collection \n
72 SENF_PARSER_LIST() macro used to define list fields \n
73 ListParser_Container list container wrapper API \n
76 \ingroup parsecollection
78 template <class ListPolicy>
80 : public PacketParserBase,
84 typedef ListPolicy policy;
86 ListParser(data_iterator i, state_type s);
87 ListParser(ListPolicy policy, data_iterator i, state_type s);
88 ///< Additional policy specific constructor
89 /**< This constructor may be used, if the policy needs
90 additional parameters. */
92 size_type bytes() const;
95 static const size_type init_bytes = ListPolicy::init_bytes;
97 //-////////////////////////////////////////////////////////////////////////
98 // Container interface
100 typedef typename ListPolicy::element_type value_type;
101 typedef typename ListPolicy::container_type container;
103 size_type size() const;
106 value_type front() const;
107 value_type back() const;
109 template <class Value> void push_back (Value const & value, size_type n=1) const;
110 value_type push_back_space (size_type n=1) const;
111 template <class Value> void push_front (Value const & value, size_type n=1) const;
112 value_type push_front_space (size_type n=1) const;
113 void resize (size_type n) const;
114 template <class Value> void resize (size_type n, Value value) const;
116 static ListParser & get(ListPolicy & p);
117 static ListParser const & get(ListPolicy const & p);
120 template <class Policy> friend class ListParser_Container;
123 /** \brief ListParser container wrapper
125 This is the container wrapper used for list parsers. The container wrapper will stay valid
126 after changing the collection. However the container still depends on the packet and will be
127 invalidated if the Packet is deallocated or if the packet size is changed from without the
128 container wrapper (more precisely, it is invalidated if the insertion/deletion happens before
129 the vector in the packet data).
131 The vector container wrapper provides a complete STL random-access sequence interface.
135 SomePacket::aListCollection_t::container c (p->aListCollection());
136 c.insert(c.begin(), ... );
141 template <class ListPolicy>
142 class ListParser_Container
146 //-////////////////////////////////////////////////////////////////////////
149 typedef ListPolicy policy;
150 typedef typename ListPolicy::parser_type parser_type;
151 typedef PacketParserBase::data_iterator data_iterator;
152 typedef PacketParserBase::size_type size_type;
153 typedef PacketParserBase::difference_type difference_type;
154 typedef typename ListPolicy::element_type value_type;
155 typedef detail::ListParser_Iterator<ListParser_Container> iterator;
156 typedef iterator const_iterator;
157 typedef PacketParserBase::state_type state_type;
159 //-////////////////////////////////////////////////////////////////////////
160 ///\name Structors and default members
163 // no default constructor
165 // default destructor
166 // conversion constructors
168 ListParser_Container(parser_type const & list);
169 ~ListParser_Container();
172 //-////////////////////////////////////////////////////////////////////////
177 size_type size() const;
180 iterator begin() const;
181 iterator end() const;
183 value_type front() const;
184 value_type back() const;
190 // All these operations can be quite inefficient depending on the list type
191 value_type shift(iterator pos, size_type n=1);
192 template <class Value>
193 void insert(iterator pos, Value const & t);
194 template <class Value>
195 void insert(iterator pos, size_type n, Value const & t);
196 template <class ForwardIterator>
198 void insert(iterator pos, ForwardIterator f, ForwardIterator l,
199 typename boost::disable_if< boost::is_convertible<ForwardIterator,size_type> >::type * = 0);
201 void insert(iterator pos, ForwardIterator f, ForwardIterator l);
204 void erase(iterator pos, size_type n=1);
205 void erase(iterator f, iterator l);
208 template <class Value> void push_back (Value const & value, size_type n=1);
209 value_type push_back_space (size_type n=1);
210 template <class Value> void push_front (Value const & value, size_type n=1);
211 value_type push_front_space (size_type n=1);
212 void resize (size_type n);
213 template <class Value> void resize (size_type n, Value value);
217 ///\name Parser interface
220 parser_type parser() const;
221 data_iterator i() const;
222 state_type state() const;
223 PacketData & data() const;
225 size_type bytes() const;
231 friend class detail::ListParser_Iterator<ListParser_Container>;
237 /** \brief Define ListParser field
239 This macro is a special helper to define a senf::ListParser type field, a list of elements
240 of type \a elt_type (a parser) which size is determined by \a size.
243 // The size field should be declared private or read-only (size is accessible via the list)
244 SENF_PARSER_PRIVATE_FIELD ( list_size_, senf::UInt16Parser );
246 SENF_PARSER_LIST ( list, list_size_, EltParser );
249 Here \c EltParser can be an arbitrary parser and need not have a fixed size.
251 \warning Realize, that the \a size field is controlled by the list parser. This field
252 should therefore be declared either read-only or private and must be changed only via
255 Further additional tags are supported which modify the type of list created:
257 <table class="senf fixedcolumn">
258 <tr><td>\c bytes(\a size)</td><td>\a size gives the size of the list in bytes not the
259 number of contained elements</td></tr>
261 <tr><td>\c packetSize()</td><td>Use the size of the packet to get the list size. The
262 list will occupy all space up to the end of the packet.</td></tr>
264 <tr><td>\c transform(\a transform, \a size)</td><td>The \a transform is applied to the \a
265 size value, the value is not used directly</td>
267 <tr><td>\c transform(\a transform, \c bytes(\a size))</td><td>The \a transform is applied to
268 the \a size value. The value is then interpreted containing the list size in bytes not
269 number of elements</td>
272 The optional \a transform is a class with the following layout
276 typedef ... value_type;
277 static value_type get(other_type v);
278 static other_type set(value_type v);
282 \c other_type is \a size ::\c value_type, the type of the value returned by the \a size
283 field, whereas the \c value_type typedef is the arbitrary return type of the transform.
285 The tags are applied to the \a size parameter:
287 SENF_PARSER_LIST ( list, transform(MyTransform, list_size_), EltParser );
290 \warning There are some caveats when working with \c bytes() type lists:
291 \li You may <b>only change the size of a contained element from a container wrapper</b>.
292 \li While you hold a container wrapper, <b>only access the packet through this wrapper</b>
293 or a nested wrapper either for reading or writing.
295 \warning If lists are nested, you need to allocate a container wrapper for each level and
296 may only access the packet through the lowest-level active container wrapper.
298 \implementation These restrictions are necessary to ensure correct recalculation of the
299 <tt>bytes</tt> field. For more info, see the comments in \ref ListBParser.ih
301 \param[in] name field name
302 \param[in] size name of field giving the list size
303 \param[in] elt_type list element type
306 How to use \ref packet_usage_fields_collection \n
307 senf::ListParser the list parser API for list field access
308 senf::ListParser_Container the list parser container API for list field access
311 \ingroup packetparsermacros
313 # define SENF_PARSER_LIST(name, size, elt_type) \
314 SENF_PARSER_LIST_I(public, name, size, elt_type)
316 /** \brief Define private ListParser field
318 \see \ref SENF_PARSER_LIST()
321 \ingroup packetparsermacros
323 # define SENF_PARSER_PRIVATE_LIST(name, size, elt_type) \
324 SENF_PARSER_LIST_I(protected, name, size, elt_type)
328 //-/////////////////////////////////////////////////////////////////////////////////////////////////
330 #if !defined(HH_SENF_Packets_Packets__decls_) && !defined(HH_SENF_Packets_ListParser_i_)
331 #define HH_SENF_Packets_ListParser_i_
332 //#include "ListParser.cci"
333 #include "ListParser.ct"
334 #include "ListParser.cti"
341 // c-file-style: "senf"
342 // indent-tabs-mode: nil
343 // ispell-local-dictionary: "american"
344 // compile-command: "scons -u test"
345 // comment-column: 40