fdc7b85632d0c84173f3221e670c3f273207823d
[senf.git] / 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_IntParser_
27 #define IH_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 24bit network byte order value
118
119         \internal
120      */
121     inline boost::uint32_t parse_uint24(iterator i)
122     {
123         return i[2] | i[1]<<8 | i[0]<<16;
124     }
125
126     /** \brief Internal: Write 24bit network byte order value
127
128         \internal
129      */
130     inline void write_uint24(iterator i, boost::uint32_t v)
131     {
132         i[0] = ( v >> 16 ) & 0xff;
133         i[1] = ( v >>  8 ) & 0xff;
134         i[2] = ( v       ) & 0xff;
135     }
136
137     /** \brief Internal: Extract 32bit network byte order value
138
139         \internal
140      */
141     inline boost::uint32_t parse_uint32(iterator i)
142     {
143         return i[3] | i[2]<<8 | i[1]<<16 | i[0]<<24;
144     }
145
146     /** \brief Internal: Write 32bit network byte order value
147
148         \internal
149      */
150     inline void write_uint32(iterator i, boost::uint32_t v)
151     {
152         i[0] = ( v >> 24 ) & 0xff;
153         i[1] = ( v >> 16 ) & 0xff;
154         i[2] = ( v >>  8 ) & 0xff;
155         i[3] = ( v       ) & 0xff;
156     }
157
158     /** \brief Internal: Extract 64bit network byte order value
159
160         \internal
161      */
162     inline boost::uint64_t parse_uint64(iterator i)
163     {
164         return ((boost::uint64_t)i[7]) | ((boost::uint64_t)i[6])<<8
165                 | ((boost::uint64_t)i[5])<<16 | ((boost::uint64_t)i[4])<<24
166                 | ((boost::uint64_t)i[3])<<32 | ((boost::uint64_t)i[2])<<40
167                 | ((boost::uint64_t)i[1])<<48 | ((boost::uint64_t)i[0])<<56;
168     }
169
170     /** \brief Internal: Write 64bit network byte order value
171
172         \internal
173      */
174     inline void write_uint64(iterator i, boost::uint64_t v)
175     {
176         i[0] = ( v >> 56 ) & 0xff;
177         i[1] = ( v >> 48 ) & 0xff;
178         i[2] = ( v >> 40 ) & 0xff;
179         i[3] = ( v >> 32 ) & 0xff;
180         i[4] = ( v >> 24 ) & 0xff;
181         i[5] = ( v >> 16 ) & 0xff;
182         i[6] = ( v >> 8  ) & 0xff;
183         i[7] = ( v       ) & 0xff;
184     }
185
186     ///////////////////////////////////////////////////////////////////////////
187     // bitfield extraction
188
189     // Doxygen doesn't like this stuff ...
190
191 #   ifndef DOXYGEN
192
193     template <unsigned offset, unsigned endb, unsigned start, unsigned end>
194     struct parse_bitfield_i
195     {
196         static boost::uint32_t parse(iterator i) {
197             return ( ( ( parse_uint32(i+offset+1)>>(40-end) ) // Beware of sign extension !!
198                        & boost::low_bits_mask_t<32-(40-end)>::sig_bits )
199                      | (i[offset]<<(32-(40-end))) )
200                 & boost::low_bits_mask_t<end-start>::sig_bits;
201         }
202
203         static void write(iterator i, boost::uint32_t v) {
204             write_uint32(i+offset+1,
205                          (parse_uint32(i+offset+1) & ~(boost::low_bits_mask_t<end-8>::sig_bits<<(40-end)))
206                          | ((v & boost::low_bits_mask_t<end-8>::sig_bits) << (40-end)));
207             i[offset] = (i[offset] & ~(boost::low_bits_mask_t<8-start>::sig_bits))
208                 | ((v>>(end-8)) & boost::low_bits_mask_t<8-start>::sig_bits);
209         }
210     };
211
212     template <unsigned offset, unsigned start, unsigned end>
213     struct parse_bitfield_i<offset, 3, start, end>
214     {
215         static boost::uint32_t parse(iterator i) {
216             return ( parse_uint32(i+offset)>>(32-end) )
217                 & boost::low_bits_mask_t<end-start>::sig_bits;
218         }
219
220         static void write(iterator i, boost::uint32_t v) {
221             write_uint32(i+offset,
222                          (parse_uint32(i+offset) & ~(boost::low_bits_mask_t<end-start>::sig_bits<<(32-end)))
223                          | ((v & boost::low_bits_mask_t<end-start>::sig_bits) << (32-end)));
224         }
225     };
226
227     template <unsigned offset, unsigned start, unsigned end>
228     struct parse_bitfield_i<offset, 2, start, end>
229     {
230         static boost::uint32_t parse(iterator i) {
231             return ( parse_uint24(i+offset)>>(24-end) )
232                 & boost::low_bits_mask_t<end-start>::sig_bits;
233         }
234
235         static void write(iterator i, boost::uint32_t v) {
236             write_uint24(i+offset,
237                          (parse_uint24(i+offset) & ~(boost::low_bits_mask_t<end-start>::sig_bits<<(24-end)))
238                          | ((v & boost::low_bits_mask_t<end-start>::sig_bits) << (24-end)));
239         }
240     };
241
242     template <unsigned offset, unsigned start, unsigned end>
243     struct parse_bitfield_i<offset, 1, start, end>
244     {
245         static boost::uint32_t parse(iterator i) {
246             return ( parse_uint16(i+offset)>>(16-end) )
247                 & boost::low_bits_mask_t<end-start>::sig_bits;
248         }
249
250         static void write(iterator i, boost::uint32_t v) {
251             write_uint16(i+offset,
252                          (parse_uint16(i+offset) & ~(boost::low_bits_mask_t<end-start>::sig_bits<<(16-end)))
253                          | ((v & boost::low_bits_mask_t<end-start>::sig_bits) << (16-end)));
254         }
255     };
256
257     template <unsigned offset, unsigned start, unsigned end>
258     struct parse_bitfield_i<offset, 0, start, end>
259     {
260         static boost::uint32_t parse(iterator i) {
261             return ( i[offset]>>(8-end) )
262                 & boost::low_bits_mask_t<end-start>::sig_bits;
263         }
264
265         static void write(iterator i, boost::uint32_t v) {
266             i[offset] = (i[offset] & ~(boost::low_bits_mask_t<end-start>::sig_bits<<(8-end)))
267                 | ((v & boost::low_bits_mask_t<end-start>::sig_bits) << (8-end));
268         }
269     };
270
271 #   endif
272
273     /** \brief Internal: Bitfield read/write helper
274
275         \internal
276
277         Using template specializations, this class provides optimized bitfield parsers and
278         writers. For each number of bytes the bitfield covers (from 1 to 5 bytes), a template
279         specialization is provided in \c parse_bitfield_i.
280
281         This helper always processes unsigned values. For signed values sign extension still needs
282         to be performed.
283      */
284     template <unsigned start, unsigned end>
285     struct parse_bitfield
286         : public parse_bitfield_i<start/8,(end-1)/8-start/8,start%8,end-8*(start/8)>
287     {};
288
289 }}}
290
291 ///////////////////////////////ih.e////////////////////////////////////////
292 #endif
293
294
295 // Local Variables:
296 // mode: c++
297 // fill-column: 100
298 // c-file-style: "senf"
299 // indent-tabs-mode: nil
300 // ispell-local-dictionary: "american"
301 // compile-command: "scons -u test"
302 // comment-column: 40
303 // End: