Packets: Complete reimplementation of parse helper macros
[senf.git] / Packets / ParseList.hh
1 // Copyright (C) 2007 
2 // Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
3 // Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
4 //     Stefan Bund <g0dil@berlios.de>
5 //
6 // This program is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 2 of the License, or
9 // (at your option) any later version.
10 //
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the
18 // Free Software Foundation, Inc.,
19 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20
21 /** \file
22     \brief ParseList public header */
23
24 #ifndef HH_ParseList_
25 #define HH_ParseList_ 1
26
27 // Custom includes
28 #include <boost/utility.hpp>
29 #include "PacketParser.hh"
30
31 //#include "ParseList.mpp"
32 ///////////////////////////////hh.p////////////////////////////////////////
33
34 namespace senf {
35
36     namespace detail { template <class ElementParser, class IteratorPolicy> 
37                        class Parse_List_Iterator; }
38
39     template <class ListPolicy>
40     class Parse_List_Container;
41
42     /** \brief Arbitrary sequential element collection
43
44         A List is a sequential collection of elements. The element type is given as an arbitrary
45         parser. The list is more flexible than a vector: It is not limited to fixed-size elements
46         and it might not have direct access to the size of the collection. 
47
48         The cost is however, that a List is only a model of an STL forward sequence. The parser
49         provides a reduced interface to this sequence, the container wrapper provides the complete
50         interface.
51
52         Pare_List makes use of a policy template argument, \a ListPolicy, to customize the way the
53         list is laid out. This policy is given quite some freedom in the list
54         implementation. It is however important, that list elements <em>always follow each other
55         without padding</em> (if padding is needed, it needs to be part of the element parser).
56
57         \see ExampleListPolicy
58         \ingroup parsecollection
59       */
60     template <class ListPolicy>
61     class Parse_List 
62         : public PacketParserBase,
63           private ListPolicy
64     {
65     public:
66         Parse_List(data_iterator i, state_type s);
67         Parse_List(ListPolicy policy, data_iterator i, state_type s);
68                                         ///< Additional policy specific constructor
69                                         /**< This constructor may be used, if the policy needs
70                                              additional parameters. */
71
72         size_type bytes() const;
73         void init() const;
74
75         static const size_type init_bytes = ListPolicy::init_bytes;
76
77         ///////////////////////////////////////////////////////////////////////////
78         // Container interface
79
80         typedef typename ListPolicy::element_type value_type;
81         typedef detail::Parse_List_Iterator< 
82             value_type, typename ListPolicy::iterator_policy > iterator;
83         typedef iterator const_iterator;
84         typedef typename ListPolicy::container_type container;
85
86         size_type size() const;
87         bool empty() const;
88         
89         iterator begin() const;
90         iterator end() 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     private:
103         template <class Policy> friend class Parse_List_Container;
104     };
105
106     /** \brief Example of a list policy. ONLY FOR EXPOSITION.
107         
108         This class shows the interface which must be implemented by a list policy. It is not a list
109         policy only a declaration of the interface:
110         \code
111         struct ExampleListPolicy
112         {
113             // optional typedefs used to simplify all other declarations
114             typedef PacketParserBase::data_iterator data_iterator;
115             typedef PacketParserBase::state_type state_type;
116             typedef PacketParserBase::size_type size_type;
117
118             // mandatory typedefs in the parser and container policy
119             typedef ElementParser element_type;
120             typedef Parse_List< ExampleListPolicy > parser_type;
121             typedef Parse_List_Container< ExampleListPolicy > container_type;
122
123             // mandatory constant in parser and container policy
124             static const size_type init_bytes = 0;
125
126             // Members needed in the parser and the container policy
127             size_type bytes  (data_iterator i, state_type s) const;
128             size_type size   (data_iterator i, state_type s) const;
129             void      init   (data_iterator i, state_type s) const;
130         
131             // Members needed only in the container policy
132             void      erase  (data_iterator i, state_type s, iterator p) const;
133             void      insert (data_iterator i, state_type s, iterator p) const;
134
135             struct iterator_policy
136             {
137                 iterator setBegin        (data_iterator i, state_type s);
138                 iterator setEnd          (data_iterator i, state_type s);
139                 void     setFromPosition (data_iterator i, state_type s, iterator p);
140                 iterator next            (data_iterator i, state_type s);
141                 iterator raw             (data_iterator i, state_type s) const;
142             };
143         };
144         \endcode
145
146         If necessary, you may use a different policy in the container_type. The ListPolicy must
147         define the elements bytes(), size() and init(), the container policy needs all these and
148         additionally needs erase() and insert(). The container policy will also need the
149         element_type, parser_type and container_type typedefs.
150         
151         \see \ref Parse_List
152      */
153     struct ExampleListPolicy
154     {
155         typedef PacketParserBase::data_iterator iterator;
156         typedef PacketParserBase::state_type state_type;
157         typedef PacketParserBase::size_type size_type;
158
159         typedef void element_type;      ///< Type of list elements
160                                         /**< This is the parser used to parse the list elements. */
161         typedef void parser_type;       ///< List parser type
162                                         /**< parser_type is the list parser used to parse a list of
163                                              this type,
164                                              e.g. <tt>senf::Parse_List<ExampleListPolicy></tt>. */
165         typedef void container_type;    ///< Type of container wrapper
166                                         /**< This is the container wrapper of the list, e.g.
167                                              <tt>Parse_List_Container<ExampleListPolicy></tt>. The
168                                              container may however use a \e different policy, as
169                                              long as that policy is constructible from the parser
170                                              policy. */
171
172         static const size_type init_bytes = 0; ///< Size of a new list of this type
173                                         /**< Initial size which needs to be allocated to this type
174                                              of list */
175
176         size_type bytes(iterator i, state_type s) const; ///< Size of list in bytes
177                                         /**< Return the complete size of the list in
178                                              bytes. Depending on the type of list, this call may
179                                              need to completely traverse the list ... */
180
181         size_type size(iterator i, state_type s) const; ///< Number of elements in list
182                                         /**< Return the number of elements in the list. This
183                                              operation may be quite inefficient for some lists (the
184                                              list must be traversed to find that number. */
185
186         void init(iterator i, state_type s) const; ///< Initialize new list
187                                         /**< Called after init_size bytes have been allocated to
188                                              initialize the list. After init() is called, the list
189                                              is traversed to initialize any members (probably
190                                              none) */
191
192         void erase(iterator i, state_type s, iterator p) const; ///< Erase element from list
193                                         /**< Delete the list element at p from the List (i,s). When
194                                              this operation is called, the element is still part of
195                                              the list. This call must update the meta-data as
196                                              needed. The data will be removed after this call
197                                              returns. */
198
199         void insert(iterator i, state_type s, iterator p) const; ///< Insert element into list
200                                         /**< This is called after an element has been inserted at p
201                                              into the List (i,s) to update the meta-data. */
202
203         /** \brief Example of a list iterator policy. ONLY FOR EXPOSITION.
204
205             \see \ref ExampleListPolicy \n
206                 \ref Parse_List
207          */
208         struct iterator_policy 
209         {
210             iterator setBegin(iterator i, state_type s); ///< Initialize iterator to begin()
211                                         /**< Initialize the policy from the given List (i,s). Set
212                                              the iterator to the beginning iterator. Return
213                                              data_iterator to the first element.
214
215                                              \warning if the list is empty, the returned iterator
216                                              \e must be the same as the one returned by setEnd. */
217
218             iterator setEnd(iterator i, state_type s); ///< Initialize iterator to end()
219                                         /**< Initialize the policy from the given List (i,s). Set
220                                              the iterator to the end iterator. Return data_iterator
221                                              used to mark the end of the range. This may be a
222                                              special sentinel value (e.g. data().end()) if
223                                              needed. */
224
225             void setFromPosition(iterator i, state_type s, iterator p); 
226                                         ///< Initialize iterator from the given raw position
227                                         /**< Set the iterator to the Element at raw position p. This
228                                              operation can potentially be very inefficient if the
229                                              list needs to be traversed from the beginning until the
230                                              iterator is found. */
231             
232             iterator next(iterator i, state_type s); ///< Advance to next element
233                                         /**< given an iterator to an element, go to the next
234                                              element. */
235
236             iterator raw(iterator i, state_type s); ///< Return raw position of element
237                                         /**< Given the iterator state (i,s), return the raw iterator
238                                              to the datum. This will be i in almost all cases EXCEPT
239                                              if a special sentinel value is used as end() value. In
240                                              this case, this member must return the real position
241                                              after the last element. */
242         };
243
244         /** \brief Example of a list container policy. ONLY FOR EXPOSITION
245             
246             \see \ref ExampleListPolicy \n
247                 \ref Parse_List
248          */
249         struct container_policy
250         {
251             void init(iterator i, state_type s); ///< Initialize new container
252             void update(iterator i, state_type s); ///< Called before every container access
253         };
254     };
255
256     /** \brief Parse_List container wrapper
257
258         This is the container wrapper used for list parsers. The container wrapper will stay valid
259         after changing the collection. However the container still depends on the packet and will be
260         invalidated if the Packet is deallocated or if the packet size is changed from without the
261         container wrapper (more precisely, it is invalided if the insertion/deletion happens before
262         the vector in the packet data).
263
264         The vector container wrapper provides a complete STL random-access sequence interface.
265         
266         \code
267         SomePacket p (...);
268         SomePacket::aListCollection_t::container c (p->aListCollection());
269         c.insert(c.begin(), ... );
270         \endcode
271
272         \see Parse_List
273       */
274     template <class ListPolicy>
275     class Parse_List_Container
276         : private ListPolicy
277     {
278     public:
279         ///////////////////////////////////////////////////////////////////////////
280         // Types
281
282         typedef typename ListPolicy::parser_type parser_type;
283         typedef PacketParserBase::data_iterator data_iterator;
284         typedef PacketParserBase::size_type size_type;
285         typedef PacketParserBase::difference_type difference_type;
286         typedef typename ListPolicy::element_type value_type;
287         typedef detail::Parse_List_Iterator<
288             value_type, typename ListPolicy::iterator_policy> iterator;
289         typedef iterator const_iterator;
290         typedef PacketParserBase::state_type state_type;
291         
292         ///////////////////////////////////////////////////////////////////////////
293         ///\name Structors and default members
294         ///@{
295
296         // no default constructor
297         // default copy
298         // default destructor
299         // conversion constructors
300
301         Parse_List_Container(parser_type const & list);
302         ~Parse_List_Container();
303         
304         ///@}
305         ///////////////////////////////////////////////////////////////////////////
306
307         ///\name Accessors
308         ///@{
309
310         size_type size() const;
311         bool empty() const;
312
313         iterator begin() const;
314         iterator end() const;
315
316         value_type front() const;
317         value_type back() const;
318
319         ///@}
320         ///\name Mutators
321         ///@{
322
323         // All these operations can be quite inefficient depending on the list type
324         void shift(iterator pos, size_type n=1);
325         template <class Value>
326         void insert(iterator pos, Value const & t);
327         template <class Value>
328         void insert(iterator pos, size_type n, Value const & t);
329         template <class ForwardIterator>
330 #       ifndef DOXYGEN
331         void insert(iterator pos, ForwardIterator f, ForwardIterator l,
332                     typename boost::disable_if< boost::is_convertible<ForwardIterator,size_type> >::type * = 0);
333 #       else
334         void insert(iterator pos, ForwardIterator f, ForwardIterator l);
335 #       endif
336
337         void erase(iterator pos, size_type n=1);
338         void erase(iterator f, iterator l);
339         void clear();
340
341         template <class Value> void push_back        (Value value, size_type n=1);
342                                void push_back_space  (size_type n=1);
343         template <class Value> void push_front       (Value value, size_type n=1);
344                                void push_front_space (size_type n=1);
345                                void resize           (size_type n);
346         template <class Value> void resize           (size_type n, Value value);
347
348         ///@}
349
350         ///\name Parser interface
351         ///@{
352
353         parser_type parser() const;
354         data_iterator i() const;
355         state_type state() const;
356         PacketData & data() const;
357
358         size_type bytes() const;
359         void init() const;
360         
361         ///@}
362
363     private:
364         state_type state_;
365         size_type i_;
366     };
367
368         
369 }
370
371 ///////////////////////////////hh.e////////////////////////////////////////
372 #endif
373 #if !defined(HH_Packets__decls_) && !defined(HH_ParseList_i_)
374 #define HH_ParseList_i_
375 //#include "ParseList.cci"
376 #include "ParseList.ct"
377 #include "ParseList.cti"
378 #endif
379
380 \f
381 // Local Variables:
382 // mode: c++
383 // fill-column: 100
384 // c-file-style: "senf"
385 // indent-tabs-mode: nil
386 // ispell-local-dictionary: "american"
387 // compile-command: "scons -u test"
388 // comment-column: 40
389 // End: