18bc1d645a23f8080cc6da0c0104db3c14822d7d
[senf.git] / 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_ListParser_
27 #define HH_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         \see ExampleListPolicy
62         \ingroup parsecollection
63       */
64     template <class ListPolicy>
65     class ListParser
66         : public PacketParserBase,
67           private ListPolicy
68     {
69     public:
70         typedef ListPolicy policy;
71
72         ListParser(data_iterator i, state_type s);
73         ListParser(ListPolicy policy, data_iterator i, state_type s);
74                                         ///< Additional policy specific constructor
75                                         /**< This constructor may be used, if the policy needs
76                                              additional parameters. */
77
78         size_type bytes() const;
79         void init() const;
80
81         static const size_type init_bytes = ListPolicy::init_bytes;
82
83         ///////////////////////////////////////////////////////////////////////////
84         // Container interface
85
86         typedef typename ListPolicy::element_type value_type;
87         typedef typename ListPolicy::container_type container;
88
89         size_type size() const;
90         bool empty() const;
91
92         value_type front() const;
93         value_type back() const;
94
95         template <class Value> void push_back        (Value value, size_type n=1) const;
96                                void push_back_space  (size_type n=1) const;
97         template <class Value> void push_front       (Value value, size_type n=1) const;
98                                void push_front_space (size_type n=1) const;
99                                void resize           (size_type n) const;
100         template <class Value> void resize           (size_type n, Value value) const;
101
102         static ListParser & get(ListPolicy & p);
103         static ListParser const & get(ListPolicy const & p);
104
105     private:
106         template <class Policy> friend class ListParser_Container;
107     };
108
109     /** \brief ListParser container wrapper
110
111         This is the container wrapper used for list parsers. The container wrapper will stay valid
112         after changing the collection. However the container still depends on the packet and will be
113         invalidated if the Packet is deallocated or if the packet size is changed from without the
114         container wrapper (more precisely, it is invalided if the insertion/deletion happens before
115         the vector in the packet data).
116
117         The vector container wrapper provides a complete STL random-access sequence interface.
118
119         \code
120         SomePacket p (...);
121         SomePacket::aListCollection_t::container c (p->aListCollection());
122         c.insert(c.begin(), ... );
123         \endcode
124
125         \see ListParser
126       */
127     template <class ListPolicy>
128     class ListParser_Container
129         : private ListPolicy
130     {
131     public:
132         ///////////////////////////////////////////////////////////////////////////
133         // Types
134
135         typedef ListPolicy policy;
136         typedef typename ListPolicy::parser_type parser_type;
137         typedef PacketParserBase::data_iterator data_iterator;
138         typedef PacketParserBase::size_type size_type;
139         typedef PacketParserBase::difference_type difference_type;
140         typedef typename ListPolicy::element_type value_type;
141         typedef detail::ListParser_Iterator<ListParser_Container> iterator;
142         typedef iterator const_iterator;
143         typedef PacketParserBase::state_type state_type;
144
145         ///////////////////////////////////////////////////////////////////////////
146         ///\name Structors and default members
147         ///@{
148
149         // no default constructor
150         // default copy
151         // default destructor
152         // conversion constructors
153
154         ListParser_Container(parser_type const & list);
155         ~ListParser_Container();
156
157         ///@}
158         ///////////////////////////////////////////////////////////////////////////
159
160         ///\name Accessors
161         ///@{
162
163         size_type size() const;
164         bool empty() const;
165
166         iterator begin() const;
167         iterator end() const;
168
169         value_type front() const;
170         value_type back() const;
171
172         ///@}
173         ///\name Mutators
174         ///@{
175
176         // All these operations can be quite inefficient depending on the list type
177         void shift(iterator pos, size_type n=1);
178         template <class Value>
179         void insert(iterator pos, Value const & t);
180         template <class Value>
181         void insert(iterator pos, size_type n, Value const & t);
182         template <class ForwardIterator>
183 #       ifndef DOXYGEN
184         void insert(iterator pos, ForwardIterator f, ForwardIterator l,
185                     typename boost::disable_if< boost::is_convertible<ForwardIterator,size_type> >::type * = 0);
186 #       else
187         void insert(iterator pos, ForwardIterator f, ForwardIterator l);
188 #       endif
189
190         void erase(iterator pos, size_type n=1);
191         void erase(iterator f, iterator l);
192         void clear();
193
194         template <class Value> void push_back        (Value value, size_type n=1);
195                                void push_back_space  (size_type n=1);
196         template <class Value> void push_front       (Value value, size_type n=1);
197                                void push_front_space (size_type n=1);
198                                void resize           (size_type n);
199         template <class Value> void resize           (size_type n, Value value);
200
201         ///@}
202
203         ///\name Parser interface
204         ///@{
205
206         parser_type parser() const;
207         data_iterator i() const;
208         state_type state() const;
209         PacketData & data() const;
210
211         size_type bytes() const;
212         void init() const;
213
214         ///@}
215
216     private:
217         friend class detail::ListParser_Iterator<ListParser_Container>;
218
219         state_type state_;
220         size_type i_;
221     };
222
223     /** \brief Define ListParser field
224
225         This macro is a special helper to define a senf::ListParser type field, a list of elements
226         of type \a elt_type (a parser)  which size is determined by \a size.
227
228         \code
229         // The size field should be declared private or read-only (size is accessible via the list)
230         SENF_PARSER_PRIVATE_FIELD ( list_size_, senf::UInt16Parser );
231         // Define the list
232         SENF_PARSER_VECTOR ( list, list_size_, EltParser );
233         \endcode
234         
235         Here \c EltParser can be an arbitrary parser and need not have a fixed size.
236
237         Further additional tags are supported which modify the type of list created:
238
239         <table class="senf fixedcolumn">
240         <tr><td>\c bytes(\a size)</td><td>\a size gives the size of the list in bytes not the
241         number of contained elements</td></tr>
242
243         <tr><td>\c transform(\a transform, \a size)</td><td>The \a transform is applied to the \a
244         size value, the value is not used directly</td>
245
246         <tr><td>\c transform(\a transform, \c bytes(\a size))</td><td>The \a transform is applied to
247         the \a size value. The value is then interpreted containing the list size in bytes not
248         number of elements</td> 
249         </table>
250
251         The optional \a transform is a class with the following layout
252         \code
253         struct MyTransform
254         {
255             typedef ... value_type;
256             static value_type get(other_type v);
257             static other_type set(value_type v);
258         };
259         \endcode 
260
261         \c other_type is \a size ::\c value_type, the type of the value returned by the \a size
262         field, whereas the \c value_type typedef is the arbitrary return type of the transform.
263
264         The tags are applied to the \a size parameter:
265         \code
266         SENF_PARSER_LIST ( vec, transform(MyTransform, list_size_), EltParser );
267         \endcode
268
269         \warning There are some caveats when working with \c bytes() type lists:
270         \li You may <b>only change the size of a contained element from a container wrapper</b>.
271         \li While you hold a container wrapper, <b>only access the packet through this wrapper</b>
272             or a nested wrapper either for reading or writing.
273
274         \warning If lists are nested, you need to allocate a container wrapper for each level and
275         may only access the packet through the lowest-level active container wrapper.
276
277         \implementation These restrictions are necessary to ensure correct recalculation of the
278             <tt>bytes</tt> field. For more info, see the comments in \ref ListBParser.ih
279
280         \param[in] name field name
281         \param[in] size name of field giving the list size
282         \param[in] elt_type list element type
283
284         \hideinitializer
285         \ingroup packetparsermacros
286      */
287 #   define SENF_PARSER_LIST(name, size, elt_type) \
288         SENF_PARSER_LIST_I(public, name, size, elt_type)
289
290     /** \brief Define private ListParser field
291
292         \see \ref SENF_PARSER_LIST()
293
294         \hideinitializer
295         \ingroup packetparsermacros
296      */
297 #   define SENF_PARSER_PRIVATE_LIST(name, size, elt_type) \
298         SENF_PARSER_LIST_I(private, name, size, elt_type)
299
300 }
301
302 ///////////////////////////////hh.e////////////////////////////////////////
303 #endif
304 #if !defined(HH_Packets__decls_) && !defined(HH_ListParser_i_)
305 #define HH_ListParser_i_
306 //#include "ListParser.cci"
307 #include "ListParser.ct"
308 #include "ListParser.cti"
309 #endif
310
311 \f
312 // Local Variables:
313 // mode: c++
314 // fill-column: 100
315 // c-file-style: "senf"
316 // indent-tabs-mode: nil
317 // ispell-local-dictionary: "american"
318 // compile-command: "scons -u test"
319 // comment-column: 40
320 // End: