Utils/Logger: Implement TimeSource facility
[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 Define Parse_VectorN field
141         
142         This macro is a special helper to define a senf::Parse_VectorN type field, a vector of
143         elements of type \a elt_type (a parser) directly preceded by a numeric size field of type \a
144         size_type (another parser).
145         
146         \param[in] name field name
147         \param[in] elt_type vector element type
148         \param[in] size_type size type
149         \hideinitializer
150         \ingroup packetparsermacros
151      */
152 #   define SENF_PARSER_VEC_N(name, elt_type, size_type)                                           \
153         typedef senf::Parse_VectorN<elt_type, size_type>::parser BOOST_PP_CAT(name, _vec_t);      \
154         SENF_PARSER_FIELD( name, BOOST_PP_CAT(name, _vec_t) )
155
156     /** \brief Parse_Vector container wrapper
157
158         This is the container wrapper used for vector parsers. The container wrapper will stay valid
159         after changing the collection. However the container still depends on the packet and will be
160         invalidated if the Packet is deallocated or if the packet size is changed from without the
161         container wrapper (more precisely, it is invalided if the insertion/deletion happens before
162         the vector in the packet data).
163
164         The vector container wrapper provides a complete STL random-access sequence interface.
165         
166         \code
167         SomePacket p (...);
168         SomePacket::aVectorCollection_t::container c (p->aVectorCollection());
169         c.insert(c.begin(), ... );
170         \endcode
171
172         \see Parse_Vector
173       */
174     template <class ElementParser, class Sizer>
175     class Parse_Vector_Container
176     {
177     public:
178         ///////////////////////////////////////////////////////////////////////////
179         // Types
180
181         typedef Parse_Vector<ElementParser,Sizer> parser_type;
182         typedef PacketParserBase::data_iterator data_iterator;
183         typedef PacketParserBase::size_type size_type;
184         typedef PacketParserBase::difference_type difference_type;
185         typedef ElementParser value_type;
186         typedef detail::Parse_Array_iterator<value_type> iterator;
187         typedef iterator const_iterator;
188         typedef PacketParserBase::state_type state_type;
189
190         ///////////////////////////////////////////////////////////////////////////
191         ///\name Structors and default members
192         ///@{
193
194         // no default constructor
195         // default copy
196         // default destructor
197         // conversion constructors
198
199         Parse_Vector_Container(parser_type const & vector);
200
201         ///@}
202         ///////////////////////////////////////////////////////////////////////////
203
204         ///\name Accessors
205         ///@{
206
207         size_type size() const;
208         bool empty() const;
209
210         iterator begin() const;
211         iterator end() const;
212
213         value_type operator[](difference_type i) const;
214         value_type front() const;
215         value_type back() const;
216
217         ///@}
218         ///\name Mutators
219         ///@{
220
221         iterator shift(iterator pos, size_type n=1);
222         template <class Value>
223         void insert(iterator pos, Value const & t);
224         template <class Value>
225         void insert(iterator pos, size_type n, Value const & t);
226 #       ifndef DOXYGEN
227         template <class ForwardIterator>
228         void insert(iterator pos, ForwardIterator f, ForwardIterator l,
229                     typename boost::disable_if< boost::is_convertible<ForwardIterator,size_type> >::type * = 0);
230 #       else
231         template <class ForwardIterator>
232         void insert(iterator pos, ForwardIterator f, ForwardIterator l);
233 #       endif
234
235         void erase(iterator pos, size_type n=1);
236         void erase(iterator f, iterator l);
237         void clear();
238
239         template <class Value> void push_back        (Value value, size_type n=1);
240                                void push_back_space  (size_type n=1);
241         template <class Value> void push_front       (Value value, size_type n=1);
242                                void push_front_space (size_type n=1);
243                                void resize           (size_type n);
244         template <class Value> void resize           (size_type n, Value value);
245
246         ///@}
247
248         ///\name Parser interface
249         ///@{
250
251         parser_type parser() const;
252         data_iterator i() const;
253         state_type state() const;
254         PacketData & data() const;
255
256         size_type bytes() const;
257         void init() const;
258         
259         ///@}
260
261     protected:
262
263     private:
264         void setSize(size_type value);
265
266         Sizer sizer_;
267         state_type state_;
268         size_type i_;
269     };
270
271 }
272
273 ///////////////////////////////hh.e////////////////////////////////////////
274 #endif
275 #if !defined(HH_Packets__decls_) && !defined(HH_ParseVec_i_)
276 #define HH_ParseVec_i_
277 //#include "ParseVec.cci"
278 #include "ParseVec.ct"
279 #include "ParseVec.cti"
280 #endif
281
282 \f
283 // Local Variables:
284 // mode: c++
285 // fill-column: 100
286 // c-file-style: "senf"
287 // indent-tabs-mode: nil
288 // ispell-local-dictionary: "american"
289 // compile-command: "scons -u test"
290 // comment-column: 40
291 // End: