404c3cc682b03d8ee18d5396ef678281fb5a47b7
[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     ///////////////////////////////////////////////////////////////////////////
159     // bitfield extraction
160
161     // Doxygen doesn't like this stuff ... 
162
163 #   ifndef DOXYGEN
164
165     template <unsigned offset, unsigned endb, unsigned start, unsigned end>
166     struct parse_bitfield_i
167     {
168         static boost::uint32_t parse(iterator i) {
169             return ( ( ( parse_uint32(i+offset+1)>>(40-end) ) // Beware of sign extension !!
170                        & boost::low_bits_mask_t<32-(40-end)>::sig_bits )
171                      | (i[offset]<<(32-(40-end))) )
172                 & boost::low_bits_mask_t<end-start>::sig_bits;
173         }
174
175         static void write(iterator i, boost::uint32_t v) {
176             write_uint32(i+offset+1,
177                          (parse_uint32(i+offset+1) & ~(boost::low_bits_mask_t<end-8>::sig_bits<<(40-end)))
178                          | ((v & boost::low_bits_mask_t<end-8>::sig_bits) << (40-end)));
179             i[offset] = (i[offset] & ~(boost::low_bits_mask_t<8-start>::sig_bits))
180                 | ((v>>(end-8)) & boost::low_bits_mask_t<8-start>::sig_bits);
181         }
182     };
183
184     template <unsigned offset, unsigned start, unsigned end>
185     struct parse_bitfield_i<offset, 3, start, end>
186     {
187         static boost::uint32_t parse(iterator i) {
188             return ( parse_uint32(i+offset)>>(32-end) )
189                 & boost::low_bits_mask_t<end-start>::sig_bits;
190         }
191
192         static void write(iterator i, boost::uint32_t v) {
193             write_uint32(i+offset,
194                          (parse_uint32(i+offset) & ~(boost::low_bits_mask_t<end-start>::sig_bits<<(32-end)))
195                          | ((v & boost::low_bits_mask_t<end-start>::sig_bits) << (32-end)));
196         }
197     };
198
199     template <unsigned offset, unsigned start, unsigned end>
200     struct parse_bitfield_i<offset, 2, start, end>
201     {
202         static boost::uint32_t parse(iterator i) {
203             return ( parse_uint24(i+offset)>>(24-end) )
204                 & boost::low_bits_mask_t<end-start>::sig_bits;
205         }
206
207         static void write(iterator i, boost::uint32_t v) {
208             write_uint24(i+offset,
209                          (parse_uint24(i+offset) & ~(boost::low_bits_mask_t<end-start>::sig_bits<<(24-end)))
210                          | ((v & boost::low_bits_mask_t<end-start>::sig_bits) << (24-end)));
211         }
212     };
213
214     template <unsigned offset, unsigned start, unsigned end>
215     struct parse_bitfield_i<offset, 1, start, end>
216     {
217         static boost::uint32_t parse(iterator i) {
218             return ( parse_uint16(i+offset)>>(16-end) )
219                 & boost::low_bits_mask_t<end-start>::sig_bits;
220         }
221
222         static void write(iterator i, boost::uint32_t v) {
223             write_uint16(i+offset,
224                          (parse_uint16(i+offset) & ~(boost::low_bits_mask_t<end-start>::sig_bits<<(16-end)))
225                          | ((v & boost::low_bits_mask_t<end-start>::sig_bits) << (16-end)));
226         }
227     };
228
229     template <unsigned offset, unsigned start, unsigned end>
230     struct parse_bitfield_i<offset, 0, start, end>
231     {
232         static boost::uint32_t parse(iterator i) {
233             return ( i[offset]>>(8-end) )
234                 & boost::low_bits_mask_t<end-start>::sig_bits;
235         }
236
237         static void write(iterator i, boost::uint32_t v) {
238             i[offset] = (i[offset] & ~(boost::low_bits_mask_t<end-start>::sig_bits<<(8-end)))
239                 | ((v & boost::low_bits_mask_t<end-start>::sig_bits) << (8-end));
240         }
241     };
242
243 #   endif
244
245     /** \brief Internal: Bitfield read/write helper
246
247         \internal
248         
249         Using template specializations, this class provides optimized bitfield parsers and
250         writers. For each number of bytes the bitfield covers (from 1 to 5 bytes), a template
251         specialization is provided in \c parse_bitfield_i.
252
253         This helper always processes unsigned values. For signed values sign extension still needs
254         to be performed.
255      */
256     template <unsigned start, unsigned end>
257     struct parse_bitfield
258         : public parse_bitfield_i<start/8,(end-1)/8-start/8,start%8,end-8*(start/8)>
259     {};
260
261 }}}
262
263 ///////////////////////////////ih.e////////////////////////////////////////
264 #endif
265
266 \f
267 // Local Variables:
268 // mode: c++
269 // fill-column: 100
270 // c-file-style: "senf"
271 // indent-tabs-mode: nil
272 // ispell-local-dictionary: "american"
273 // compile-command: "scons -u test"
274 // comment-column: 40
275 // End: