Socket: BUGFIX: Explicitly copy image
[senf.git] / Packets / ParseInt.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 #ifndef HH_ParseInt_
24 #define HH_ParseInt_ 1
25
26 // Custom includes
27 #include <iostream>
28 #include <boost/cstdint.hpp>
29 #include <boost/static_assert.hpp>
30 #include <boost/integer/integer_mask.hpp>
31 #include "PacketParser.hh"
32
33 //#include "ParseInt.mpp"
34 ///////////////////////////////hh.p////////////////////////////////////////
35 #include "ParseInt.ih"
36
37 namespace senf {
38
39     /** \defgroup parseint Integer parsers
40
41         Most packet fields will ultimately contain some type of integral number. The integer parsers
42         allow to parse arbitrary integers in network byte order from 1-32 bit, both signed and
43         unsigned. There are two types of integer parsers:
44
45         \li The normal integer parsers with interpret 1-4 byte integers (9, 16, 24, 32 bits) aligned
46             at byte boundaries.
47         \li The bitfield parsers which parse integers with 1-32 bits aligned at any bit. A special
48             case is the single bit flag parser.
49
50         All fields are parsed in network byte order, the return value of all these parsers is the
51         value in host byte order.
52
53         The interface of all these parsers is the same (p is an arbitrary integer parser instance, v
54         is an integer constant):
55
56         \li <tt>p = v</tt>: Assigns the value to the packet field.
57         \li <tt>p.value(v)</tt>: same as above.
58         \li <tt>p.value()</tt>: Returns the fields value as an integer number.
59         \li Use of p like an integer in most contexts: <tt>p += v</tt>, <tt>p *= v</tt>, <tt>v = p +
60             1</tt> and so on. You will only need to use the explicit \c value() member in rare
61             circumstances when the automatic conversion is ambiguous or in some template contexts.
62
63         \ingroup packetparser
64      */
65
66     /** \brief Parse 8bit signed byte aligned integer
67         \see parseint
68         \ingroup parseint
69      */
70     struct Parse_Int8
71         : public detail::packet::ParseIntOps<Parse_Int8,boost::int8_t>,
72           public PacketParserBase
73     {
74         Parse_Int8(data_iterator i, state_type s) : PacketParserBase(i,s,fixed_bytes) {}
75
76         ///////////////////////////////////////////////////////////////////////////
77
78         typedef boost::int8_t value_type;
79         static size_type const fixed_bytes = 1;
80
81         value_type value() const { return i()[0]; }
82         void value(value_type v) { i()[0] = v; }
83         Parse_Int8 const & operator= (value_type other) { value(other); return *this; }
84     };
85     /** \brief Write parsed value to stream
86         \related Parse_Int8
87      */
88     inline std::ostream & operator<<(std::ostream & os, Parse_Int8 const & i)
89     { os << i.value(); return os; }
90
91     /** \brief Parse 8bit unsigned byte aligned integer
92         \see parseint
93         \ingroup parseint
94      */
95     struct Parse_UInt8
96         : public detail::packet::ParseIntOps<Parse_UInt8,boost::uint8_t>,
97           public PacketParserBase
98     {
99         Parse_UInt8(data_iterator i, state_type s) : PacketParserBase(i,s,fixed_bytes) {}
100
101         ///////////////////////////////////////////////////////////////////////////
102
103         typedef boost::uint8_t value_type;
104         static size_type const fixed_bytes = 1;
105
106         value_type value() const { return i()[0]; }
107         void value(value_type v) { i()[0] = v; }
108         Parse_UInt8 const & operator= (value_type other) { value(other); return *this; }
109     };
110     /** \brief Write parsed value to stream
111         \related Parse_UInt8
112      */
113     inline std::ostream & operator<<(std::ostream & os, Parse_UInt8 const & i)
114     { os << i.value(); return os; }
115
116     /** \brief Parse 16bit signed byte aligned integer
117         \see parseint
118         \ingroup parseint
119      */
120     struct Parse_Int16
121         : public detail::packet::ParseIntOps<Parse_Int16,boost::int16_t>,
122           public PacketParserBase
123     {
124         Parse_Int16(data_iterator i, state_type s) : PacketParserBase(i,s,fixed_bytes) {}
125
126         ///////////////////////////////////////////////////////////////////////////
127
128         typedef boost::int16_t value_type;
129         static size_type const fixed_bytes = 2;
130
131         value_type value() const { return detail::packet::parse_uint16(i()); }
132         void value(value_type v) { detail::packet::write_uint16(i(),v); }
133         Parse_Int16 const & operator= (value_type other) { value(other); return *this; }
134     };
135     /** \brief Write parsed value to stream
136         \related Parse_Int16
137      */
138     inline std::ostream & operator<<(std::ostream & os, Parse_Int16 const & i)
139     { os << i.value(); return os; }
140
141     /** \brief Parse 16bit unsigned byte aligned integer
142         \see parseint
143         \ingroup parseint
144      */
145     struct Parse_UInt16
146         : public detail::packet::ParseIntOps<Parse_UInt16,boost::uint16_t>,
147           public PacketParserBase
148     {
149         Parse_UInt16(data_iterator i, state_type s) : PacketParserBase(i,s,fixed_bytes) {}
150
151         ///////////////////////////////////////////////////////////////////////////
152
153         typedef boost::uint16_t value_type;
154         static size_type const fixed_bytes = 2;
155
156         value_type value() const { return detail::packet::parse_uint16(i()); }
157         void value(value_type v) { detail::packet::write_uint16(i(),v); }
158         Parse_UInt16 const & operator= (value_type other) { value(other); return *this; }
159     };
160     /** \brief Write parsed value to stream
161         \related Parse_UInt16
162      */
163     inline std::ostream & operator<<(std::ostream & os, Parse_UInt16 const & i)
164     { os << i.value(); return os; }
165
166     /** \brief Parse 24bit signed byte aligned integer
167         \see parseint
168         \ingroup parseint
169      */
170     struct Parse_Int24
171         : public detail::packet::ParseIntOps<Parse_Int24,boost::int32_t>,
172           public PacketParserBase
173     {
174         Parse_Int24(data_iterator i, state_type s) : PacketParserBase(i,s,fixed_bytes) {}
175
176         ///////////////////////////////////////////////////////////////////////////
177
178         typedef boost::int32_t value_type;
179         static size_type const fixed_bytes = 3;
180
181         value_type value() const {
182             value_type v (detail::packet::parse_uint24(i())); return v&0x800000 ? v|0xff000000 : v; }
183         void value(value_type v) { detail::packet::write_uint24(i(),v); }
184         Parse_Int24 const & operator= (value_type other) { value(other); return *this; }
185     };
186     /** \brief Write parsed value to stream
187         \related Parse_Int24
188      */
189     inline std::ostream & operator<<(std::ostream & os, Parse_Int24 const & i)
190     { os << i.value(); return os; }
191
192     /** \brief Parse 24bit unsigned byte aligned integer
193         \see parseint
194         \ingroup parseint
195      */
196     struct Parse_UInt24
197         : public detail::packet::ParseIntOps<Parse_UInt24,boost::uint32_t>,
198           public PacketParserBase
199     {
200         Parse_UInt24(data_iterator i, state_type s) : PacketParserBase(i,s,fixed_bytes) {}
201
202         ///////////////////////////////////////////////////////////////////////////
203
204         typedef boost::uint32_t value_type;
205         static size_type const fixed_bytes = 3;
206
207         value_type value() const { return detail::packet::parse_uint24(i()); }
208         void value(value_type v) { detail::packet::write_uint24(i(),v); }
209         Parse_UInt24 const & operator= (value_type other) { value(other); return *this; }
210     };
211     /** \brief Write parsed value to stream
212         \related Parse_UInt24
213      */
214     inline std::ostream & operator<<(std::ostream & os, Parse_UInt24 const & i)
215     { os << i.value(); return os; }
216
217     /** \brief Parse 32bit signed byte aligned integer
218         \see parseint
219         \ingroup parseint
220      */
221     struct Parse_Int32
222         : public detail::packet::ParseIntOps<Parse_Int32,boost::int32_t>,
223           public PacketParserBase
224     {
225         Parse_Int32(data_iterator i, state_type s) : PacketParserBase(i,s,fixed_bytes) {}
226
227         ///////////////////////////////////////////////////////////////////////////
228
229         typedef boost::int32_t value_type;
230         static size_type const fixed_bytes = 4;
231
232         value_type value() const { return detail::packet::parse_uint32(i()); }
233         void value(value_type v) { detail::packet::write_uint32(i(),v); }
234         Parse_Int32 const & operator= (value_type other) { value(other); return *this; }
235     };
236     /** \brief Write parsed value to stream
237         \related Parse_Int32
238      */
239     inline std::ostream & operator<<(std::ostream & os, Parse_Int32 const & i)
240     { os << i.value(); return os; }
241
242     /** \brief Parse 32bit unsigned byte aligned integer
243         \see parseint
244         \ingroup parseint
245      */
246     struct Parse_UInt32
247         : public detail::packet::ParseIntOps<Parse_UInt32,boost::uint32_t>,
248           public PacketParserBase
249     {
250         Parse_UInt32(data_iterator i, state_type s) : PacketParserBase(i,s,fixed_bytes) {}
251
252         ///////////////////////////////////////////////////////////////////////////
253
254         typedef boost::uint32_t value_type;
255         static size_type const fixed_bytes = 4;
256
257         value_type value() const { return detail::packet::parse_uint32(i()); }
258         void value(value_type v) { detail::packet::write_uint32(i(),v); }
259         Parse_UInt32 const & operator= (value_type other) { value(other); return *this; }
260     };
261     /** \brief Write parsed value to stream
262         \related Parse_UInt32
263      */
264     inline std::ostream & operator<<(std::ostream & os, Parse_UInt32 const & i)
265     { os << i.value(); return os; }
266
267     /** \brief Parse signed bitfield with up to 32bit's
268         
269         This parser will parse a bitfield beginning at the bit \a Start and ending \e before \a
270         End. Bits are numbered <em>most significant bit first</em> as this is the customary
271         numbering used when defining packet data structures. \a Start and \a End can be \e
272         arbitrary as long as the field is between 1 and 32 bits in size. In other words, \c
273         Parse_IntField<53,81> is a valid 30 bit field.
274
275         When defining a compound parser with several bit fields, you need to take care of the fact,
276         that several integer field parsers will interpret the same data \e bytes (but not the same
277         \e bits). It is customary for several integer field parsers to start at the same byte offset
278         with ever increasing bit offsets.
279
280         \see parseint
281
282         \implementation The integer field parser is highly optimized. Since the bit positions are
283             compile-time constants, the compiler will create optimized bit-masks to directly access
284             the value. The parser is also optimized to access the minimum number of data bytes
285             necessary.
286         
287         \ingroup parseint
288      */
289     template <unsigned Start, unsigned End>
290     struct Parse_IntField
291         : public detail::packet::ParseIntOps<Parse_IntField<Start,End>,boost::int32_t>,
292           public PacketParserBase
293     {
294         Parse_IntField(data_iterator i, state_type s) : PacketParserBase(i,s,fixed_bytes) {}
295
296         ///////////////////////////////////////////////////////////////////////////
297
298         typedef boost::int32_t value_type;
299         static size_type const fixed_bytes = (End-1)/8+1;
300
301         value_type value() const {
302             value_type v (detail::packet::parse_bitfield<Start,End>::parse(i()));
303             return v&boost::high_bit_mask_t<End-Start-1>::high_bit ?
304                 v | ~boost::low_bits_mask_t<End-Start>::sig_bits : v;
305         }
306         void value(value_type v) { detail::packet::parse_bitfield<Start,End>::write(i(),v); }
307         Parse_IntField const & operator= (value_type other) { value(other); return *this; }
308
309     private:
310         BOOST_STATIC_ASSERT( Start<End );
311         BOOST_STATIC_ASSERT( End-Start<=32 );
312     };
313     /** \brief Write parsed value to stream
314         \related Parse_IntField
315      */
316     template <unsigned Start, unsigned End>
317     inline std::ostream & operator<<(std::ostream & os, Parse_IntField<Start,End> const & i)
318     { os << i.value(); return os; }
319
320     /** \brief Parse unsigned bitfield with up to 32bit's
321         
322         This parser will parse a bitfield beginning at the bit \a Start and ending \e before \a
323         End. Bits are numbered <em>most significant bit first</em> as this is the customary
324         numbering used when defining packet data structures. \a Start and \a End can be \e
325         arbitrary as long as the field is between 1 and 32 bits in size. In other words, \c
326         Parse_IntField<53,81> is a valid 30 bit field.
327
328         When defining a compound parser with several bit fields, you need to take care of the fact,
329         that several integer field parsers will interpret the same data \e bytes (but not the same
330         \e bits). It is customary for several integer field parsers to start at the same byte offset
331         with ever increasing bit offsets.
332
333         \see parseint
334
335         \implementation The integer field parser is highly optimized. Since the bit positions are
336             compile-time constants, the compiler will create optimized bit-masks to directly access
337             the value. The parser is also optimized to access the minimum number of data bytes
338             necessary.
339         
340         \ingroup parseint
341      */
342     template <unsigned Start, unsigned End>
343     struct Parse_UIntField
344         : public detail::packet::ParseIntOps<Parse_UIntField<Start,End>,boost::uint32_t>,
345           public PacketParserBase
346     {
347         Parse_UIntField(data_iterator i, state_type s) : PacketParserBase(i,s,fixed_bytes) {}
348
349         ///////////////////////////////////////////////////////////////////////////
350
351         typedef boost::uint32_t value_type;
352         static size_type const fixed_bytes = (End-1)/8+1;
353
354         value_type value() const { return detail::packet::parse_bitfield<Start,End>::parse(i()); }
355         void value(value_type v) { detail::packet::parse_bitfield<Start,End>::write(i(),v); }
356         Parse_UIntField const & operator= (value_type other) { value(other); return *this; }
357
358     private:
359         BOOST_STATIC_ASSERT( Start<End );
360         BOOST_STATIC_ASSERT( End-Start<=32 );
361     };
362     /** \brief Write parsed value to stream
363         \related Parse_UIntField
364      */
365     template <unsigned Start, unsigned End>
366     inline std::ostream & operator<<(std::ostream & os, Parse_UIntField<Start,End> const & i)
367     { os << i.value(); return os; }
368
369     /** \brief Parse single-bit flag
370
371         This parser will parse a single bit as True/False value. Bits are numbered <em>most
372         significant bit first</em> as this is the customary numbering used when defining packet data
373         structures. \a Bit can be arbitrary, \c Parse_Flag<75> is a valid flag parser.
374
375         When defining a compound parser with several bit fields, you need to take care of the fact,
376         that several integer field parsers will interpret the same data \e bytes (but not the same
377         \e bits). It is customary for several integer field parsers to start at the same byte offset
378         with ever increasing bit offsets.
379
380         \see parseint
381         \ingroup parseint
382      */
383     template <unsigned Bit>
384     struct Parse_Flag
385         : public detail::packet::ParseIntOps<Parse_Flag<Bit>,bool>,
386           public PacketParserBase
387     {
388         Parse_Flag(data_iterator i, state_type s) : PacketParserBase(i,s,fixed_bytes) {}
389
390         ///////////////////////////////////////////////////////////////////////////
391
392         typedef bool value_type;
393         static size_type const fixed_bytes = Bit/8+1;
394
395         value_type value() const { return i()[Bit/8] & (1<<(7-(Bit%8))); }
396         void value(value_type v) {
397             if (v) i()[0] |= 1<<(7-(Bit%8));
398             else   i()[0] &= ~(1<<(7-(Bit%8)));
399         }
400         Parse_Flag const & operator= (value_type other) { value(other); return *this; }
401     };
402     /** \brief Write parsed value to stream
403         \related Parse_Flag
404      */
405     template <unsigned Bit>
406     inline std::ostream & operator<<(std::ostream & os, Parse_Flag<Bit> const & i)
407     { os << i.value(); return os; }
408
409 }
410
411 ///////////////////////////////hh.e////////////////////////////////////////
412 #endif
413 #if !defined(SENF_PACKETS_DECL_ONLY) && !defined(HH_ParseInt_i_)
414 #define HH_ParseInt_i_
415 //#include "ParseInt.cci"
416 //#include "ParseInt.ct"
417 //#include "ParseInt.cti"
418 #endif
419
420 \f
421 // Local Variables:
422 // mode: c++
423 // fill-column: 100
424 // c-file-style: "senf"
425 // indent-tabs-mode: nil
426 // ispell-local-dictionary: "american"
427 // compile-command: "scons -u test"
428 // comment-column: 40
429 // End: