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 fixed_bytes = (End-1)/8+1;
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;
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; }
313 BOOST_STATIC_ASSERT( Start<End );
314 BOOST_STATIC_ASSERT( End-Start<=32 );
316 /** \brief Write parsed value to stream
317 \related Parse_IntField
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; }
323 /** \brief Parse unsigned bitfield with up to 32bit's
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.
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.
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
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
350 Parse_UIntField(data_iterator i, state_type s) : PacketParserBase(i,s,fixed_bytes) {}
352 ///////////////////////////////////////////////////////////////////////////
354 typedef boost::uint32_t value_type;
355 static size_type const fixed_bytes = (End-1)/8+1;
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; }
362 BOOST_STATIC_ASSERT( Start<End );
363 BOOST_STATIC_ASSERT( End-Start<=32 );
365 /** \brief Write parsed value to stream
366 \related Parse_UIntField
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; }
372 /** \brief Parse single-bit flag
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.
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.
386 template <unsigned Bit>
388 : public detail::packet::ParseIntOps<Parse_Flag<Bit>,bool>,
389 public PacketParserBase
391 Parse_Flag(data_iterator i, state_type s) : PacketParserBase(i,s,fixed_bytes) {}
393 ///////////////////////////////////////////////////////////////////////////
395 typedef bool value_type;
396 static size_type const fixed_bytes = Bit/8+1;
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)));
403 Parse_Flag const & operator= (value_type other) { value(other); return *this; }
405 /** \brief Write parsed value to stream
408 template <unsigned Bit>
409 inline std::ostream & operator<<(std::ostream & os, Parse_Flag<Bit> const & i)
410 { os << i.value(); return os; }
414 ///////////////////////////////hh.e////////////////////////////////////////
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"
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