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;
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; }
88 /** \brief Write parsed value to stream
91 inline std::ostream & operator<<(std::ostream & os, Parse_Int8 const & i)
92 { os << i.value(); return os; }
94 /** \brief Parse 8bit unsigned byte aligned integer
99 : public detail::packet::ParseIntOps<Parse_UInt8,boost::uint8_t>,
100 public PacketParserBase
102 Parse_UInt8(data_iterator i, state_type s) : PacketParserBase(i,s,fixed_bytes) {}
104 ///////////////////////////////////////////////////////////////////////////
106 typedef boost::uint8_t value_type;
107 static size_type const fixed_bytes = 1;
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; }
113 /** \brief Write parsed value to stream
116 inline std::ostream & operator<<(std::ostream & os, Parse_UInt8 const & i)
117 { os << i.value(); return os; }
119 /** \brief Parse 16bit signed byte aligned integer
124 : public detail::packet::ParseIntOps<Parse_Int16,boost::int16_t>,
125 public PacketParserBase
127 Parse_Int16(data_iterator i, state_type s) : PacketParserBase(i,s,fixed_bytes) {}
129 ///////////////////////////////////////////////////////////////////////////
131 typedef boost::int16_t value_type;
132 static size_type const fixed_bytes = 2;
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; }
138 /** \brief Write parsed value to stream
141 inline std::ostream & operator<<(std::ostream & os, Parse_Int16 const & i)
142 { os << i.value(); return os; }
144 /** \brief Parse 16bit unsigned byte aligned integer
149 : public detail::packet::ParseIntOps<Parse_UInt16,boost::uint16_t>,
150 public PacketParserBase
152 Parse_UInt16(data_iterator i, state_type s) : PacketParserBase(i,s,fixed_bytes) {}
154 ///////////////////////////////////////////////////////////////////////////
156 typedef boost::uint16_t value_type;
157 static size_type const fixed_bytes = 2;
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; }
163 /** \brief Write parsed value to stream
164 \related Parse_UInt16
166 inline std::ostream & operator<<(std::ostream & os, Parse_UInt16 const & i)
167 { os << i.value(); return os; }
169 /** \brief Parse 24bit signed byte aligned integer
174 : public detail::packet::ParseIntOps<Parse_Int24,boost::int32_t>,
175 public PacketParserBase
177 Parse_Int24(data_iterator i, state_type s) : PacketParserBase(i,s,fixed_bytes) {}
179 ///////////////////////////////////////////////////////////////////////////
181 typedef boost::int32_t value_type;
182 static size_type const fixed_bytes = 3;
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; }
189 /** \brief Write parsed value to stream
192 inline std::ostream & operator<<(std::ostream & os, Parse_Int24 const & i)
193 { os << i.value(); return os; }
195 /** \brief Parse 24bit unsigned byte aligned integer
200 : public detail::packet::ParseIntOps<Parse_UInt24,boost::uint32_t>,
201 public PacketParserBase
203 Parse_UInt24(data_iterator i, state_type s) : PacketParserBase(i,s,fixed_bytes) {}
205 ///////////////////////////////////////////////////////////////////////////
207 typedef boost::uint32_t value_type;
208 static size_type const fixed_bytes = 3;
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; }
214 /** \brief Write parsed value to stream
215 \related Parse_UInt24
217 inline std::ostream & operator<<(std::ostream & os, Parse_UInt24 const & i)
218 { os << i.value(); return os; }
220 /** \brief Parse 32bit signed byte aligned integer
225 : public detail::packet::ParseIntOps<Parse_Int32,boost::int32_t>,
226 public PacketParserBase
228 Parse_Int32(data_iterator i, state_type s) : PacketParserBase(i,s,fixed_bytes) {}
230 ///////////////////////////////////////////////////////////////////////////
232 typedef boost::int32_t value_type;
233 static size_type const fixed_bytes = 4;
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; }
239 /** \brief Write parsed value to stream
242 inline std::ostream & operator<<(std::ostream & os, Parse_Int32 const & i)
243 { os << i.value(); return os; }
245 /** \brief Parse 32bit unsigned byte aligned integer
250 : public detail::packet::ParseIntOps<Parse_UInt32,boost::uint32_t>,
251 public PacketParserBase
253 Parse_UInt32(data_iterator i, state_type s) : PacketParserBase(i,s,fixed_bytes) {}
255 ///////////////////////////////////////////////////////////////////////////
257 typedef boost::uint32_t value_type;
258 static size_type const fixed_bytes = 4;
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; }
264 /** \brief Write parsed value to stream
265 \related Parse_UInt32
267 inline std::ostream & operator<<(std::ostream & os, Parse_UInt32 const & i)
268 { os << i.value(); return os; }
270 /** \brief Parse signed bitfield with up to 32bit's
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.
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.
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
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
297 Parse_IntField(data_iterator i, state_type s) : PacketParserBase(i,s,fixed_bytes) {}
299 ///////////////////////////////////////////////////////////////////////////
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;
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;
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; }
315 BOOST_STATIC_ASSERT( Start<End );
316 BOOST_STATIC_ASSERT( End-Start<=32 );
318 /** \brief Write parsed value to stream
319 \related Parse_IntField
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; }
325 /** \brief Parse unsigned bitfield with up to 32bit's
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.
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.
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
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
352 Parse_UIntField(data_iterator i, state_type s) : PacketParserBase(i,s,fixed_bytes) {}
354 ///////////////////////////////////////////////////////////////////////////
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;
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; }
366 BOOST_STATIC_ASSERT( Start<End );
367 BOOST_STATIC_ASSERT( End-Start<=32 );
369 /** \brief Write parsed value to stream
370 \related Parse_UIntField
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; }
376 /** \brief Parse single-bit flag
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.
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.
390 template <unsigned Bit>
392 : public detail::packet::ParseIntOps<Parse_Flag<Bit>,bool>,
393 public PacketParserBase
395 Parse_Flag(data_iterator i, state_type s) : PacketParserBase(i,s,fixed_bytes) {}
397 ///////////////////////////////////////////////////////////////////////////
399 typedef bool value_type;
400 static size_type const bit = Bit;
401 static size_type const fixed_bytes = Bit/8+1;
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)));
408 Parse_Flag const & operator= (value_type other) { value(other); return *this; }
410 /** \brief Write parsed value to stream
413 template <unsigned Bit>
414 inline std::ostream & operator<<(std::ostream & os, Parse_Flag<Bit> const & i)
415 { os << i.value(); return os; }
419 ///////////////////////////////hh.e////////////////////////////////////////
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"
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