4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY
6 // Stefan Bund <g0dil@berlios.de>
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.
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.
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.
24 \brief IntParser public header */
27 #define HH_IntParser_ 1
31 #include <boost/cstdint.hpp>
32 #include <boost/static_assert.hpp>
33 #include <boost/integer/integer_mask.hpp>
34 #include "PacketParser.hh"
36 //#include "IntParser.mpp"
37 ///////////////////////////////hh.p////////////////////////////////////////
38 #include "IntParser.ih"
42 /** \defgroup parseint Integer parsers
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:
48 \li The normal integer parsers with interpret 1-4 byte integers (9, 16, 24, 32 bits) aligned
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.
53 All fields are parsed in network byte order, the return value of all these parsers is the
54 value in host byte order.
56 The interface of all these parsers is the same (p is an arbitrary integer parser instance, v
57 is an integer constant):
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.
69 /** \brief Parse 8bit signed byte aligned integer
74 : public detail::packet::IntParserOps<Int8Parser,boost::int8_t>,
75 public PacketParserBase
77 Int8Parser(data_iterator i, state_type s) : PacketParserBase(i,s,fixed_bytes) {}
79 ///////////////////////////////////////////////////////////////////////////
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;
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; }
90 /** \brief Write parsed value to stream
93 inline std::ostream & operator<<(std::ostream & os, Int8Parser const & i)
94 { os << i.value(); return os; }
96 /** \brief Parse 8bit unsigned byte aligned integer
101 : public detail::packet::IntParserOps<UInt8Parser,boost::uint8_t>,
102 public PacketParserBase
104 UInt8Parser(data_iterator i, state_type s) : PacketParserBase(i,s,fixed_bytes) {}
106 ///////////////////////////////////////////////////////////////////////////
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;
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; }
117 /** \brief Write parsed value to stream
120 inline std::ostream & operator<<(std::ostream & os, UInt8Parser const & i)
121 { os << i.value(); return os; }
123 /** \brief Parse 16bit signed byte aligned integer
128 : public detail::packet::IntParserOps<Int16Parser,boost::int16_t>,
129 public PacketParserBase
131 Int16Parser(data_iterator i, state_type s) : PacketParserBase(i,s,fixed_bytes) {}
133 ///////////////////////////////////////////////////////////////////////////
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;
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; }
145 /** \brief Write parsed value to stream
148 inline std::ostream & operator<<(std::ostream & os, Int16Parser const & i)
149 { os << i.value(); return os; }
151 /** \brief Parse 16bit unsigned byte aligned integer
156 : public detail::packet::IntParserOps<UInt16Parser,boost::uint16_t>,
157 public PacketParserBase
159 UInt16Parser(data_iterator i, state_type s) : PacketParserBase(i,s,fixed_bytes) {}
161 ///////////////////////////////////////////////////////////////////////////
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;
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; }
172 /** \brief Write parsed value to stream
173 \related UInt16Parser
175 inline std::ostream & operator<<(std::ostream & os, UInt16Parser const & i)
176 { os << i.value(); return os; }
178 /** \brief Parse 24bit signed byte aligned integer
183 : public detail::packet::IntParserOps<Int24Parser,boost::int32_t>,
184 public PacketParserBase
186 Int24Parser(data_iterator i, state_type s) : PacketParserBase(i,s,fixed_bytes) {}
188 ///////////////////////////////////////////////////////////////////////////
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;
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; }
200 /** \brief Write parsed value to stream
203 inline std::ostream & operator<<(std::ostream & os, Int24Parser const & i)
204 { os << i.value(); return os; }
206 /** \brief Parse 24bit unsigned byte aligned integer
211 : public detail::packet::IntParserOps<UInt24Parser,boost::uint32_t>,
212 public PacketParserBase
214 UInt24Parser(data_iterator i, state_type s) : PacketParserBase(i,s,fixed_bytes) {}
216 ///////////////////////////////////////////////////////////////////////////
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;
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; }
227 /** \brief Write parsed value to stream
228 \related UInt24Parser
230 inline std::ostream & operator<<(std::ostream & os, UInt24Parser const & i)
231 { os << i.value(); return os; }
233 /** \brief Parse 32bit signed byte aligned integer
238 : public detail::packet::IntParserOps<Int32Parser,boost::int32_t>,
239 public PacketParserBase
241 Int32Parser(data_iterator i, state_type s) : PacketParserBase(i,s,fixed_bytes) {}
243 ///////////////////////////////////////////////////////////////////////////
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;
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; }
254 /** \brief Write parsed value to stream
257 inline std::ostream & operator<<(std::ostream & os, Int32Parser const & i)
258 { os << i.value(); return os; }
260 /** \brief Parse 32bit unsigned byte aligned integer
265 : public detail::packet::IntParserOps<UInt32Parser,boost::uint32_t>,
266 public PacketParserBase
268 UInt32Parser(data_iterator i, state_type s) : PacketParserBase(i,s,fixed_bytes) {}
270 ///////////////////////////////////////////////////////////////////////////
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;
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; }
281 /** \brief Write parsed value to stream
282 \related UInt32Parser
284 inline std::ostream & operator<<(std::ostream & os, UInt32Parser const & i)
285 { os << i.value(); return os; }
287 /** \brief Parse 64bit signed byte aligned integer
292 : public detail::packet::IntParserOps<Int64Parser,boost::int64_t>,
293 public PacketParserBase
295 Int64Parser(data_iterator i, state_type s) : PacketParserBase(i,s,fixed_bytes) {}
297 ///////////////////////////////////////////////////////////////////////////
299 typedef boost::int64_t value_type;
300 static size_type const fixed_bytes = 8;
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; }
306 /** \brief Write parsed value to stream
309 inline std::ostream & operator<<(std::ostream & os, Int64Parser const & i)
310 { os << i.value(); return os; }
313 /** \brief Parse 64bit unsigned byte aligned integer
318 : public detail::packet::IntParserOps<UInt64Parser,boost::uint64_t>,
319 public PacketParserBase
321 UInt64Parser(data_iterator i, state_type s) : PacketParserBase(i,s,fixed_bytes) {}
323 ///////////////////////////////////////////////////////////////////////////
325 typedef boost::uint64_t value_type;
326 static size_type const fixed_bytes = 8;
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; }
332 /** \brief Write parsed value to stream
333 \related UInt64Parser
335 inline std::ostream & operator<<(std::ostream & os, UInt64Parser const & i)
336 { os << i.value(); return os; }
339 /** \brief Parse signed bitfield with up to 32bit's
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.
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.
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
361 template <unsigned Start, unsigned End>
362 struct IntFieldParser
363 : public detail::packet::IntParserOps<IntFieldParser<Start,End>,boost::int32_t>,
364 public PacketParserBase
366 IntFieldParser(data_iterator i, state_type s) : PacketParserBase(i,s,fixed_bytes) {}
368 ///////////////////////////////////////////////////////////////////////////
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;
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;
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; }
387 BOOST_STATIC_ASSERT( Start<End );
388 BOOST_STATIC_ASSERT( End-Start<=32 );
390 /** \brief Write parsed value to stream
391 \related IntFieldParser
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; }
397 /** \brief Parse unsigned bitfield with up to 32bit's
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.
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.
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
419 template <unsigned Start, unsigned End>
420 struct UIntFieldParser
421 : public detail::packet::IntParserOps<UIntFieldParser<Start,End>,boost::uint32_t>,
422 public PacketParserBase
424 UIntFieldParser(data_iterator i, state_type s) : PacketParserBase(i,s,fixed_bytes) {}
426 ///////////////////////////////////////////////////////////////////////////
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;
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; }
440 BOOST_STATIC_ASSERT( Start<End );
441 BOOST_STATIC_ASSERT( End-Start<=32 );
443 /** \brief Write parsed value to stream
444 \related UIntFieldParser
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; }
450 /** \brief Parse single-bit flag
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.
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.
464 template <unsigned Bit>
466 : public detail::packet::IntParserOps<FlagParser<Bit>,bool>,
467 public PacketParserBase
469 FlagParser(data_iterator i, state_type s) : PacketParserBase(i,s,fixed_bytes) {}
471 ///////////////////////////////////////////////////////////////////////////
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;
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)));
484 FlagParser const & operator= (value_type other) { value(other); return *this; }
486 /** \brief Write parsed value to stream
489 template <unsigned Bit>
490 inline std::ostream & operator<<(std::ostream & os, FlagParser<Bit> const & i)
491 { os << i.value(); return os; }
495 ///////////////////////////////hh.e////////////////////////////////////////
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"
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