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