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