Socket: BUGFIX: Explicitly copy image
[senf.git] / Packets / ParseInt.ih
1 // $Id$
2 //
3 // Copyright (C) 2006
4 // Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
5 // Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
6 //     Stefan Bund <stefan.bund@fokus.fraunhofer.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 #ifndef IH_ParseInt_
24 #define IH_ParseInt_ 1
25
26 // Custom includes
27 #include "PacketTypes.hh"
28
29 ///////////////////////////////ih.p////////////////////////////////////////
30
31 namespace senf {
32 namespace detail {
33 namespace packet {
34
35     ///////////////////////////////////////////////////////////////////////////
36     // Integer operators
37
38     /** \brief Internal: Integer operation mixin for integer parsers
39
40         \internal
41
42         This class contains all the integer operations supported by the integer parsers. It is
43         inherited by each integer parser.
44      */
45     template <class Derived, class Value>
46     class ParseIntOps
47     {
48     public:
49         typedef Value value_type;
50
51         operator Value () const { return derived().value(); }
52
53 #       define unary(op) \
54             Value operator op () const { return op derived().value(); }
55 #       define mutator(op) \
56             template <class Other> Derived const & operator op ## =  (Other other) \
57                 { derived().value( derived().value() op other ); return derived(); }
58
59         unary(~)
60         unary(!)
61         unary(-)
62
63         mutator(+)
64         mutator(-)
65         mutator(*)
66         mutator(/)
67         mutator(%)
68         mutator(<<)
69         mutator(>>)
70         mutator(&)
71         mutator(|)
72         mutator(^)
73
74 #       undef unary
75 #       undef mutator
76
77         Derived const & operator ++ ()
78             { derived().value( derived().value()+1 ); return derived(); }
79         Derived const & operator -- ()
80             { derived().value( derived().value()-1 ); return derived(); }
81
82         Value operator ++ (int)
83             { Value v (derived().value()); derived().value( v+1 ); return v; }
84         Value operator -- (int)
85             { Value v (derived().value()); derived().value( v-1 ); return v; }
86
87     private:
88         Derived & derived() { return *static_cast<Derived *>(this); }
89         Derived const & derived() const { return *static_cast<Derived const *>(this); };
90     };
91
92     ///////////////////////////////////////////////////////////////////////////
93     // Network byte order integer extraction
94
95     /** \brief Internal: Extract 16bit network byte order value
96         
97         \internal
98      */
99     inline boost::uint16_t parse_uint16(iterator i)
100     {
101         return i[1] | i[0]<<8;
102     }
103
104     /** \brief Internal: Write 16bit network byte order value
105         
106         \internal
107      */
108     inline void write_uint16(iterator i, boost::uint16_t v)
109     {
110         i[0] = ( v >>  8 ) & 0xff;
111         i[1] = ( v       ) & 0xff;
112     }
113
114     /** \brief Internal: Extract 24bit network byte order value
115         
116         \internal
117      */
118     inline boost::uint32_t parse_uint24(iterator i)
119     {
120         return i[2] | i[1]<<8 | i[0]<<16;
121     }
122
123     /** \brief Internal: Write 24bit network byte order value
124         
125         \internal
126      */
127     inline void write_uint24(iterator i, boost::uint32_t v)
128     {
129         i[0] = ( v >> 16 ) & 0xff;
130         i[1] = ( v >>  8 ) & 0xff;
131         i[2] = ( v       ) & 0xff;
132     }
133
134     /** \brief Internal: Extract 32bit network byte order value
135         
136         \internal
137      */
138     inline boost::uint32_t parse_uint32(iterator i)
139     {
140         return i[3] | i[2]<<8 | i[1]<<16 | i[0]<<24;
141     }
142
143     /** \brief Internal: Write 32bit network byte order value
144         
145         \internal
146      */
147     inline void write_uint32(iterator i, boost::uint32_t v)
148     {
149         i[0] = ( v >> 24 ) & 0xff;
150         i[1] = ( v >> 16 ) & 0xff;
151         i[2] = ( v >>  8 ) & 0xff;
152         i[3] = ( v       ) & 0xff;
153     }
154
155     ///////////////////////////////////////////////////////////////////////////
156     // bitfield extraction
157
158     // Doxygen doesn't like this stuff ... 
159
160 #   ifndef DOXYGEN
161
162     template <unsigned offset, unsigned endb, unsigned start, unsigned end>
163     struct parse_bitfield_i
164     {
165         static boost::uint32_t parse(iterator i) {
166             return ( ( ( parse_uint32(i+offset+1)>>(40-end) ) // Beware of sign extension !!
167                        & boost::low_bits_mask_t<32-(40-end)>::sig_bits )
168                      | (i[offset]<<(32-(40-end))) )
169                 & boost::low_bits_mask_t<end-start>::sig_bits;
170         }
171
172         static void write(iterator i, boost::uint32_t v) {
173             write_uint32(i+offset+1,
174                          (parse_uint32(i+offset+1) & ~(boost::low_bits_mask_t<end-8>::sig_bits<<(40-end)))
175                          | ((v & boost::low_bits_mask_t<end-8>::sig_bits) << (40-end)));
176             i[offset] = (i[offset] & ~(boost::low_bits_mask_t<8-start>::sig_bits))
177                 | ((v>>(end-8)) & boost::low_bits_mask_t<8-start>::sig_bits);
178         }
179     };
180
181     template <unsigned offset, unsigned start, unsigned end>
182     struct parse_bitfield_i<offset, 3, start, end>
183     {
184         static boost::uint32_t parse(iterator i) {
185             return ( parse_uint32(i+offset)>>(32-end) )
186                 & boost::low_bits_mask_t<end-start>::sig_bits;
187         }
188
189         static void write(iterator i, boost::uint32_t v) {
190             write_uint32(i+offset,
191                          (parse_uint32(i+offset) & ~(boost::low_bits_mask_t<end-start>::sig_bits<<(32-end)))
192                          | ((v & boost::low_bits_mask_t<end-start>::sig_bits) << (32-end)));
193         }
194     };
195
196     template <unsigned offset, unsigned start, unsigned end>
197     struct parse_bitfield_i<offset, 2, start, end>
198     {
199         static boost::uint32_t parse(iterator i) {
200             return ( parse_uint24(i+offset)>>(24-end) )
201                 & boost::low_bits_mask_t<end-start>::sig_bits;
202         }
203
204         static void write(iterator i, boost::uint32_t v) {
205             write_uint24(i+offset,
206                          (parse_uint24(i+offset) & ~(boost::low_bits_mask_t<end-start>::sig_bits<<(24-end)))
207                          | ((v & boost::low_bits_mask_t<end-start>::sig_bits) << (24-end)));
208         }
209     };
210
211     template <unsigned offset, unsigned start, unsigned end>
212     struct parse_bitfield_i<offset, 1, start, end>
213     {
214         static boost::uint32_t parse(iterator i) {
215             return ( parse_uint16(i+offset)>>(16-end) )
216                 & boost::low_bits_mask_t<end-start>::sig_bits;
217         }
218
219         static void write(iterator i, boost::uint32_t v) {
220             write_uint16(i+offset,
221                          (parse_uint16(i+offset) & ~(boost::low_bits_mask_t<end-start>::sig_bits<<(16-end)))
222                          | ((v & boost::low_bits_mask_t<end-start>::sig_bits) << (16-end)));
223         }
224     };
225
226     template <unsigned offset, unsigned start, unsigned end>
227     struct parse_bitfield_i<offset, 0, start, end>
228     {
229         static boost::uint32_t parse(iterator i) {
230             return ( i[offset]>>(8-end) )
231                 & boost::low_bits_mask_t<end-start>::sig_bits;
232         }
233
234         static void write(iterator i, boost::uint32_t v) {
235             i[offset] = (i[offset] & ~(boost::low_bits_mask_t<end-start>::sig_bits<<(8-end)))
236                 | ((v & boost::low_bits_mask_t<end-start>::sig_bits) << (8-end));
237         }
238     };
239
240 #   endif
241
242     /** \brief Internal: Bitfield read/write helper
243
244         \internal
245         
246         Using template specializations, this class provides optimized bitfield parsers and
247         writers. For each number of bytes the bitfield covers (from 1 to 5 bytes), a template
248         specialization is provided in \c parse_bitfield_i.
249
250         This helper always processes unsigned values. For signed values sign extension still needs
251         to be performed.
252      */
253     template <unsigned start, unsigned end>
254     struct parse_bitfield
255         : public parse_bitfield_i<start/8,(end-1)/8-start/8,start%8,end-8*(start/8)>
256     {};
257
258 }}}
259
260 ///////////////////////////////ih.e////////////////////////////////////////
261 #endif
262
263 \f
264 // Local Variables:
265 // mode: c++
266 // fill-column: 100
267 // c-file-style: "senf"
268 // indent-tabs-mode: nil
269 // ispell-local-dictionary: "american"
270 // compile-command: "scons -u test"
271 // comment-column: 40
272 // End: