IntParser.ih
Go to the documentation of this file.
1 //
2 // Copyright (c) 2020 Fraunhofer Institute for Applied Information Technology (FIT)
3 // Network Research Group (NET)
4 // Schloss Birlinghoven, 53754 Sankt Augustin, GERMANY
5 // Contact: support@wiback.org
6 //
7 // This file is part of the SENF code tree.
8 // It is licensed under the 3-clause BSD License (aka New BSD License).
9 // See LICENSE.txt in the top level directory for details or visit
10 // https://opensource.org/licenses/BSD-3-Clause
11 //
12 
13 
14 /** \file
15  \brief IntParser internal header */
16 
17 #ifndef IH_SENF_Packets_IntParser_
18 #define IH_SENF_Packets_IntParser_ 1
19 
20 // Custom includes
21 #include "PacketTypes.hh"
22 
23 //-/////////////////////////////////////////////////////////////////////////////////////////////////
24 
25 namespace senf {
26 namespace detail {
27 namespace packet {
28 
29  //-/////////////////////////////////////////////////////////////////////////////////////////////
30  // Integer operators
31 
32  /** \brief Internal: Integer operation mixin for integer parsers
33 
34  \internal
35 
36  This class contains all the integer operations supported by the integer parsers. It is
37  inherited by each integer parser.
38  */
39  template <class Derived, class Value>
40  class IntParserOps
41  {
42  public:
43  typedef Value value_type;
44 
45  operator Value () const { return derived().value(); }
46 
47 # define unary(op) \
48  Value operator op () const { return op derived().value(); }
49 # define mutator(op) \
50  template <class Other> Derived const & operator op ## = (Other other) \
51  { derived().value( derived().value() op other ); return derived(); }
52 
53  unary(~)
54  unary(!)
55  unary(-)
56 
57  mutator(+)
58  mutator(-)
59  mutator(*)
60  mutator(/)
61  mutator(%)
62  mutator(<<)
63  mutator(>>)
64  mutator(&)
65  mutator(|)
66  mutator(^)
67 
68 # undef unary
69 # undef mutator
70 
71  Derived const & operator ++ ()
72  { derived().value( derived().value()+1 ); return derived(); }
73  Derived const & operator -- ()
74  { derived().value( derived().value()-1 ); return derived(); }
75 
76  Value operator ++ (int)
77  { Value v (derived().value()); derived().value( v+1 ); return v; }
78  Value operator -- (int)
79  { Value v (derived().value()); derived().value( v-1 ); return v; }
80 
81  private:
82  Derived & derived() { return *static_cast<Derived *>(this); }
83  Derived const & derived() const { return *static_cast<Derived const *>(this); };
84  };
85 
86  //-/////////////////////////////////////////////////////////////////////////////////////////////
87  // Network byte order integer extraction
88 
89  /** \brief Internal: Extract 16bit network byte order value
90 
91  \internal
92  */
93  inline boost::uint16_t parse_uint16(iterator i)
94  {
95  return i[1] | i[0]<<8;
96  }
97 
98  /** \brief Internal: Write 16bit network byte order value
99 
100  \internal
101  */
102  inline void write_uint16(iterator i, boost::uint16_t v)
103  {
104  i[0] = ( v >> 8 ) & 0xff;
105  i[1] = ( v ) & 0xff;
106  }
107 
108  /** \brief Internal: Extract 16bit least significant bit order value
109 
110  \internal
111  */
112  inline boost::uint16_t parse_uint16LSB(iterator i)
113  {
114  return i[0] | i[1]<<8;
115  }
116 
117  /** \brief Internal: Write 16bit least significant bit order value
118 
119  \internal
120  */
121  inline void write_uint16LSB(iterator i, boost::uint16_t v)
122  {
123  i[0] = ( v ) & 0xff;
124  i[1] = ( v >> 8 ) & 0xff;
125  }
126 
127  /** \brief Internal: Extract 24bit network byte order value
128 
129  \internal
130  */
131  inline boost::uint32_t parse_uint24(iterator i)
132  {
133  return i[2] | i[1]<<8 | i[0]<<16;
134  }
135 
136  /** \brief Internal: Write 24bit network byte order value
137 
138  \internal
139  */
140  inline void write_uint24(iterator i, boost::uint32_t v)
141  {
142  i[0] = ( v >> 16 ) & 0xff;
143  i[1] = ( v >> 8 ) & 0xff;
144  i[2] = ( v ) & 0xff;
145  }
146 
147  /** \brief Internal: Extract 32bit network byte order value
148 
149  \internal
150  */
151  inline boost::uint32_t parse_uint32(iterator i)
152  {
153  return i[3] | i[2]<<8 | i[1]<<16 | i[0]<<24;
154  }
155 
156  /** \brief Internal: Write 32bit network byte order value
157 
158  \internal
159  */
160  inline void write_uint32(iterator i, boost::uint32_t v)
161  {
162  i[0] = ( v >> 24 ) & 0xff;
163  i[1] = ( v >> 16 ) & 0xff;
164  i[2] = ( v >> 8 ) & 0xff;
165  i[3] = ( v ) & 0xff;
166  }
167 
168  /** \brief Internal: Extract 32bit network byte order value
169 
170  \internal
171  */
172  inline boost::uint32_t parse_uint32LSB(iterator i)
173  {
174  return i[0] | i[1]<<8 | i[2]<<16 | i[3]<<24;
175  }
176 
177  /** \brief Internal: Write 32bit network byte order value
178 
179  \internal
180  */
181  inline void write_uint32LSB(iterator i, boost::uint32_t v)
182  {
183  i[3] = ( v >> 24 ) & 0xff;
184  i[2] = ( v >> 16 ) & 0xff;
185  i[1] = ( v >> 8 ) & 0xff;
186  i[0] = ( v ) & 0xff;
187  }
188 
189  /** \brief Internal: Extract 64bit network byte order value
190 
191  \internal
192  */
193  inline boost::uint64_t parse_uint64(iterator i)
194  {
195  return ((boost::uint64_t)i[7]) | ((boost::uint64_t)i[6])<<8
196  | ((boost::uint64_t)i[5])<<16 | ((boost::uint64_t)i[4])<<24
197  | ((boost::uint64_t)i[3])<<32 | ((boost::uint64_t)i[2])<<40
198  | ((boost::uint64_t)i[1])<<48 | ((boost::uint64_t)i[0])<<56;
199  }
200 
201  /** \brief Internal: Write 64bit network byte order value
202 
203  \internal
204  */
205  inline void write_uint64(iterator i, boost::uint64_t v)
206  {
207  i[0] = ( v >> 56 ) & 0xff;
208  i[1] = ( v >> 48 ) & 0xff;
209  i[2] = ( v >> 40 ) & 0xff;
210  i[3] = ( v >> 32 ) & 0xff;
211  i[4] = ( v >> 24 ) & 0xff;
212  i[5] = ( v >> 16 ) & 0xff;
213  i[6] = ( v >> 8 ) & 0xff;
214  i[7] = ( v ) & 0xff;
215  }
216 
217  /** \brief Internal: Extract 64bit least significant bit order value
218 
219  \internal
220  */
221  inline boost::uint64_t parse_uint64LSB(iterator i)
222  {
223  return ((boost::uint64_t)i[0]) | ((boost::uint64_t)i[1])<<8
224  | ((boost::uint64_t)i[2])<<16 | ((boost::uint64_t)i[3])<<24
225  | ((boost::uint64_t)i[4])<<32 | ((boost::uint64_t)i[5])<<40
226  | ((boost::uint64_t)i[6])<<48 | ((boost::uint64_t)i[7])<<56;
227  }
228 
229  /** \brief Internal: Write 64bit least significant bit order value
230 
231  \internal
232  */
233  inline void write_uint64LSB(iterator i, boost::uint64_t v)
234  {
235  i[0] = ( v ) & 0xff;
236  i[1] = ( v >> 8 ) & 0xff;
237  i[2] = ( v >> 16 ) & 0xff;
238  i[3] = ( v >> 24 ) & 0xff;
239  i[4] = ( v >> 32 ) & 0xff;
240  i[5] = ( v >> 40 ) & 0xff;
241  i[6] = ( v >> 48 ) & 0xff;
242  i[7] = ( v >> 56 ) & 0xff;
243  }
244 
245  //-/////////////////////////////////////////////////////////////////////////////////////////////
246  // bitfield extraction
247 
248  // Doxygen doesn't like this stuff ...
249 
250 # ifndef DOXYGEN
251 
252  template <unsigned offset, unsigned endb, unsigned start, unsigned end>
253  struct parse_bitfield_i
254  {
255  static boost::uint32_t parse(iterator i) {
256  return ( ( ( parse_uint32(i+offset+1)>>(40-end) ) // Beware of sign extension !!
257  & boost::low_bits_mask_t<32-(40-end)>::sig_bits )
258  | (i[offset]<<(32-(40-end))) )
259  & boost::low_bits_mask_t<end-start>::sig_bits;
260  }
261 
262  static void write(iterator i, boost::uint32_t v) {
263  write_uint32(i+offset+1,
264  (parse_uint32(i+offset+1) & ~(boost::low_bits_mask_t<end-8>::sig_bits<<(40-end)))
265  | ((v & boost::low_bits_mask_t<end-8>::sig_bits) << (40-end)));
266  i[offset] = (i[offset] & ~(boost::low_bits_mask_t<8-start>::sig_bits))
267  | ((v>>(end-8)) & boost::low_bits_mask_t<8-start>::sig_bits);
268  }
269  };
270 
271  template <unsigned offset, unsigned start, unsigned end>
272  struct parse_bitfield_i<offset, 3, start, end>
273  {
274  static boost::uint32_t parse(iterator i) {
275  return ( parse_uint32(i+offset)>>(32-end) )
276  & boost::low_bits_mask_t<end-start>::sig_bits;
277  }
278 
279  static void write(iterator i, boost::uint32_t v) {
280  write_uint32(i+offset,
281  (parse_uint32(i+offset) & ~(boost::low_bits_mask_t<end-start>::sig_bits<<(32-end)))
282  | ((v & boost::low_bits_mask_t<end-start>::sig_bits) << (32-end)));
283  }
284  };
285 
286  template <unsigned offset, unsigned start, unsigned end>
287  struct parse_bitfield_i<offset, 2, start, end>
288  {
289  static boost::uint32_t parse(iterator i) {
290  return ( parse_uint24(i+offset)>>(24-end) )
291  & boost::low_bits_mask_t<end-start>::sig_bits;
292  }
293 
294  static void write(iterator i, boost::uint32_t v) {
295  write_uint24(i+offset,
296  (parse_uint24(i+offset) & ~(boost::low_bits_mask_t<end-start>::sig_bits<<(24-end)))
297  | ((v & boost::low_bits_mask_t<end-start>::sig_bits) << (24-end)));
298  }
299  };
300 
301  template <unsigned offset, unsigned start, unsigned end>
302  struct parse_bitfield_i<offset, 1, start, end>
303  {
304  static boost::uint32_t parse(iterator i) {
305  return ( parse_uint16(i+offset)>>(16-end) )
306  & boost::low_bits_mask_t<end-start>::sig_bits;
307  }
308 
309  static void write(iterator i, boost::uint32_t v) {
310  write_uint16(i+offset,
311  (parse_uint16(i+offset) & ~(boost::low_bits_mask_t<end-start>::sig_bits<<(16-end)))
312  | ((v & boost::low_bits_mask_t<end-start>::sig_bits) << (16-end)));
313  }
314  };
315 
316  template <unsigned offset, unsigned start, unsigned end>
317  struct parse_bitfield_i<offset, 0, start, end>
318  {
319  static boost::uint32_t parse(iterator i) {
320  return ( i[offset]>>(8-end) )
321  & boost::low_bits_mask_t<end-start>::sig_bits;
322  }
323 
324  static void write(iterator i, boost::uint32_t v) {
325  i[offset] = (i[offset] & ~(boost::low_bits_mask_t<end-start>::sig_bits<<(8-end)))
326  | ((v & boost::low_bits_mask_t<end-start>::sig_bits) << (8-end));
327  }
328  };
329 
330 # endif
331 
332  /** \brief Internal: Bitfield read/write helper
333 
334  \internal
335 
336  Using template specializations, this class provides optimized bitfield parsers and
337  writers. For each number of bytes the bitfield covers (from 1 to 5 bytes), a template
338  specialization is provided in \c parse_bitfield_i.
339 
340  This helper always processes unsigned values. For signed values sign extension still needs
341  to be performed.
342  */
343  template <unsigned start, unsigned end>
344  struct parse_bitfield
345  : public parse_bitfield_i<start/8,(end-1)/8-start/8,start%8,end-8*(start/8)>
346  {};
347 
348 }}}
349 
350 //-/////////////////////////////////////////////////////////////////////////////////////////////////
351 #endif
352 
353 
354 // Local Variables:
355 // mode: c++
356 // fill-column: 100
357 // c-file-style: "senf"
358 // indent-tabs-mode: nil
359 // ispell-local-dictionary: "american"
360 // compile-command: "scons -u test"
361 // comment-column: 40
362 // End: