eb51170b63a3b6084f248fba8c6b88bef08e15ef
[senf.git] / Packets / IntParser.hh
1 // $Id$
2 //
3 // Copyright (C) 2006
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY
6 //     Stefan Bund <g0dil@berlios.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 IntParser public header */
25
26 #ifndef HH_IntParser_
27 #define HH_IntParser_ 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 "IntParser.mpp"
37 ///////////////////////////////hh.p////////////////////////////////////////
38 #include "IntParser.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 Int8Parser
74         : public detail::packet::IntParserOps<Int8Parser,boost::int8_t>,
75           public PacketParserBase
76     {
77         Int8Parser(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         Int8Parser const & operator= (value_type other) { value(other); return *this; }
89     };
90     /** \brief Write parsed value to stream
91         \related Int8Parser
92      */
93     inline std::ostream & operator<<(std::ostream & os, Int8Parser 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 UInt8Parser
101         : public detail::packet::IntParserOps<UInt8Parser,boost::uint8_t>,
102           public PacketParserBase
103     {
104         UInt8Parser(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         UInt8Parser const & operator= (value_type other) { value(other); return *this; }
116     };
117     /** \brief Write parsed value to stream
118         \related UInt8Parser
119      */
120     inline std::ostream & operator<<(std::ostream & os, UInt8Parser 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 Int16Parser
128         : public detail::packet::IntParserOps<Int16Parser,boost::int16_t>,
129           public PacketParserBase
130     {
131         Int16Parser(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         Int16Parser const & operator= (value_type other) { value(other); return *this; }
144     };
145     /** \brief Write parsed value to stream
146         \related Int16Parser
147      */
148     inline std::ostream & operator<<(std::ostream & os, Int16Parser 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 UInt16Parser
156         : public detail::packet::IntParserOps<UInt16Parser,boost::uint16_t>,
157           public PacketParserBase
158     {
159         UInt16Parser(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         UInt16Parser const & operator= (value_type other) { value(other); return *this; }
171     };
172     /** \brief Write parsed value to stream
173         \related UInt16Parser
174      */
175     inline std::ostream & operator<<(std::ostream & os, UInt16Parser 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 Int24Parser
183         : public detail::packet::IntParserOps<Int24Parser,boost::int32_t>,
184           public PacketParserBase
185     {
186         Int24Parser(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         Int24Parser const & operator= (value_type other) { value(other); return *this; }
199     };
200     /** \brief Write parsed value to stream
201         \related Int24Parser
202      */
203     inline std::ostream & operator<<(std::ostream & os, Int24Parser 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 UInt24Parser
211         : public detail::packet::IntParserOps<UInt24Parser,boost::uint32_t>,
212           public PacketParserBase
213     {
214         UInt24Parser(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         UInt24Parser const & operator= (value_type other) { value(other); return *this; }
226     };
227     /** \brief Write parsed value to stream
228         \related UInt24Parser
229      */
230     inline std::ostream & operator<<(std::ostream & os, UInt24Parser 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 Int32Parser
238         : public detail::packet::IntParserOps<Int32Parser,boost::int32_t>,
239           public PacketParserBase
240     {
241         Int32Parser(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         Int32Parser const & operator= (value_type other) { value(other); return *this; }
253     };
254     /** \brief Write parsed value to stream
255         \related Int32Parser
256      */
257     inline std::ostream & operator<<(std::ostream & os, Int32Parser 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 UInt32Parser
265         : public detail::packet::IntParserOps<UInt32Parser,boost::uint32_t>,
266           public PacketParserBase
267     {
268         UInt32Parser(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         UInt32Parser const & operator= (value_type other) { value(other); return *this; }
280     };
281     /** \brief Write parsed value to stream
282         \related UInt32Parser
283      */
284     inline std::ostream & operator<<(std::ostream & os, UInt32Parser const & i)
285     { os << i.value(); return os; }
286
287     /** \brief Parse 64bit signed byte aligned integer
288         \see parseint
289         \ingroup parseint
290      */
291     struct Int64Parser
292         : public detail::packet::IntParserOps<Int64Parser,boost::int64_t>,
293           public PacketParserBase
294     {
295         Int64Parser(data_iterator i, state_type s) : PacketParserBase(i,s,fixed_bytes) {}
296
297         ///////////////////////////////////////////////////////////////////////////
298
299         typedef boost::int64_t value_type;
300         static size_type const fixed_bytes = 8;
301
302         value_type value() const { return detail::packet::parse_uint64(i()); }
303         void value(value_type v) { detail::packet::write_uint64(i(),v); }
304         Int64Parser const & operator= (value_type other) { value(other); return *this; }
305     };
306     /** \brief Write parsed value to stream
307         \related Int64Parser
308     */
309     inline std::ostream & operator<<(std::ostream & os, Int64Parser const & i)
310     { os << i.value(); return os; }
311
312
313     /** \brief Parse 64bit unsigned byte aligned integer
314         \see parseint
315         \ingroup parseint
316      */
317     struct UInt64Parser
318         : public detail::packet::IntParserOps<UInt64Parser,boost::uint64_t>,
319           public PacketParserBase
320     {
321         UInt64Parser(data_iterator i, state_type s) : PacketParserBase(i,s,fixed_bytes) {}
322
323         ///////////////////////////////////////////////////////////////////////////
324
325         typedef boost::uint64_t value_type;
326         static size_type const fixed_bytes = 8;
327
328         value_type value() const { return detail::packet::parse_uint64(i()); }
329         void value(value_type v) { detail::packet::write_uint64(i(),v); }
330         UInt64Parser const & operator= (value_type other) { value(other); return *this; }
331     };
332     /** \brief Write parsed value to stream
333         \related UInt64Parser
334      */
335     inline std::ostream & operator<<(std::ostream & os, UInt64Parser const & i)
336     { os << i.value(); return os; }
337
338
339     /** \brief Parse signed bitfield with up to 32bit's
340
341         This parser will parse a bitfield beginning at the bit \a Start and ending \e before \a
342         End. Bits are numbered <em>most significant bit first</em> as this is the customary
343         numbering used when defining packet data structures. \a Start and \a End can be \e
344         arbitrary as long as the field is between 1 and 32 bits in size. In other words, \c
345         IntFieldParser<53,81> is a valid 30 bit field.
346
347         When defining a compound parser with several bit fields, you need to take care of the fact,
348         that several integer field parsers will interpret the same data \e bytes (but not the same
349         \e bits). It is customary for several integer field parsers to start at the same byte offset
350         with ever increasing bit offsets.
351
352         \see parseint
353
354         \implementation The integer field parser is highly optimized. Since the bit positions are
355             compile-time constants, the compiler will create optimized bit-masks to directly access
356             the value. The parser is also optimized to access the minimum number of data bytes
357             necessary.
358
359         \ingroup parseint
360      */
361     template <unsigned Start, unsigned End>
362     struct IntFieldParser
363         : public detail::packet::IntParserOps<IntFieldParser<Start,End>,boost::int32_t>,
364           public PacketParserBase
365     {
366         IntFieldParser(data_iterator i, state_type s) : PacketParserBase(i,s,fixed_bytes) {}
367
368         ///////////////////////////////////////////////////////////////////////////
369
370         typedef boost::int32_t value_type;
371         static size_type const start_bit = Start;
372         static size_type const end_bit = End;
373         static size_type const fixed_bytes = (End-1)/8+1;
374         static value_type const max_value = boost::low_bits_mask_t<End-Start-1>::sig_bits;
375         static value_type const min_value = - max_value - 1;
376
377
378         value_type value() const {
379             value_type v (detail::packet::parse_bitfield<Start,End>::parse(i()));
380             return v&boost::high_bit_mask_t<End-Start-1>::high_bit ?
381                 v | ~boost::low_bits_mask_t<End-Start>::sig_bits : v;
382         }
383         void value(value_type v) { detail::packet::parse_bitfield<Start,End>::write(i(),v); }
384         IntFieldParser const & operator= (value_type other) { value(other); return *this; }
385
386     private:
387         BOOST_STATIC_ASSERT( Start<End );
388         BOOST_STATIC_ASSERT( End-Start<=32 );
389     };
390     /** \brief Write parsed value to stream
391         \related IntFieldParser
392      */
393     template <unsigned Start, unsigned End>
394     inline std::ostream & operator<<(std::ostream & os, IntFieldParser<Start,End> const & i)
395     { os << i.value(); return os; }
396
397     /** \brief Parse unsigned bitfield with up to 32bit's
398
399         This parser will parse a bitfield beginning at the bit \a Start and ending \e before \a
400         End. Bits are numbered <em>most significant bit first</em> as this is the customary
401         numbering used when defining packet data structures. \a Start and \a End can be \e
402         arbitrary as long as the field is between 1 and 32 bits in size. In other words, \c
403         IntFieldParser<53,81> is a valid 30 bit field.
404
405         When defining a compound parser with several bit fields, you need to take care of the fact,
406         that several integer field parsers will interpret the same data \e bytes (but not the same
407         \e bits). It is customary for several integer field parsers to start at the same byte offset
408         with ever increasing bit offsets.
409
410         \see parseint
411
412         \implementation The integer field parser is highly optimized. Since the bit positions are
413             compile-time constants, the compiler will create optimized bit-masks to directly access
414             the value. The parser is also optimized to access the minimum number of data bytes
415             necessary.
416
417         \ingroup parseint
418      */
419     template <unsigned Start, unsigned End>
420     struct UIntFieldParser
421         : public detail::packet::IntParserOps<UIntFieldParser<Start,End>,boost::uint32_t>,
422           public PacketParserBase
423     {
424         UIntFieldParser(data_iterator i, state_type s) : PacketParserBase(i,s,fixed_bytes) {}
425
426         ///////////////////////////////////////////////////////////////////////////
427
428         typedef boost::uint32_t value_type;
429         static size_type const start_bit = Start;
430         static size_type const end_bit = End;
431         static size_type const fixed_bytes = (End-1)/8+1;
432         static value_type const min_value = 0u;
433         static value_type const max_value = boost::low_bits_mask_t<End-Start>::sig_bits;
434
435         value_type value() const { return detail::packet::parse_bitfield<Start,End>::parse(i()); }
436         void value(value_type v) { detail::packet::parse_bitfield<Start,End>::write(i(),v); }
437         UIntFieldParser const & operator= (value_type other) { value(other); return *this; }
438
439     private:
440         BOOST_STATIC_ASSERT( Start<End );
441         BOOST_STATIC_ASSERT( End-Start<=32 );
442     };
443     /** \brief Write parsed value to stream
444         \related UIntFieldParser
445      */
446     template <unsigned Start, unsigned End>
447     inline std::ostream & operator<<(std::ostream & os, UIntFieldParser<Start,End> const & i)
448     { os << i.value(); return os; }
449
450     /** \brief Parse single-bit flag
451
452         This parser will parse a single bit as True/False value. Bits are numbered <em>most
453         significant bit first</em> as this is the customary numbering used when defining packet data
454         structures. \a Bit can be arbitrary, \c FlagParser<75> is a valid flag parser.
455
456         When defining a compound parser with several bit fields, you need to take care of the fact,
457         that several integer field parsers will interpret the same data \e bytes (but not the same
458         \e bits). It is customary for several integer field parsers to start at the same byte offset
459         with ever increasing bit offsets.
460
461         \see parseint
462         \ingroup parseint
463      */
464     template <unsigned Bit>
465     struct FlagParser
466         : public detail::packet::IntParserOps<FlagParser<Bit>,bool>,
467           public PacketParserBase
468     {
469         FlagParser(data_iterator i, state_type s) : PacketParserBase(i,s,fixed_bytes) {}
470
471         ///////////////////////////////////////////////////////////////////////////
472
473         typedef bool value_type;
474         static size_type const bit = Bit;
475         static size_type const fixed_bytes = Bit/8+1;
476         static value_type const min_value = 0;
477         static value_type const max_value = 1;
478
479         value_type value() const { return i()[Bit/8] & (1<<(7-(Bit%8))); }
480         void value(value_type v) {
481             if (v) i()[Bit/8] |= 1<<(7-(Bit%8));
482             else   i()[Bit/8] &= ~(1<<(7-(Bit%8)));
483         }
484         FlagParser const & operator= (value_type other) { value(other); return *this; }
485     };
486     /** \brief Write parsed value to stream
487         \related FlagParser
488      */
489     template <unsigned Bit>
490     inline std::ostream & operator<<(std::ostream & os, FlagParser<Bit> const & i)
491     { os << i.value(); return os; }
492
493 }
494
495 ///////////////////////////////hh.e////////////////////////////////////////
496 #endif
497 #if !defined(HH_Packets__decls_) && !defined(HH_IntParser_i_)
498 #define HH_IntParser_i_
499 //#include "IntParser.cci"
500 //#include "IntParser.ct"
501 //#include "IntParser.cti"
502 #endif
503
504
505 // Local Variables:
506 // mode: c++
507 // fill-column: 100
508 // c-file-style: "senf"
509 // indent-tabs-mode: nil
510 // ispell-local-dictionary: "american"
511 // compile-command: "scons -u test"
512 // comment-column: 40
513 // End: