switch to new MPL based Fraunhofer FOKUS Public License
[senf.git] / senf / Packets / ListParser.hh
1 // $Id$
2 //
3 // Copyright (C) 2007
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 //
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
10 //
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.
14 //
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.
18 //
19 // The Original Code is Fraunhofer FOKUS code.
20 //
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.
24 //
25 // Contributor(s):
26 //   Stefan Bund <g0dil@berlios.de>
27
28 /** \file
29     \brief ListParser public header */
30
31 #ifndef HH_SENF_Packets_ListParser_
32 #define HH_SENF_Packets_ListParser_ 1
33
34 // Custom includes
35 #include <boost/utility.hpp>
36 #include "PacketParser.hh"
37
38 //#include "ListParser.mpp"
39 //-/////////////////////////////////////////////////////////////////////////////////////////////////
40
41 namespace senf {
42
43     namespace detail { template <class Container> class ListParser_Iterator; }
44
45     template <class ListPolicy>
46     class ListParser_Container;
47
48     /** \brief Arbitrary sequential element collection
49
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.
53
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
56         interface.
57
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).
62
63         You will normally not instantiate ListParser directly, you will use the \ref
64         SENF_PARSER_LIST() helper macro.
65
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.
69
70         \see
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
74             ExampleListPolicy
75
76         \ingroup parsecollection
77       */
78     template <class ListPolicy>
79     class ListParser
80         : public PacketParserBase,
81           private ListPolicy
82     {
83     public:
84         typedef ListPolicy policy;
85
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. */
91
92         size_type bytes() const;
93         void init() const;
94
95         static const size_type init_bytes = ListPolicy::init_bytes;
96
97         //-////////////////////////////////////////////////////////////////////////
98         // Container interface
99
100         typedef typename ListPolicy::element_type value_type;
101         typedef typename ListPolicy::container_type container;
102
103         size_type size() const;
104         bool empty() const;
105
106         value_type front() const;
107         value_type back() const;
108
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;
115
116         static ListParser & get(ListPolicy & p);
117         static ListParser const & get(ListPolicy const & p);
118
119     private:
120         template <class Policy> friend class ListParser_Container;
121     };
122
123     /** \brief ListParser container wrapper
124
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).
130
131         The vector container wrapper provides a complete STL random-access sequence interface.
132
133         \code
134         SomePacket p (...);
135         SomePacket::aListCollection_t::container c (p->aListCollection());
136         c.insert(c.begin(), ... );
137         \endcode
138
139         \see ListParser
140       */
141     template <class ListPolicy>
142     class ListParser_Container
143         : private ListPolicy
144     {
145     public:
146         //-////////////////////////////////////////////////////////////////////////
147         // Types
148
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;
158
159         //-////////////////////////////////////////////////////////////////////////
160         ///\name Structors and default members
161         //\{
162
163         // no default constructor
164         // default copy
165         // default destructor
166         // conversion constructors
167
168         ListParser_Container(parser_type const & list);
169         ~ListParser_Container();
170
171         //\}
172         //-////////////////////////////////////////////////////////////////////////
173
174         ///\name Accessors
175         //\{
176
177         size_type size() const;
178         bool empty() const;
179
180         iterator begin() const;
181         iterator end() const;
182
183         value_type front() const;
184         value_type back() const;
185
186         //\}
187         ///\name Mutators
188         //\{
189
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>
197 #       ifndef DOXYGEN
198         void insert(iterator pos, ForwardIterator f, ForwardIterator l,
199                     typename boost::disable_if< boost::is_convertible<ForwardIterator,size_type> >::type * = 0);
200 #       else
201         void insert(iterator pos, ForwardIterator f, ForwardIterator l);
202 #       endif
203
204         void erase(iterator pos, size_type n=1);
205         void erase(iterator f, iterator l);
206         void clear();
207
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);
214
215         //\}
216
217         ///\name Parser interface
218         //\{
219
220         parser_type parser() const;
221         data_iterator i() const;
222         state_type state() const;
223         PacketData & data() const;
224
225         size_type bytes() const;
226         void init() const;
227
228         //\}
229
230     private:
231         friend class detail::ListParser_Iterator<ListParser_Container>;
232
233         state_type state_;
234         size_type i_;
235     };
236
237     /** \brief Define ListParser field
238
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.
241
242         \code
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 );
245         // Define the list
246         SENF_PARSER_LIST ( list, list_size_, EltParser );
247         \endcode
248
249         Here \c EltParser can be an arbitrary parser and need not have a fixed size.
250
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
253             the list parser.
254
255         Further additional tags are supported which modify the type of list created:
256
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>
260
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>
263
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>
266
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>
270         </table>
271
272         The optional \a transform is a class with the following layout
273         \code
274         struct MyTransform
275         {
276             typedef ... value_type;
277             static value_type get(other_type v);
278             static other_type set(value_type v);
279         };
280         \endcode
281
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.
284
285         The tags are applied to the \a size parameter:
286         \code
287         SENF_PARSER_LIST ( list, transform(MyTransform, list_size_), EltParser );
288         \endcode
289
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.
294
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.
297
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
300
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
304
305         \see
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
309
310         \hideinitializer
311         \ingroup packetparsermacros
312      */
313 #   define SENF_PARSER_LIST(name, size, elt_type) \
314         SENF_PARSER_LIST_I(public, name, size, elt_type)
315
316     /** \brief Define private ListParser field
317
318         \see \ref SENF_PARSER_LIST()
319
320         \hideinitializer
321         \ingroup packetparsermacros
322      */
323 #   define SENF_PARSER_PRIVATE_LIST(name, size, elt_type) \
324         SENF_PARSER_LIST_I(protected, name, size, elt_type)
325
326 }
327
328 //-/////////////////////////////////////////////////////////////////////////////////////////////////
329 #endif
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"
335 #endif
336
337 \f
338 // Local Variables:
339 // mode: c++
340 // fill-column: 100
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
346 // End: