4 // Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
5 // Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
6 // Stefan Bund <stefan.bund@fokus.fraunhofer.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 ParseInt public header */
27 #define HH_ParseInt_ 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 "ParseInt.mpp"
37 ///////////////////////////////hh.p////////////////////////////////////////
38 #include "ParseInt.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::ParseIntOps<Parse_Int8,boost::int8_t>,
75 public PacketParserBase
77 Parse_Int8(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 Parse_Int8 const & operator= (value_type other) { value(other); return *this; }
90 /** \brief Write parsed value to stream
93 inline std::ostream & operator<<(std::ostream & os, Parse_Int8 const & i)
94 { os << i.value(); return os; }
96 /** \brief Parse 8bit unsigned byte aligned integer
101 : public detail::packet::ParseIntOps<Parse_UInt8,boost::uint8_t>,
102 public PacketParserBase
104 Parse_UInt8(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 Parse_UInt8 const & operator= (value_type other) { value(other); return *this; }
117 /** \brief Write parsed value to stream
120 inline std::ostream & operator<<(std::ostream & os, Parse_UInt8 const & i)
121 { os << i.value(); return os; }
123 /** \brief Parse 16bit signed byte aligned integer
128 : public detail::packet::ParseIntOps<Parse_Int16,boost::int16_t>,
129 public PacketParserBase
131 Parse_Int16(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 Parse_Int16 const & operator= (value_type other) { value(other); return *this; }
145 /** \brief Write parsed value to stream
148 inline std::ostream & operator<<(std::ostream & os, Parse_Int16 const & i)
149 { os << i.value(); return os; }
151 /** \brief Parse 16bit unsigned byte aligned integer
156 : public detail::packet::ParseIntOps<Parse_UInt16,boost::uint16_t>,
157 public PacketParserBase
159 Parse_UInt16(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 Parse_UInt16 const & operator= (value_type other) { value(other); return *this; }
172 /** \brief Write parsed value to stream
173 \related Parse_UInt16
175 inline std::ostream & operator<<(std::ostream & os, Parse_UInt16 const & i)
176 { os << i.value(); return os; }
178 /** \brief Parse 24bit signed byte aligned integer
183 : public detail::packet::ParseIntOps<Parse_Int24,boost::int32_t>,
184 public PacketParserBase
186 Parse_Int24(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 Parse_Int24 const & operator= (value_type other) { value(other); return *this; }
200 /** \brief Write parsed value to stream
203 inline std::ostream & operator<<(std::ostream & os, Parse_Int24 const & i)
204 { os << i.value(); return os; }
206 /** \brief Parse 24bit unsigned byte aligned integer
211 : public detail::packet::ParseIntOps<Parse_UInt24,boost::uint32_t>,
212 public PacketParserBase
214 Parse_UInt24(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 Parse_UInt24 const & operator= (value_type other) { value(other); return *this; }
227 /** \brief Write parsed value to stream
228 \related Parse_UInt24
230 inline std::ostream & operator<<(std::ostream & os, Parse_UInt24 const & i)
231 { os << i.value(); return os; }
233 /** \brief Parse 32bit signed byte aligned integer
238 : public detail::packet::ParseIntOps<Parse_Int32,boost::int32_t>,
239 public PacketParserBase
241 Parse_Int32(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 Parse_Int32 const & operator= (value_type other) { value(other); return *this; }
254 /** \brief Write parsed value to stream
257 inline std::ostream & operator<<(std::ostream & os, Parse_Int32 const & i)
258 { os << i.value(); return os; }
260 /** \brief Parse 32bit unsigned byte aligned integer
265 : public detail::packet::ParseIntOps<Parse_UInt32,boost::uint32_t>,
266 public PacketParserBase
268 Parse_UInt32(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 Parse_UInt32 const & operator= (value_type other) { value(other); return *this; }
281 /** \brief Write parsed value to stream
282 \related Parse_UInt32
284 inline std::ostream & operator<<(std::ostream & os, Parse_UInt32 const & i)
285 { os << i.value(); return os; }
287 template <int X, int Y>
289 static const int result = X * ctime_pow<X,Y-1>::result;
292 struct ctime_pow<X,0> {
293 static const int result = 1;
296 /** \brief Parse signed bitfield with up to 32bit's
298 This parser will parse a bitfield beginning at the bit \a Start and ending \e before \a
299 End. Bits are numbered <em>most significant bit first</em> as this is the customary
300 numbering used when defining packet data structures. \a Start and \a End can be \e
301 arbitrary as long as the field is between 1 and 32 bits in size. In other words, \c
302 Parse_IntField<53,81> is a valid 30 bit field.
304 When defining a compound parser with several bit fields, you need to take care of the fact,
305 that several integer field parsers will interpret the same data \e bytes (but not the same
306 \e bits). It is customary for several integer field parsers to start at the same byte offset
307 with ever increasing bit offsets.
311 \implementation The integer field parser is highly optimized. Since the bit positions are
312 compile-time constants, the compiler will create optimized bit-masks to directly access
313 the value. The parser is also optimized to access the minimum number of data bytes
318 template <unsigned Start, unsigned End>
319 struct Parse_IntField
320 : public detail::packet::ParseIntOps<Parse_IntField<Start,End>,boost::int32_t>,
321 public PacketParserBase
323 Parse_IntField(data_iterator i, state_type s) : PacketParserBase(i,s,fixed_bytes) {}
325 ///////////////////////////////////////////////////////////////////////////
327 typedef boost::int32_t value_type;
328 static size_type const start_bit = Start;
329 static size_type const end_bit = End;
330 static size_type const fixed_bytes = (End-1)/8+1;
331 static value_type const min_value = -ctime_pow<2,(End-Start)-1>::result;
332 static value_type const max_value = ctime_pow<2,(End-Start)-1>::result - 1;
335 value_type value() const {
336 value_type v (detail::packet::parse_bitfield<Start,End>::parse(i()));
337 return v&boost::high_bit_mask_t<End-Start-1>::high_bit ?
338 v | ~boost::low_bits_mask_t<End-Start>::sig_bits : v;
340 void value(value_type v) { detail::packet::parse_bitfield<Start,End>::write(i(),v); }
341 Parse_IntField const & operator= (value_type other) { value(other); return *this; }
344 BOOST_STATIC_ASSERT( Start<End );
345 BOOST_STATIC_ASSERT( End-Start<=32 );
347 /** \brief Write parsed value to stream
348 \related Parse_IntField
350 template <unsigned Start, unsigned End>
351 inline std::ostream & operator<<(std::ostream & os, Parse_IntField<Start,End> const & i)
352 { os << i.value(); return os; }
354 /** \brief Parse unsigned bitfield with up to 32bit's
356 This parser will parse a bitfield beginning at the bit \a Start and ending \e before \a
357 End. Bits are numbered <em>most significant bit first</em> as this is the customary
358 numbering used when defining packet data structures. \a Start and \a End can be \e
359 arbitrary as long as the field is between 1 and 32 bits in size. In other words, \c
360 Parse_IntField<53,81> is a valid 30 bit field.
362 When defining a compound parser with several bit fields, you need to take care of the fact,
363 that several integer field parsers will interpret the same data \e bytes (but not the same
364 \e bits). It is customary for several integer field parsers to start at the same byte offset
365 with ever increasing bit offsets.
369 \implementation The integer field parser is highly optimized. Since the bit positions are
370 compile-time constants, the compiler will create optimized bit-masks to directly access
371 the value. The parser is also optimized to access the minimum number of data bytes
376 template <unsigned Start, unsigned End>
377 struct Parse_UIntField
378 : public detail::packet::ParseIntOps<Parse_UIntField<Start,End>,boost::uint32_t>,
379 public PacketParserBase
381 Parse_UIntField(data_iterator i, state_type s) : PacketParserBase(i,s,fixed_bytes) {}
383 ///////////////////////////////////////////////////////////////////////////
385 typedef boost::uint32_t value_type;
386 static size_type const start_bit = Start;
387 static size_type const end_bit = End;
388 static size_type const fixed_bytes = (End-1)/8+1;
389 static value_type const min_value = 0;
390 static value_type const max_value = ctime_pow<2,(End-Start)>::result - 1;
392 value_type value() const { return detail::packet::parse_bitfield<Start,End>::parse(i()); }
393 void value(value_type v) { detail::packet::parse_bitfield<Start,End>::write(i(),v); }
394 Parse_UIntField const & operator= (value_type other) { value(other); return *this; }
397 BOOST_STATIC_ASSERT( Start<End );
398 BOOST_STATIC_ASSERT( End-Start<=32 );
400 /** \brief Write parsed value to stream
401 \related Parse_UIntField
403 template <unsigned Start, unsigned End>
404 inline std::ostream & operator<<(std::ostream & os, Parse_UIntField<Start,End> const & i)
405 { os << i.value(); return os; }
407 /** \brief Parse single-bit flag
409 This parser will parse a single bit as True/False value. Bits are numbered <em>most
410 significant bit first</em> as this is the customary numbering used when defining packet data
411 structures. \a Bit can be arbitrary, \c Parse_Flag<75> is a valid flag parser.
413 When defining a compound parser with several bit fields, you need to take care of the fact,
414 that several integer field parsers will interpret the same data \e bytes (but not the same
415 \e bits). It is customary for several integer field parsers to start at the same byte offset
416 with ever increasing bit offsets.
421 template <unsigned Bit>
423 : public detail::packet::ParseIntOps<Parse_Flag<Bit>,bool>,
424 public PacketParserBase
426 Parse_Flag(data_iterator i, state_type s) : PacketParserBase(i,s,fixed_bytes) {}
428 ///////////////////////////////////////////////////////////////////////////
430 typedef bool value_type;
431 static size_type const bit = Bit;
432 static size_type const fixed_bytes = Bit/8+1;
433 static value_type const min_value = 0;
434 static value_type const max_value = 1;
436 value_type value() const { return i()[Bit/8] & (1<<(7-(Bit%8))); }
437 void value(value_type v) {
438 if (v) i()[0] |= 1<<(7-(Bit%8));
439 else i()[0] &= ~(1<<(7-(Bit%8)));
441 Parse_Flag const & operator= (value_type other) { value(other); return *this; }
443 /** \brief Write parsed value to stream
446 template <unsigned Bit>
447 inline std::ostream & operator<<(std::ostream & os, Parse_Flag<Bit> const & i)
448 { os << i.value(); return os; }
452 ///////////////////////////////hh.e////////////////////////////////////////
454 #if !defined(HH_Packets__decls_) && !defined(HH_ParseInt_i_)
455 #define HH_ParseInt_i_
456 //#include "ParseInt.cci"
457 //#include "ParseInt.ct"
458 //#include "ParseInt.cti"
465 // c-file-style: "senf"
466 // indent-tabs-mode: nil
467 // ispell-local-dictionary: "american"
468 // compile-command: "scons -u test"
469 // comment-column: 40