ded220ab8ef6735a9708c59b1e10ae53eea0b151
[senf.git] / Packets / ParseVec.hh
1 // $Id$
2 //
3 // Copyright (C) 2006
4 // Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
5 // Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
6 //     Stefan Bund <stefan.bund@fokus.fraunhofer.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 ParseVec public header */
25
26 #ifndef HH_ParseVec_
27 #define HH_ParseVec_ 1
28
29 // Custom includes
30 #include <boost/iterator/iterator_facade.hpp>
31 #include <boost/utility.hpp>
32 #include <boost/range.hpp>
33 #include <boost/type_traits.hpp>
34 #include "PacketParser.hh"
35 #include "ParseArray.hh" // for Parse_Array_iterator
36
37 //#include "ParseVec.mpp"
38 ///////////////////////////////hh.p////////////////////////////////////////
39
40 namespace senf {
41
42     template <class ElementParser, class Sizer> class Parse_Vector_Container;
43
44     /** \brief Collection of fixed-size elements
45
46         A Vector is a collection of fixed-size elements of which the size of the collection can be
47         determined directly (that is without traversing the collection). This allows very efficient
48         random access to the elements of the collection.
49         
50         A vector is a model of an STL random-access sequence. The parser only provides a reduced
51         interface, the container wrapper however completes this interface.
52
53         Parse_Vector makes use of a policy template argument, \a Sizer, to customize the way the
54         containers size is obtained. You will normally not instantiate Parser_Vector directly, you
55         will use one of the 'template typedefs' (which are templated structures since C++ does not
56         provide real template typedefs) provided with the policy implementations.
57         
58         \todo Make the sizer a private base-class to profit from the empty-base-class optimization
59
60         \see ExampleVectorPolicy
61         \ingroup parsecollection
62      */
63     template <class ElementParser, class Sizer>
64     struct Parse_Vector : public PacketParserBase
65     {
66         Parse_Vector(data_iterator i, state_type s);
67         Parse_Vector(Sizer sizer, data_iterator i, state_type s);
68                                         ///< Additional sizer specific constructor
69                                         /**< This constructor may be used, if the sizer needs
70                                              additional parameters. */
71
72         size_type bytes() const;
73         void init() const;
74
75         static const size_type init_bytes = Sizer::init_bytes;
76
77         ///////////////////////////////////////////////////////////////////////////
78         // Container interface
79
80         typedef ElementParser value_type;
81         typedef detail::Parse_Array_iterator<value_type> iterator;
82         typedef iterator const_iterator;
83         typedef Parse_Vector_Container<ElementParser,Sizer> container;
84
85         size_type size() const;
86         bool empty() const;
87
88         iterator begin() const;
89         iterator end() const;
90
91         value_type operator[](difference_type i) const;
92         value_type front() const;
93         value_type back() const;
94
95         // Mutators
96         
97         // The mutators provided here are those which don't take an iterator argument.
98         // If you need to pass an iterator it is much simpler and cleaner to use the
99         // 'container' wrapper
100                    
101         template <class Value> void push_back        (Value value, size_type n=1) const;
102                                void push_back_space  (size_type n=1) const;
103         template <class Value> void push_front       (Value value, size_type n=1) const;
104                                void push_front_space (size_type n=1) const;
105                                void resize           (size_type n) const;
106         template <class Value> void resize           (size_type n, Value value) const;
107
108      private:
109         Sizer sizer_;
110
111         friend class Parse_Vector_Container<ElementParser,Sizer>;
112     };
113
114     namespace detail { template <class SizeParser> class Parse_VectorN_Sizer; }
115
116     /** \brief Vector with prefix sizing
117         
118         This is a 'template typedef'. It defines a vector with a <em>directly preceding</em> size
119         field holding the number of vector elements. The size field is considered part of the
120         vector.
121         \code
122         // Define MyVector as a vector of 16bit unsigned elements with a directly preceding
123         // 8bit unsigned size field
124         typedef senf::Parse_VectorN<senf::Parse_UInt16, senf::Parse_UInt8>::parser MyVector;
125         \endcode
126
127         \param ElementParser \e fixed-size parser for parsing the vector elements
128         \param SizeParser parser for parsing the vector size (number of elements)
129
130         \see Parse_Vector
131         \ingroup parsecollection
132      */
133     template <class ElementParser, class SizeParser>
134     struct Parse_VectorN
135     {
136         typedef Parse_Vector< ElementParser,
137                               detail::Parse_VectorN_Sizer<SizeParser> > parser;
138     };
139
140     /** \brief Example vector sizer. ONLY FOR EXPOSITION
141
142         This class shows the interface which must be implemented by a vector sizer policy. It is not
143         a vector sizer, it is only a declaration of the interface:
144         \code
145         struct ExampleVectorPolicy
146         {
147             // optional typedefs used to simplify all other declarations
148             typedef PacketParserBase::size_type size_type;
149             typedef PacketParserBase::data_iterator iterator;
150             typedef PacketParserBase::state_type state_type;
151
152             // mandatory members
153             static const size_type init_bytes = 0;
154             size_type  size  (iterator i, state_type s) const;
155             void       size  (iterator i, state_type s, size_type v) const;
156             iterator   begin (iterator i, state_type s) const;
157             size_type  bytes (iterator i, state_type s) const;
158             void       init  (iterator i, state_type s) const;
159         };
160         \endcode
161
162         A sizer may if needed define additional data members.
163      */
164     struct ExampleVectorPolicy
165     {
166         typedef PacketParserBase::size_type size_type;
167         typedef PacketParserBase::data_iterator iterator;
168         typedef PacketParserBase::state_type state_type;
169
170         static const size_type init_bytes = 0; ///< Size of a new vector of this size
171                                         /**< Initial size which needs to be allocated to this type
172                                              of list */
173
174         size_type  size  (iterator i, state_type s) const; ///< Get current vector size
175                                         /**< Return the current number of elements in the 
176                                              vector. */
177         void       size  (iterator i, state_type s, size_type v) const; ///< Change vector size
178                                         /**< Set the size of the vector to \a v. */
179         iterator   begin (iterator i, state_type s) const; 
180                                         ///< Return data_iterator to first element
181                                         /**< The returned data_iterator must point to the beginning
182                                              of the first vector element. The last iterator can than
183                                              automatically be calculated from the fixed element size
184                                              and the number of vector elements. */
185         size_type  bytes (iterator i, state_type s) const; ///< Size of vector parser
186                                         /**< Return the size of the complete vector in bytes. This
187                                              is not necessarily the same as \c size() * \e
188                                              fixed_element_bytes. */
189         void       init  (iterator i, state_type s) const; ///< Initialize new vector
190                                         /** Called to initialize a new vector after allocating
191                                             init_bytes number of bytes for the vector. */
192     };
193
194     /** \brief Parse_Vector container wrapper
195
196         This is the container wrapper used for vector parsers. The container wrapper will stay valid
197         after changing the collection. However the container still depends on the packet and will be
198         invalidated if the Packet is deallocated or if the packet size is changed from without the
199         container wrapper (more precisely, it is invalided if the insertion/deletion happens before
200         the vector in the packet data).
201
202         The vector container wrapper provides a complete STL random-access sequence interface.
203         
204         \code
205         SomePacket p (...);
206         SomePacket::aVectorCollection_t::container c (p->aVectorCollection());
207         c.insert(c.begin(), ... );
208         \endcode
209
210         \see Parse_Vector
211       */
212     template <class ElementParser, class Sizer>
213     class Parse_Vector_Container
214     {
215     public:
216         ///////////////////////////////////////////////////////////////////////////
217         // Types
218
219         typedef Parse_Vector<ElementParser,Sizer> parser_type;
220         typedef PacketParserBase::data_iterator data_iterator;
221         typedef PacketParserBase::size_type size_type;
222         typedef PacketParserBase::difference_type difference_type;
223         typedef ElementParser value_type;
224         typedef detail::Parse_Array_iterator<value_type> iterator;
225         typedef iterator const_iterator;
226         typedef PacketParserBase::state_type state_type;
227
228         ///////////////////////////////////////////////////////////////////////////
229         ///\name Structors and default members
230         ///@{
231
232         // no default constructor
233         // default copy
234         // default destructor
235         // conversion constructors
236
237         Parse_Vector_Container(parser_type const & vector);
238
239         ///@}
240         ///////////////////////////////////////////////////////////////////////////
241
242         ///\name Accessors
243         ///@{
244
245         size_type size() const;
246         bool empty() const;
247
248         iterator begin() const;
249         iterator end() const;
250
251         value_type operator[](difference_type i) const;
252         value_type front() const;
253         value_type back() const;
254
255         ///@}
256         ///\name Mutators
257         ///@{
258
259         iterator shift(iterator pos, size_type n=1);
260         template <class Value>
261         void insert(iterator pos, Value const & t);
262         template <class Value>
263         void insert(iterator pos, size_type n, Value const & t);
264 #       ifndef DOXYGEN
265         template <class ForwardIterator>
266         void insert(iterator pos, ForwardIterator f, ForwardIterator l,
267                     typename boost::disable_if< boost::is_convertible<ForwardIterator,size_type> >::type * = 0);
268 #       else
269         template <class ForwardIterator>
270         void insert(iterator pos, ForwardIterator f, ForwardIterator l);
271 #       endif
272
273         void erase(iterator pos, size_type n=1);
274         void erase(iterator f, iterator l);
275         void clear();
276
277         template <class Value> void push_back        (Value value, size_type n=1);
278                                void push_back_space  (size_type n=1);
279         template <class Value> void push_front       (Value value, size_type n=1);
280                                void push_front_space (size_type n=1);
281                                void resize           (size_type n);
282         template <class Value> void resize           (size_type n, Value value);
283
284         ///@}
285
286         ///\name Parser interface
287         ///@{
288
289         parser_type parser() const;
290         data_iterator i() const;
291         state_type state() const;
292         PacketData & data() const;
293
294         size_type bytes() const;
295         void init() const;
296         
297         ///@}
298
299     protected:
300
301     private:
302         void setSize(size_type value);
303
304         Sizer sizer_;
305         state_type state_;
306         size_type i_;
307     };
308
309 }
310
311 ///////////////////////////////hh.e////////////////////////////////////////
312 #endif
313 #if !defined(HH_Packets__decls_) && !defined(HH_ParseVec_i_)
314 #define HH_ParseVec_i_
315 //#include "ParseVec.cci"
316 #include "ParseVec.ct"
317 #include "ParseVec.cti"
318 #endif
319
320 \f
321 // Local Variables:
322 // mode: c++
323 // fill-column: 100
324 // c-file-style: "senf"
325 // indent-tabs-mode: nil
326 // ispell-local-dictionary: "american"
327 // compile-command: "scons -u test"
328 // comment-column: 40
329 // End: