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 #define HH_ParseInt_ 1
28 #include <boost/cstdint.hpp>
29 #include <boost/static_assert.hpp>
30 #include <boost/integer/integer_mask.hpp>
31 #include "PacketParser.hh"
33 //#include "ParseInt.mpp"
34 ///////////////////////////////hh.p////////////////////////////////////////
35 #include "ParseInt.ih"
39 /** \defgroup parseint Integer parsers
41 Most packet fields will ultimately contain some type of integral number. The integer parsers
42 allow to parse arbitrary integers in network byte order from 1-32 bit, both signed and
43 unsigned. There are two types of integer parsers:
45 \li The normal integer parsers with interpret 1-4 byte integers (9, 16, 24, 32 bits) aligned
47 \li The bitfield parsers which parse integers with 1-32 bits aligned at any bit. A special
48 case is the single bit flag parser.
50 All fields are parsed in network byte order, the return value of all these parsers is the
51 value in host byte order.
53 The interface of all these parsers is the same (p is an arbitrary integer parser instance, v
54 is an integer constant):
56 \li <tt>p = v</tt>: Assigns the value to the packet field.
57 \li <tt>p.value(v)</tt>: same as above.
58 \li <tt>p.value()</tt>: Returns the fields value as an integer number.
59 \li Use of p like an integer in most contexts: <tt>p += v</tt>, <tt>p *= v</tt>, <tt>v = p +
60 1</tt> and so on. You will only need to use the explicit \c value() member in rare
61 circumstances when the automatic conversion is ambiguous or in some template contexts.
66 /** \brief Parse 8bit signed byte aligned integer
71 : public detail::packet::ParseIntOps<Parse_Int8,boost::int8_t>,
72 public PacketParserBase
74 Parse_Int8(data_iterator i, state_type s) : PacketParserBase(i,s,fixed_bytes) {}
76 ///////////////////////////////////////////////////////////////////////////
78 typedef boost::int8_t value_type;
79 static size_type const fixed_bytes = 1;
81 value_type value() const { return i()[0]; }
82 void value(value_type v) { i()[0] = v; }
83 Parse_Int8 const & operator= (value_type other) { value(other); return *this; }
85 /** \brief Write parsed value to stream
88 inline std::ostream & operator<<(std::ostream & os, Parse_Int8 const & i)
89 { os << i.value(); return os; }
91 /** \brief Parse 8bit unsigned byte aligned integer
96 : public detail::packet::ParseIntOps<Parse_UInt8,boost::uint8_t>,
97 public PacketParserBase
99 Parse_UInt8(data_iterator i, state_type s) : PacketParserBase(i,s,fixed_bytes) {}
101 ///////////////////////////////////////////////////////////////////////////
103 typedef boost::uint8_t value_type;
104 static size_type const fixed_bytes = 1;
106 value_type value() const { return i()[0]; }
107 void value(value_type v) { i()[0] = v; }
108 Parse_UInt8 const & operator= (value_type other) { value(other); return *this; }
110 /** \brief Write parsed value to stream
113 inline std::ostream & operator<<(std::ostream & os, Parse_UInt8 const & i)
114 { os << i.value(); return os; }
116 /** \brief Parse 16bit signed byte aligned integer
121 : public detail::packet::ParseIntOps<Parse_Int16,boost::int16_t>,
122 public PacketParserBase
124 Parse_Int16(data_iterator i, state_type s) : PacketParserBase(i,s,fixed_bytes) {}
126 ///////////////////////////////////////////////////////////////////////////
128 typedef boost::int16_t value_type;
129 static size_type const fixed_bytes = 2;
131 value_type value() const { return detail::packet::parse_uint16(i()); }
132 void value(value_type v) { detail::packet::write_uint16(i(),v); }
133 Parse_Int16 const & operator= (value_type other) { value(other); return *this; }
135 /** \brief Write parsed value to stream
138 inline std::ostream & operator<<(std::ostream & os, Parse_Int16 const & i)
139 { os << i.value(); return os; }
141 /** \brief Parse 16bit unsigned byte aligned integer
146 : public detail::packet::ParseIntOps<Parse_UInt16,boost::uint16_t>,
147 public PacketParserBase
149 Parse_UInt16(data_iterator i, state_type s) : PacketParserBase(i,s,fixed_bytes) {}
151 ///////////////////////////////////////////////////////////////////////////
153 typedef boost::uint16_t value_type;
154 static size_type const fixed_bytes = 2;
156 value_type value() const { return detail::packet::parse_uint16(i()); }
157 void value(value_type v) { detail::packet::write_uint16(i(),v); }
158 Parse_UInt16 const & operator= (value_type other) { value(other); return *this; }
160 /** \brief Write parsed value to stream
161 \related Parse_UInt16
163 inline std::ostream & operator<<(std::ostream & os, Parse_UInt16 const & i)
164 { os << i.value(); return os; }
166 /** \brief Parse 24bit signed byte aligned integer
171 : public detail::packet::ParseIntOps<Parse_Int24,boost::int32_t>,
172 public PacketParserBase
174 Parse_Int24(data_iterator i, state_type s) : PacketParserBase(i,s,fixed_bytes) {}
176 ///////////////////////////////////////////////////////////////////////////
178 typedef boost::int32_t value_type;
179 static size_type const fixed_bytes = 3;
181 value_type value() const {
182 value_type v (detail::packet::parse_uint24(i())); return v&0x800000 ? v|0xff000000 : v; }
183 void value(value_type v) { detail::packet::write_uint24(i(),v); }
184 Parse_Int24 const & operator= (value_type other) { value(other); return *this; }
186 /** \brief Write parsed value to stream
189 inline std::ostream & operator<<(std::ostream & os, Parse_Int24 const & i)
190 { os << i.value(); return os; }
192 /** \brief Parse 24bit unsigned byte aligned integer
197 : public detail::packet::ParseIntOps<Parse_UInt24,boost::uint32_t>,
198 public PacketParserBase
200 Parse_UInt24(data_iterator i, state_type s) : PacketParserBase(i,s,fixed_bytes) {}
202 ///////////////////////////////////////////////////////////////////////////
204 typedef boost::uint32_t value_type;
205 static size_type const fixed_bytes = 3;
207 value_type value() const { return detail::packet::parse_uint24(i()); }
208 void value(value_type v) { detail::packet::write_uint24(i(),v); }
209 Parse_UInt24 const & operator= (value_type other) { value(other); return *this; }
211 /** \brief Write parsed value to stream
212 \related Parse_UInt24
214 inline std::ostream & operator<<(std::ostream & os, Parse_UInt24 const & i)
215 { os << i.value(); return os; }
217 /** \brief Parse 32bit signed byte aligned integer
222 : public detail::packet::ParseIntOps<Parse_Int32,boost::int32_t>,
223 public PacketParserBase
225 Parse_Int32(data_iterator i, state_type s) : PacketParserBase(i,s,fixed_bytes) {}
227 ///////////////////////////////////////////////////////////////////////////
229 typedef boost::int32_t value_type;
230 static size_type const fixed_bytes = 4;
232 value_type value() const { return detail::packet::parse_uint32(i()); }
233 void value(value_type v) { detail::packet::write_uint32(i(),v); }
234 Parse_Int32 const & operator= (value_type other) { value(other); return *this; }
236 /** \brief Write parsed value to stream
239 inline std::ostream & operator<<(std::ostream & os, Parse_Int32 const & i)
240 { os << i.value(); return os; }
242 /** \brief Parse 32bit unsigned byte aligned integer
247 : public detail::packet::ParseIntOps<Parse_UInt32,boost::uint32_t>,
248 public PacketParserBase
250 Parse_UInt32(data_iterator i, state_type s) : PacketParserBase(i,s,fixed_bytes) {}
252 ///////////////////////////////////////////////////////////////////////////
254 typedef boost::uint32_t value_type;
255 static size_type const fixed_bytes = 4;
257 value_type value() const { return detail::packet::parse_uint32(i()); }
258 void value(value_type v) { detail::packet::write_uint32(i(),v); }
259 Parse_UInt32 const & operator= (value_type other) { value(other); return *this; }
261 /** \brief Write parsed value to stream
262 \related Parse_UInt32
264 inline std::ostream & operator<<(std::ostream & os, Parse_UInt32 const & i)
265 { os << i.value(); return os; }
267 /** \brief Parse signed bitfield with up to 32bit's
269 This parser will parse a bitfield beginning at the bit \a Start and ending \e before \a
270 End. Bits are numbered <em>most significant bit first</em> as this is the customary
271 numbering used when defining packet data structures. \a Start and \a End can be \e
272 arbitrary as long as the field is between 1 and 32 bits in size. In other words, \c
273 Parse_IntField<53,81> is a valid 30 bit field.
275 When defining a compound parser with several bit fields, you need to take care of the fact,
276 that several integer field parsers will interpret the same data \e bytes (but not the same
277 \e bits). It is customary for several integer field parsers to start at the same byte offset
278 with ever increasing bit offsets.
282 \implementation The integer field parser is highly optimized. Since the bit positions are
283 compile-time constants, the compiler will create optimized bit-masks to directly access
284 the value. The parser is also optimized to access the minimum number of data bytes
289 template <unsigned Start, unsigned End>
290 struct Parse_IntField
291 : public detail::packet::ParseIntOps<Parse_IntField<Start,End>,boost::int32_t>,
292 public PacketParserBase
294 Parse_IntField(data_iterator i, state_type s) : PacketParserBase(i,s,fixed_bytes) {}
296 ///////////////////////////////////////////////////////////////////////////
298 typedef boost::int32_t value_type;
299 static size_type const fixed_bytes = (End-1)/8+1;
301 value_type value() const {
302 value_type v (detail::packet::parse_bitfield<Start,End>::parse(i()));
303 return v&boost::high_bit_mask_t<End-Start-1>::high_bit ?
304 v | ~boost::low_bits_mask_t<End-Start>::sig_bits : v;
306 void value(value_type v) { detail::packet::parse_bitfield<Start,End>::write(i(),v); }
307 Parse_IntField const & operator= (value_type other) { value(other); return *this; }
310 BOOST_STATIC_ASSERT( Start<End );
311 BOOST_STATIC_ASSERT( End-Start<=32 );
313 /** \brief Write parsed value to stream
314 \related Parse_IntField
316 template <unsigned Start, unsigned End>
317 inline std::ostream & operator<<(std::ostream & os, Parse_IntField<Start,End> const & i)
318 { os << i.value(); return os; }
320 /** \brief Parse unsigned bitfield with up to 32bit's
322 This parser will parse a bitfield beginning at the bit \a Start and ending \e before \a
323 End. Bits are numbered <em>most significant bit first</em> as this is the customary
324 numbering used when defining packet data structures. \a Start and \a End can be \e
325 arbitrary as long as the field is between 1 and 32 bits in size. In other words, \c
326 Parse_IntField<53,81> is a valid 30 bit field.
328 When defining a compound parser with several bit fields, you need to take care of the fact,
329 that several integer field parsers will interpret the same data \e bytes (but not the same
330 \e bits). It is customary for several integer field parsers to start at the same byte offset
331 with ever increasing bit offsets.
335 \implementation The integer field parser is highly optimized. Since the bit positions are
336 compile-time constants, the compiler will create optimized bit-masks to directly access
337 the value. The parser is also optimized to access the minimum number of data bytes
342 template <unsigned Start, unsigned End>
343 struct Parse_UIntField
344 : public detail::packet::ParseIntOps<Parse_UIntField<Start,End>,boost::uint32_t>,
345 public PacketParserBase
347 Parse_UIntField(data_iterator i, state_type s) : PacketParserBase(i,s,fixed_bytes) {}
349 ///////////////////////////////////////////////////////////////////////////
351 typedef boost::uint32_t value_type;
352 static size_type const fixed_bytes = (End-1)/8+1;
354 value_type value() const { return detail::packet::parse_bitfield<Start,End>::parse(i()); }
355 void value(value_type v) { detail::packet::parse_bitfield<Start,End>::write(i(),v); }
356 Parse_UIntField const & operator= (value_type other) { value(other); return *this; }
359 BOOST_STATIC_ASSERT( Start<End );
360 BOOST_STATIC_ASSERT( End-Start<=32 );
362 /** \brief Write parsed value to stream
363 \related Parse_UIntField
365 template <unsigned Start, unsigned End>
366 inline std::ostream & operator<<(std::ostream & os, Parse_UIntField<Start,End> const & i)
367 { os << i.value(); return os; }
369 /** \brief Parse single-bit flag
371 This parser will parse a single bit as True/False value. Bits are numbered <em>most
372 significant bit first</em> as this is the customary numbering used when defining packet data
373 structures. \a Bit can be arbitrary, \c Parse_Flag<75> is a valid flag parser.
375 When defining a compound parser with several bit fields, you need to take care of the fact,
376 that several integer field parsers will interpret the same data \e bytes (but not the same
377 \e bits). It is customary for several integer field parsers to start at the same byte offset
378 with ever increasing bit offsets.
383 template <unsigned Bit>
385 : public detail::packet::ParseIntOps<Parse_Flag<Bit>,bool>,
386 public PacketParserBase
388 Parse_Flag(data_iterator i, state_type s) : PacketParserBase(i,s,fixed_bytes) {}
390 ///////////////////////////////////////////////////////////////////////////
392 typedef bool value_type;
393 static size_type const fixed_bytes = Bit/8+1;
395 value_type value() const { return i()[Bit/8] & (1<<(7-(Bit%8))); }
396 void value(value_type v) {
397 if (v) i()[0] |= 1<<(7-(Bit%8));
398 else i()[0] &= ~(1<<(7-(Bit%8)));
400 Parse_Flag const & operator= (value_type other) { value(other); return *this; }
402 /** \brief Write parsed value to stream
405 template <unsigned Bit>
406 inline std::ostream & operator<<(std::ostream & os, Parse_Flag<Bit> const & i)
407 { os << i.value(); return os; }
411 ///////////////////////////////hh.e////////////////////////////////////////
413 #if !defined(SENF_PACKETS_DECL_ONLY) && !defined(HH_ParseInt_i_)
414 #define HH_ParseInt_i_
415 //#include "ParseInt.cci"
416 //#include "ParseInt.ct"
417 //#include "ParseInt.cti"
424 // c-file-style: "senf"
425 // indent-tabs-mode: nil
426 // ispell-local-dictionary: "american"
427 // compile-command: "scons -u test"
428 // comment-column: 40