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