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