a1e961c97a096f5bde6121a5c0291e935dca2fdf
[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     template <class Derived, class Value>
39     class ParseIntOps
40     {
41     public:
42         typedef Value value_type;
43
44         operator Value () const { return derived().value(); }
45
46 #       define unary(op) \
47             Value operator op () const { return op derived().value(); }
48 #       define mutator(op) \
49             template <class Other> Derived const & operator op ## =  (Other other) \
50                 { derived().value( derived().value() op other ); return derived(); }
51
52         unary(~)
53         unary(!)
54         unary(-)
55
56         mutator(+)
57         mutator(-)
58         mutator(*)
59         mutator(/)
60         mutator(%)
61         mutator(<<)
62         mutator(>>)
63         mutator(&)
64         mutator(|)
65         mutator(^)
66
67 #       undef unary
68 #       undef mutator
69
70         Derived const & operator ++ ()
71             { derived().value( derived().value()+1 ); return derived(); }
72         Derived const & operator -- ()
73             { derived().value( derived().value()-1 ); return derived(); }
74
75         Value operator ++ (int)
76             { Value v (derived().value()); derived().value( v+1 ); return v; }
77         Value operator -- (int)
78             { Value v (derived().value()); derived().value( v-1 ); return v; }
79
80     private:
81         Derived & derived() { return *static_cast<Derived *>(this); }
82         Derived const & derived() const { return *static_cast<Derived const *>(this); };
83     };
84
85     ///////////////////////////////////////////////////////////////////////////
86     // Network byte order integer extraction
87
88     inline boost::uint16_t parse_uint16(iterator i)
89     {
90         return i[1] | i[0]<<8;
91     }
92
93     inline void write_uint16(iterator i, boost::uint16_t v)
94     {
95         i[0] = ( v >>  8 ) & 0xff;
96         i[1] = ( v       ) & 0xff;
97     }
98
99     inline boost::uint32_t parse_uint24(iterator i)
100     {
101         return i[2] | i[1]<<8 | i[0]<<16;
102     }
103
104     inline void write_uint24(iterator i, boost::uint32_t v)
105     {
106         i[0] = ( v >> 16 ) & 0xff;
107         i[1] = ( v >>  8 ) & 0xff;
108         i[2] = ( v       ) & 0xff;
109     }
110
111     inline boost::uint32_t parse_uint32(iterator i)
112     {
113         return i[3] | i[2]<<8 | i[1]<<16 | i[0]<<24;
114     }
115
116     inline void write_uint32(iterator i, boost::uint32_t v)
117     {
118         i[0] = ( v >> 24 ) & 0xff;
119         i[1] = ( v >> 16 ) & 0xff;
120         i[2] = ( v >>  8 ) & 0xff;
121         i[3] = ( v       ) & 0xff;
122     }
123
124     ///////////////////////////////////////////////////////////////////////////
125     // bitfield extraction
126
127     // Doxygen doesn't like this stuff ... 
128
129 #   ifndef DOXYGEN
130
131     template <unsigned offset, unsigned endb, unsigned start, unsigned end>
132     struct parse_bitfield_i
133     {
134         static boost::uint32_t parse(iterator i) {
135             return ( ( ( parse_uint32(i+offset+1)>>(40-end) ) // Beware of sign extension !!
136                        & boost::low_bits_mask_t<32-(40-end)>::sig_bits )
137                      | (i[offset]<<(32-(40-end))) )
138                 & boost::low_bits_mask_t<end-start>::sig_bits;
139         }
140
141         static void write(iterator i, boost::uint32_t v) {
142             write_uint32(i+offset+1,
143                          (parse_uint32(i+offset+1) & ~(boost::low_bits_mask_t<end-8>::sig_bits<<(40-end)))
144                          | ((v & boost::low_bits_mask_t<end-8>::sig_bits) << (40-end)));
145             i[offset] = (i[offset] & ~(boost::low_bits_mask_t<8-start>::sig_bits))
146                 | ((v>>(end-8)) & boost::low_bits_mask_t<8-start>::sig_bits);
147         }
148     };
149
150     template <unsigned offset, unsigned start, unsigned end>
151     struct parse_bitfield_i<offset, 3, start, end>
152     {
153         static boost::uint32_t parse(iterator i) {
154             return ( parse_uint32(i+offset)>>(32-end) )
155                 & boost::low_bits_mask_t<end-start>::sig_bits;
156         }
157
158         static void write(iterator i, boost::uint32_t v) {
159             write_uint32(i+offset,
160                          (parse_uint32(i+offset) & ~(boost::low_bits_mask_t<end-start>::sig_bits<<(32-end)))
161                          | ((v & boost::low_bits_mask_t<end-start>::sig_bits) << (32-end)));
162         }
163     };
164
165     template <unsigned offset, unsigned start, unsigned end>
166     struct parse_bitfield_i<offset, 2, start, end>
167     {
168         static boost::uint32_t parse(iterator i) {
169             return ( parse_uint24(i+offset)>>(24-end) )
170                 & boost::low_bits_mask_t<end-start>::sig_bits;
171         }
172
173         static void write(iterator i, boost::uint32_t v) {
174             write_uint24(i+offset,
175                          (parse_uint24(i+offset) & ~(boost::low_bits_mask_t<end-start>::sig_bits<<(24-end)))
176                          | ((v & boost::low_bits_mask_t<end-start>::sig_bits) << (24-end)));
177         }
178     };
179
180     template <unsigned offset, unsigned start, unsigned end>
181     struct parse_bitfield_i<offset, 1, start, end>
182     {
183         static boost::uint32_t parse(iterator i) {
184             return ( parse_uint16(i+offset)>>(16-end) )
185                 & boost::low_bits_mask_t<end-start>::sig_bits;
186         }
187
188         static void write(iterator i, boost::uint32_t v) {
189             write_uint16(i+offset,
190                          (parse_uint16(i+offset) & ~(boost::low_bits_mask_t<end-start>::sig_bits<<(16-end)))
191                          | ((v & boost::low_bits_mask_t<end-start>::sig_bits) << (16-end)));
192         }
193     };
194
195     template <unsigned offset, unsigned start, unsigned end>
196     struct parse_bitfield_i<offset, 0, start, end>
197     {
198         static boost::uint32_t parse(iterator i) {
199             return ( i[offset]>>(8-end) )
200                 & boost::low_bits_mask_t<end-start>::sig_bits;
201         }
202
203         static void write(iterator i, boost::uint32_t v) {
204             i[offset] = (i[offset] & ~(boost::low_bits_mask_t<end-start>::sig_bits<<(8-end)))
205                 | ((v & boost::low_bits_mask_t<end-start>::sig_bits) << (8-end));
206         }
207     };
208
209 #   endif
210
211     template <unsigned start, unsigned end>
212     struct parse_bitfield
213         : public parse_bitfield_i<start/8,(end-1)/8-start/8,start%8,end-8*(start/8)>
214     {};
215
216 }}}
217
218 ///////////////////////////////ih.e////////////////////////////////////////
219 #endif
220
221 \f
222 // Local Variables:
223 // mode: c++
224 // fill-column: 100
225 // c-file-style: "senf"
226 // indent-tabs-mode: nil
227 // ispell-local-dictionary: "american"
228 // compile-command: "scons -u test"
229 // comment-column: 40
230 // End: