Packets: Add container 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 Parse_List container wrapper
107
108         This is the container wrapper used for list parsers. The container wrapper will stay valid
109         after changing the collection. However the container still depends on the packet and will be
110         invalidated if the Packet is deallocated or if the packet size is changed from without the
111         container wrapper (more precisely, it is invalided if the insertion/deletion happens before
112         the vector in the packet data).
113
114         The vector container wrapper provides a complete STL random-access sequence interface.
115         
116         \code
117         SomePacket p (...);
118         SomePacket::aListCollection_t::container c (p->aListCollection());
119         c.insert(c.begin(), ... );
120         \endcode
121
122         \see Parse_List
123       */
124     template <class ListPolicy>
125     class Parse_List_Container
126         : private ListPolicy
127     {
128     public:
129         ///////////////////////////////////////////////////////////////////////////
130         // Types
131
132         typedef typename ListPolicy::parser_type parser_type;
133         typedef PacketParserBase::data_iterator data_iterator;
134         typedef PacketParserBase::size_type size_type;
135         typedef PacketParserBase::difference_type difference_type;
136         typedef typename ListPolicy::element_type value_type;
137         typedef detail::Parse_List_Iterator<
138             value_type, typename ListPolicy::iterator_policy> iterator;
139         typedef iterator const_iterator;
140         typedef PacketParserBase::state_type state_type;
141         
142         ///////////////////////////////////////////////////////////////////////////
143         ///\name Structors and default members
144         ///@{
145
146         // no default constructor
147         // default copy
148         // default destructor
149         // conversion constructors
150
151         Parse_List_Container(parser_type const & list);
152         ~Parse_List_Container();
153         
154         ///@}
155         ///////////////////////////////////////////////////////////////////////////
156
157         ///\name Accessors
158         ///@{
159
160         size_type size() const;
161         bool empty() const;
162
163         iterator begin() const;
164         iterator end() const;
165
166         value_type front() const;
167         value_type back() const;
168
169         ///@}
170         ///\name Mutators
171         ///@{
172
173         // All these operations can be quite inefficient depending on the list type
174         void shift(iterator pos, size_type n=1);
175         template <class Value>
176         void insert(iterator pos, Value const & t);
177         template <class Value>
178         void insert(iterator pos, size_type n, Value const & t);
179         template <class ForwardIterator>
180 #       ifndef DOXYGEN
181         void insert(iterator pos, ForwardIterator f, ForwardIterator l,
182                     typename boost::disable_if< boost::is_convertible<ForwardIterator,size_type> >::type * = 0);
183 #       else
184         void insert(iterator pos, ForwardIterator f, ForwardIterator l);
185 #       endif
186
187         void erase(iterator pos, size_type n=1);
188         void erase(iterator f, iterator l);
189         void clear();
190
191         template <class Value> void push_back        (Value value, size_type n=1);
192                                void push_back_space  (size_type n=1);
193         template <class Value> void push_front       (Value value, size_type n=1);
194                                void push_front_space (size_type n=1);
195                                void resize           (size_type n);
196         template <class Value> void resize           (size_type n, Value value);
197
198         ///@}
199
200         ///\name Parser interface
201         ///@{
202
203         parser_type parser() const;
204         data_iterator i() const;
205         state_type state() const;
206         PacketData & data() const;
207
208         size_type bytes() const;
209         void init() const;
210         
211         ///@}
212
213     private:
214         state_type state_;
215         size_type i_;
216     };
217
218         
219 }
220
221 ///////////////////////////////hh.e////////////////////////////////////////
222 #endif
223 #if !defined(HH_Packets__decls_) && !defined(HH_ParseList_i_)
224 #define HH_ParseList_i_
225 //#include "ParseList.cci"
226 #include "ParseList.ct"
227 #include "ParseList.cti"
228 #endif
229
230 \f
231 // Local Variables:
232 // mode: c++
233 // fill-column: 100
234 // c-file-style: "senf"
235 // indent-tabs-mode: nil
236 // ispell-local-dictionary: "american"
237 // compile-command: "scons -u test"
238 // comment-column: 40
239 // End: