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