removed some useless spaces; not very important, I know :)
[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 signed bitfield with up to 32bit's
288         
289         This parser will parse a bitfield beginning at the bit \a Start and ending \e before \a
290         End. Bits are numbered <em>most significant bit first</em> as this is the customary
291         numbering used when defining packet data structures. \a Start and \a End can be \e
292         arbitrary as long as the field is between 1 and 32 bits in size. In other words, \c
293         IntFieldParser<53,81> is a valid 30 bit field.
294
295         When defining a compound parser with several bit fields, you need to take care of the fact,
296         that several integer field parsers will interpret the same data \e bytes (but not the same
297         \e bits). It is customary for several integer field parsers to start at the same byte offset
298         with ever increasing bit offsets.
299
300         \see parseint
301
302         \implementation The integer field parser is highly optimized. Since the bit positions are
303             compile-time constants, the compiler will create optimized bit-masks to directly access
304             the value. The parser is also optimized to access the minimum number of data bytes
305             necessary.
306         
307         \ingroup parseint
308      */
309     template <unsigned Start, unsigned End>
310     struct IntFieldParser
311         : public detail::packet::IntParserOps<IntFieldParser<Start,End>,boost::int32_t>,
312           public PacketParserBase
313     {
314         IntFieldParser(data_iterator i, state_type s) : PacketParserBase(i,s,fixed_bytes) {}
315
316         ///////////////////////////////////////////////////////////////////////////
317
318         typedef boost::int32_t value_type;
319         static size_type const start_bit = Start;
320         static size_type const end_bit = End;
321         static size_type const fixed_bytes = (End-1)/8+1;
322         static value_type const max_value = boost::low_bits_mask_t<End-Start-1>::sig_bits;
323         static value_type const min_value = - max_value - 1;
324
325
326         value_type value() const {
327             value_type v (detail::packet::parse_bitfield<Start,End>::parse(i()));
328             return v&boost::high_bit_mask_t<End-Start-1>::high_bit ?
329                 v | ~boost::low_bits_mask_t<End-Start>::sig_bits : v;
330         }
331         void value(value_type v) { detail::packet::parse_bitfield<Start,End>::write(i(),v); }
332         IntFieldParser const & operator= (value_type other) { value(other); return *this; }
333
334     private:
335         BOOST_STATIC_ASSERT( Start<End );
336         BOOST_STATIC_ASSERT( End-Start<=32 );
337     };
338     /** \brief Write parsed value to stream
339         \related IntFieldParser
340      */
341     template <unsigned Start, unsigned End>
342     inline std::ostream & operator<<(std::ostream & os, IntFieldParser<Start,End> const & i)
343     { os << i.value(); return os; }
344
345     /** \brief Parse unsigned bitfield with up to 32bit's
346         
347         This parser will parse a bitfield beginning at the bit \a Start and ending \e before \a
348         End. Bits are numbered <em>most significant bit first</em> as this is the customary
349         numbering used when defining packet data structures. \a Start and \a End can be \e
350         arbitrary as long as the field is between 1 and 32 bits in size. In other words, \c
351         IntFieldParser<53,81> is a valid 30 bit field.
352
353         When defining a compound parser with several bit fields, you need to take care of the fact,
354         that several integer field parsers will interpret the same data \e bytes (but not the same
355         \e bits). It is customary for several integer field parsers to start at the same byte offset
356         with ever increasing bit offsets.
357
358         \see parseint
359
360         \implementation The integer field parser is highly optimized. Since the bit positions are
361             compile-time constants, the compiler will create optimized bit-masks to directly access
362             the value. The parser is also optimized to access the minimum number of data bytes
363             necessary.
364         
365         \ingroup parseint
366      */
367     template <unsigned Start, unsigned End>
368     struct UIntFieldParser
369         : public detail::packet::IntParserOps<UIntFieldParser<Start,End>,boost::uint32_t>,
370           public PacketParserBase
371     {
372         UIntFieldParser(data_iterator i, state_type s) : PacketParserBase(i,s,fixed_bytes) {}
373
374         ///////////////////////////////////////////////////////////////////////////
375
376         typedef boost::uint32_t value_type;
377         static size_type const start_bit = Start;
378         static size_type const end_bit = End;
379         static size_type const fixed_bytes = (End-1)/8+1;
380         static value_type const min_value = 0u;
381         static value_type const max_value = boost::low_bits_mask_t<End-Start>::sig_bits;
382
383         value_type value() const { return detail::packet::parse_bitfield<Start,End>::parse(i()); }
384         void value(value_type v) { detail::packet::parse_bitfield<Start,End>::write(i(),v); }
385         UIntFieldParser const & operator= (value_type other) { value(other); return *this; }
386
387     private:
388         BOOST_STATIC_ASSERT( Start<End );
389         BOOST_STATIC_ASSERT( End-Start<=32 );
390     };
391     /** \brief Write parsed value to stream
392         \related UIntFieldParser
393      */
394     template <unsigned Start, unsigned End>
395     inline std::ostream & operator<<(std::ostream & os, UIntFieldParser<Start,End> const & i)
396     { os << i.value(); return os; }
397
398     /** \brief Parse single-bit flag
399
400         This parser will parse a single bit as True/False value. Bits are numbered <em>most
401         significant bit first</em> as this is the customary numbering used when defining packet data
402         structures. \a Bit can be arbitrary, \c FlagParser<75> is a valid flag parser.
403
404         When defining a compound parser with several bit fields, you need to take care of the fact,
405         that several integer field parsers will interpret the same data \e bytes (but not the same
406         \e bits). It is customary for several integer field parsers to start at the same byte offset
407         with ever increasing bit offsets.
408
409         \see parseint
410         \ingroup parseint
411      */
412     template <unsigned Bit>
413     struct FlagParser
414         : public detail::packet::IntParserOps<FlagParser<Bit>,bool>,
415           public PacketParserBase
416     {
417         FlagParser(data_iterator i, state_type s) : PacketParserBase(i,s,fixed_bytes) {}
418
419         ///////////////////////////////////////////////////////////////////////////
420
421         typedef bool value_type;
422         static size_type const bit = Bit;
423         static size_type const fixed_bytes = Bit/8+1;
424         static value_type const min_value = 0;
425         static value_type const max_value = 1;
426
427         value_type value() const { return i()[Bit/8] & (1<<(7-(Bit%8))); }
428         void value(value_type v) {
429             if (v) i()[0] |= 1<<(7-(Bit%8));
430             else   i()[0] &= ~(1<<(7-(Bit%8)));
431         }
432         FlagParser const & operator= (value_type other) { value(other); return *this; }
433     };
434     /** \brief Write parsed value to stream
435         \related FlagParser
436      */
437     template <unsigned Bit>
438     inline std::ostream & operator<<(std::ostream & os, FlagParser<Bit> const & i)
439     { os << i.value(); return os; }
440
441 }
442
443 ///////////////////////////////hh.e////////////////////////////////////////
444 #endif
445 #if !defined(HH_Packets__decls_) && !defined(HH_IntParser_i_)
446 #define HH_IntParser_i_
447 //#include "IntParser.cci"
448 //#include "IntParser.ct"
449 //#include "IntParser.cti"
450 #endif
451
452 \f
453 // Local Variables:
454 // mode: c++
455 // fill-column: 100
456 // c-file-style: "senf"
457 // indent-tabs-mode: nil
458 // ispell-local-dictionary: "american"
459 // compile-command: "scons -u test"
460 // comment-column: 40
461 // End: