709ed0dbf1b79aa5d211c4a1a9008dfa9cbab674
[senf.git] / senf / Packets / ListParser.hh
1 // $Id$
2 //
3 // Copyright (C) 2007
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY
6 //     Stefan Bund <g0dil@berlios.de>
7 //
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 2 of the License, or
11 // (at your option) any later version.
12 //
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 // GNU General Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the
20 // Free Software Foundation, Inc.,
21 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22
23 /** \file
24     \brief ListParser public header */
25
26 #ifndef HH_SENF_Packets_ListParser_
27 #define HH_SENF_Packets_ListParser_ 1
28
29 // Custom includes
30 #include <boost/utility.hpp>
31 #include "PacketParser.hh"
32
33 //#include "ListParser.mpp"
34 ///////////////////////////////hh.p////////////////////////////////////////
35
36 namespace senf {
37
38     namespace detail { template <class Container> class ListParser_Iterator; }
39
40     template <class ListPolicy>
41     class ListParser_Container;
42
43     /** \brief Arbitrary sequential element collection
44
45         A List is a sequential collection of elements. The element type is given as an arbitrary
46         parser. The list is more flexible than a vector: It is not limited to fixed-size elements
47         and it might not have direct access to the size of the collection.
48
49         The cost is however, that a List is only a model of an STL forward sequence. The parser
50         provides a reduced interface to this sequence, the container wrapper provides the complete
51         interface.
52
53         ListParser makes use of a policy template argument, \a ListPolicy, to customize the way the
54         list is laid out. This policy is given quite some freedom in the list implementation. It is
55         however important, that list elements <em>always follow each other without padding</em> (if
56         padding is needed, it needs to be part of the element parser).
57
58         You will normally not instantiate ListParser directly, you will use the \ref
59         SENF_PARSER_LIST() helper macro.
60
61         Some basic list access methods are defined as parser members. To access the complete list
62         API however you will need to instantiate a container wrapper for the list. See \ref
63         packet_usage_fields_collection.
64
65         \see
66             How to access \ref packet_usage_fields_collection \n
67             SENF_PARSER_LIST() macro used to define list fields \n
68             ListParser_Container list container wrapper API \n
69             ExampleListPolicy
70
71         \ingroup parsecollection
72       */
73     template <class ListPolicy>
74     class ListParser
75         : public PacketParserBase,
76           private ListPolicy
77     {
78     public:
79         typedef ListPolicy policy;
80
81         ListParser(data_iterator i, state_type s);
82         ListParser(ListPolicy policy, data_iterator i, state_type s);
83                                         ///< Additional policy specific constructor
84                                         /**< This constructor may be used, if the policy needs
85                                              additional parameters. */
86
87         size_type bytes() const;
88         void init() const;
89
90         static const size_type init_bytes = ListPolicy::init_bytes;
91
92         ///////////////////////////////////////////////////////////////////////////
93         // Container interface
94
95         typedef typename ListPolicy::element_type value_type;
96         typedef typename ListPolicy::container_type container;
97
98         size_type size() const;
99         bool empty() const;
100
101         value_type front() const;
102         value_type back() const;
103
104         template <class Value> void push_back        (Value const & value, size_type n=1) const;
105         value_type                  push_back_space  (size_type n=1) const;
106         template <class Value> void push_front       (Value const & value, size_type n=1) const;
107         value_type                  push_front_space (size_type n=1) const;
108                                void resize           (size_type n) const;
109         template <class Value> void resize           (size_type n, Value value) const;
110
111         static ListParser & get(ListPolicy & p);
112         static ListParser const & get(ListPolicy const & p);
113
114     private:
115         template <class Policy> friend class ListParser_Container;
116     };
117
118     /** \brief ListParser container wrapper
119
120         This is the container wrapper used for list parsers. The container wrapper will stay valid
121         after changing the collection. However the container still depends on the packet and will be
122         invalidated if the Packet is deallocated or if the packet size is changed from without the
123         container wrapper (more precisely, it is invalided if the insertion/deletion happens before
124         the vector in the packet data).
125
126         The vector container wrapper provides a complete STL random-access sequence interface.
127
128         \code
129         SomePacket p (...);
130         SomePacket::aListCollection_t::container c (p->aListCollection());
131         c.insert(c.begin(), ... );
132         \endcode
133
134         \see ListParser
135       */
136     template <class ListPolicy>
137     class ListParser_Container
138         : private ListPolicy
139     {
140     public:
141         ///////////////////////////////////////////////////////////////////////////
142         // Types
143
144         typedef ListPolicy policy;
145         typedef typename ListPolicy::parser_type parser_type;
146         typedef PacketParserBase::data_iterator data_iterator;
147         typedef PacketParserBase::size_type size_type;
148         typedef PacketParserBase::difference_type difference_type;
149         typedef typename ListPolicy::element_type value_type;
150         typedef detail::ListParser_Iterator<ListParser_Container> iterator;
151         typedef iterator const_iterator;
152         typedef PacketParserBase::state_type state_type;
153
154         ///////////////////////////////////////////////////////////////////////////
155         ///\name Structors and default members
156         ///@{
157
158         // no default constructor
159         // default copy
160         // default destructor
161         // conversion constructors
162
163         ListParser_Container(parser_type const & list);
164         ~ListParser_Container();
165
166         ///@}
167         ///////////////////////////////////////////////////////////////////////////
168
169         ///\name Accessors
170         ///@{
171
172         size_type size() const;
173         bool empty() const;
174
175         iterator begin() const;
176         iterator end() const;
177
178         value_type front() const;
179         value_type back() const;
180
181         ///@}
182         ///\name Mutators
183         ///@{
184
185         // All these operations can be quite inefficient depending on the list type
186         value_type shift(iterator pos, size_type n=1);
187         template <class Value>
188         void insert(iterator pos, Value const & t);
189         template <class Value>
190         void insert(iterator pos, size_type n, Value const & t);
191         template <class ForwardIterator>
192 #       ifndef DOXYGEN
193         void insert(iterator pos, ForwardIterator f, ForwardIterator l,
194                     typename boost::disable_if< boost::is_convertible<ForwardIterator,size_type> >::type * = 0);
195 #       else
196         void insert(iterator pos, ForwardIterator f, ForwardIterator l);
197 #       endif
198
199         void erase(iterator pos, size_type n=1);
200         void erase(iterator f, iterator l);
201         void clear();
202
203         template <class Value> void push_back        (Value const & value, size_type n=1);
204         value_type                  push_back_space  (size_type n=1);
205         template <class Value> void push_front       (Value const & value, size_type n=1);
206         value_type                  push_front_space (size_type n=1);
207         void                        resize           (size_type n);
208         template <class Value> void resize           (size_type n, Value value);
209
210         ///@}
211
212         ///\name Parser interface
213         ///@{
214
215         parser_type parser() const;
216         data_iterator i() const;
217         state_type state() const;
218         PacketData & data() const;
219
220         size_type bytes() const;
221         void init() const;
222
223         ///@}
224
225     private:
226         friend class detail::ListParser_Iterator<ListParser_Container>;
227
228         state_type state_;
229         size_type i_;
230     };
231
232     /** \brief Define ListParser field
233
234         This macro is a special helper to define a senf::ListParser type field, a list of elements
235         of type \a elt_type (a parser)  which size is determined by \a size.
236
237         \code
238         // The size field should be declared private or read-only (size is accessible via the list)
239         SENF_PARSER_PRIVATE_FIELD ( list_size_, senf::UInt16Parser );
240         // Define the list
241         SENF_PARSER_LIST ( list, list_size_, EltParser );
242         \endcode
243
244         Here \c EltParser can be an arbitrary parser and need not have a fixed size.
245
246         \warning Realize, that the \a size field is controlled by the list parser. This field
247             should therefore be declared either read-only or private and must be changed only via
248             the list parser.
249
250         Further additional tags are supported which modify the type of list created:
251
252         <table class="senf fixedcolumn">
253         <tr><td>\c bytes(\a size)</td><td>\a size gives the size of the list in bytes not the
254         number of contained elements</td></tr>
255
256         <tr><td>\c packetSize()</td><td>Use the size of the packet to get the list size. The
257         list will occupy all space up to the end of the packet.</td></tr>
258
259         <tr><td>\c transform(\a transform, \a size)</td><td>The \a transform is applied to the \a
260         size value, the value is not used directly</td>
261
262         <tr><td>\c transform(\a transform, \c bytes(\a size))</td><td>The \a transform is applied to
263         the \a size value. The value is then interpreted containing the list size in bytes not
264         number of elements</td>
265         </table>
266
267         The optional \a transform is a class with the following layout
268         \code
269         struct MyTransform
270         {
271             typedef ... value_type;
272             static value_type get(other_type v);
273             static other_type set(value_type v);
274         };
275         \endcode
276
277         \c other_type is \a size ::\c value_type, the type of the value returned by the \a size
278         field, whereas the \c value_type typedef is the arbitrary return type of the transform.
279
280         The tags are applied to the \a size parameter:
281         \code
282         SENF_PARSER_LIST ( list, transform(MyTransform, list_size_), EltParser );
283         \endcode
284
285         \warning There are some caveats when working with \c bytes() type lists:
286         \li You may <b>only change the size of a contained element from a container wrapper</b>.
287         \li While you hold a container wrapper, <b>only access the packet through this wrapper</b>
288             or a nested wrapper either for reading or writing.
289
290         \warning If lists are nested, you need to allocate a container wrapper for each level and
291         may only access the packet through the lowest-level active container wrapper.
292
293         \implementation These restrictions are necessary to ensure correct recalculation of the
294             <tt>bytes</tt> field. For more info, see the comments in \ref ListBParser.ih
295
296         \param[in] name field name
297         \param[in] size name of field giving the list size
298         \param[in] elt_type list element type
299
300         \see
301             How to use \ref packet_usage_fields_collection \n
302             senf::ListParser the list parser API for list field access
303             senf::ListParser_Container the list parser container API for list field access
304
305         \hideinitializer
306         \ingroup packetparsermacros
307      */
308 #   define SENF_PARSER_LIST(name, size, elt_type) \
309         SENF_PARSER_LIST_I(public, name, size, elt_type)
310
311     /** \brief Define private ListParser field
312
313         \see \ref SENF_PARSER_LIST()
314
315         \hideinitializer
316         \ingroup packetparsermacros
317      */
318 #   define SENF_PARSER_PRIVATE_LIST(name, size, elt_type) \
319         SENF_PARSER_LIST_I(protected, name, size, elt_type)
320
321 }
322
323 ///////////////////////////////hh.e////////////////////////////////////////
324 #endif
325 #if !defined(HH_SENF_Packets_Packets__decls_) && !defined(HH_SENF_Packets_ListParser_i_)
326 #define HH_SENF_Packets_ListParser_i_
327 //#include "ListParser.cci"
328 #include "ListParser.ct"
329 #include "ListParser.cti"
330 #endif
331
332 \f
333 // Local Variables:
334 // mode: c++
335 // fill-column: 100
336 // c-file-style: "senf"
337 // indent-tabs-mode: nil
338 // ispell-local-dictionary: "american"
339 // compile-command: "scons -u test"
340 // comment-column: 40
341 // End: