bitunion.hh (12625:c0cf272e0456) bitunion.hh (12631:d48fc4cce6eb)
1/*
2 * Copyright (c) 2007-2008 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Gabe Black
29 */
30
31#ifndef __BASE_BITUNION_HH__
32#define __BASE_BITUNION_HH__
33
34#include <functional>
35#include <iostream>
36#include <type_traits>
37#include <typeinfo>
38
39#include "base/bitfield.hh"
40
41// The following implements the BitUnion system of defining bitfields
42//on top of an underlying class. This is done through the pervasive use of
43//both named and unnamed unions which all contain the same actual storage.
44//Since they're unioned with each other, all of these storage locations
45//overlap. This allows all of the bitfields to manipulate the same data
46//without having to have access to each other. More details are provided with
47//the individual components.
48
49//This class wraps around another which defines getter/setter functions which
50//manipulate the underlying data. The type of the underlying data and the type
51//of the bitfield itself are inferred from the argument types of the setter
52//function.
53template<class Base>
54class BitfieldTypeImpl : public Base
55{
56 static_assert(std::is_empty<Base>::value,
57 "Bitfield base class must be empty.");
58
59 private:
60
61 struct TypeDeducer
62 {
63 template<typename>
64 struct T;
65
66 template<typename C, typename Type1, typename Type2>
67 struct T<void (C::*)(Type1 &, Type2)>
68 {
69 typedef Type1 Storage;
70 typedef Type2 Type;
71 };
72
73 struct Wrapper : public Base
74 {
75 using Base::setter;
76 };
77
78 typedef typename T<decltype(&Wrapper::setter)>::Storage Storage;
79 typedef typename T<decltype(&Wrapper::setter)>::Type Type;
80 };
81
82 protected:
83 typedef typename TypeDeducer::Storage Storage;
84 typedef typename TypeDeducer::Type Type;
85
86 Type getter(const Storage &storage) const = delete;
87 void setter(Storage &storage, Type val) = delete;
88
89 Storage __storage;
90
91 operator Type () const
92 {
93 return Base::getter(__storage);
94 }
95
96 Type
97 operator=(const Type val)
98 {
99 Base::setter(__storage, val);
100 return val;
101 }
102
103 Type
104 operator=(BitfieldTypeImpl<Base> const & other)
105 {
106 return *this = (Type)other;
107 }
108};
109
110//A wrapper for the above class which allows setting and getting.
111template<class Base>
112class BitfieldType : public BitfieldTypeImpl<Base>
113{
114 protected:
115 using Impl = BitfieldTypeImpl<Base>;
116 using typename Impl::Type;
117
118 public:
119 operator Type () const { return Impl::operator Type(); }
120 Type operator=(const Type val) { return Impl::operator=(val); }
121 Type
122 operator=(BitfieldType<Base> const & other)
123 {
124 return Impl::operator=(other);
125 }
126};
127
128//A wrapper which only supports getting.
129template<class Base>
130class BitfieldROType : public BitfieldTypeImpl<Base>
131{
132 public:
133 using Impl = BitfieldTypeImpl<Base>;
134 using typename Impl::Type;
135
136 Type operator=(BitfieldROType<Base> const &other) = delete;
137 operator Type () const { return Impl::operator Type(); }
138};
139
140//A wrapper which only supports setting.
141template <class Base>
142class BitfieldWOType : public BitfieldTypeImpl<Base>
143{
144 protected:
145 using Impl = BitfieldTypeImpl<Base>;
146 using typename Impl::Type;
147
148 public:
149 Type operator=(const Type val) { return Impl::operator=(val); }
150 Type
151 operator=(BitfieldWOType<Base> const & other)
152 {
153 return Impl::operator=(other);
154 }
155};
156
157//This namespace is for classes which implement the backend of the BitUnion
158//stuff. Don't use any of these directly.
159namespace BitfieldBackend
160{
161 template<class Storage, int first, int last>
162 class Unsigned
163 {
164 static_assert(first >= last,
165 "Bitfield ranges must be specified as <msb, lsb>");
166
167 protected:
168 uint64_t
169 getter(const Storage &storage) const
170 {
171 return bits(storage, first, last);
172 }
173
174 void
175 setter(Storage &storage, uint64_t val)
176 {
177 replaceBits(storage, first, last, val);
178 }
179 };
180
181 template<class Storage, int first, int last>
182 class Signed
183 {
184 static_assert(first >= last,
185 "Bitfield ranges must be specified as <msb, lsb>");
186
187 protected:
188 int64_t
189 getter(const Storage &storage) const
190 {
191 return sext<first - last + 1>(bits(storage, first, last));
192 }
193
194 void
195 setter(Storage &storage, int64_t val)
196 {
197 replaceBits(storage, first, last, val);
198 }
199 };
200
201 //This class contains the basic bitfield types which are automatically
202 //available within a BitUnion. They inherit their Storage type from the
203 //containing BitUnion.
204 template<class Storage>
205 class BitfieldTypes
206 {
207 protected:
208
209 template<int first, int last=first>
210 using Bitfield = BitfieldType<Unsigned<Storage, first, last> >;
211 template<int first, int last=first>
212 using BitfieldRO =
213 BitfieldROType<Unsigned<Storage, first, last> >;
214 template<int first, int last=first>
215 using BitfieldWO =
216 BitfieldWOType<Unsigned<Storage, first, last> >;
217
218 template<int first, int last=first>
219 using SignedBitfield =
220 BitfieldType<Signed<Storage, first, last> >;
221 template<int first, int last=first>
222 using SignedBitfieldRO =
223 BitfieldROType<Signed<Storage, first, last> >;
224 template<int first, int last=first>
225 using SignedBitfieldWO =
226 BitfieldWOType<Signed<Storage, first, last> >;
227 };
228
229 //When a BitUnion is set up, an underlying class is created which holds
230 //the actual union. This class then inherits from it, and provids the
231 //implementations for various operators. Setting things up this way
232 //prevents having to redefine these functions in every different BitUnion
233 //type. More operators could be implemented in the future, as the need
234 //arises.
235 template <class Base>
236 class BitUnionOperators : public Base
237 {
238 static_assert(sizeof(Base) == sizeof(typename Base::__StorageType),
239 "BitUnion larger than its storage type.");
240
241 public:
242 BitUnionOperators(typename Base::__StorageType const &val)
243 {
244 Base::__storage = val;
245 }
246
247 BitUnionOperators() {}
248
249 operator const typename Base::__StorageType () const
250 {
251 return Base::__storage;
252 }
253
254 typename Base::__StorageType
255 operator=(typename Base::__StorageType const &val)
256 {
257 Base::__storage = val;
258 return val;
259 }
260
261 typename Base::__StorageType
262 operator=(BitUnionOperators const &other)
263 {
264 Base::__storage = other;
265 return Base::__storage;
266 }
267
268 bool
269 operator<(Base const &base) const
270 {
271 return Base::__storage < base.__storage;
272 }
273
274 bool
275 operator==(Base const &base) const
276 {
277 return Base::__storage == base.__storage;
278 }
279 };
280}
281
282//This macro is a backend for other macros that specialize it slightly.
283//First, it creates/extends a namespace "BitfieldUnderlyingClasses" and
284//sticks the class which has the actual union in it, which
285//BitfieldOperators above inherits from. Putting these classes in a special
286//namespace ensures that there will be no collisions with other names as long
287//as the BitUnion names themselves are all distinct and nothing else uses
288//the BitfieldUnderlyingClasses namespace, which is unlikely. The class itself
289//creates a typedef of the "type" parameter called __StorageType. This allows
290//the type to propagate outside of the macro itself in a controlled way.
291//Finally, the base storage is defined which BitfieldOperators will refer to
292//in the operators it defines. This macro is intended to be followed by
293//bitfield definitions which will end up inside it's union. As explained
294//above, these is overlayed the __storage member in its entirety by each of the
295//bitfields which are defined in the union, creating shared storage with no
296//overhead.
297#define __BitUnion(type, name) \
298 class BitfieldUnderlyingClasses##name : \
299 public BitfieldBackend::BitfieldTypes<type> \
300 { \
301 protected: \
302 typedef type __StorageType; \
303 friend BitfieldBackend::BitUnionBaseType< \
304 BitfieldBackend::BitUnionOperators< \
305 BitfieldUnderlyingClasses##name> >; \
306 friend BitfieldBackend::BitUnionBaseType< \
307 BitfieldUnderlyingClasses##name>; \
308 public: \
309 union { \
310 type __storage;
311
312//This closes off the class and union started by the above macro. It is
313//followed by a typedef which makes "name" refer to a BitfieldOperator
314//class inheriting from the class and union just defined, which completes
315//building up the type for the user.
316#define EndBitUnion(name) \
317 }; \
318 }; \
319 typedef BitfieldBackend::BitUnionOperators< \
320 BitfieldUnderlyingClasses##name> name;
321
322//This sets up a bitfield which has other bitfields nested inside of it. The
323//__storage member functions like the "underlying storage" of the top level
324//BitUnion. Like everything else, it overlays with the top level storage, so
325//making it a regular bitfield type makes the entire thing function as a
326//regular bitfield when referred to by itself.
327#define __SubBitUnion(name, fieldType, ...) \
328 class \
329 { \
330 public: \
331 union { \
332 fieldType<__VA_ARGS__> __storage;
333
334//This closes off the union created above and gives it a name. Unlike the top
335//level BitUnion, we're interested in creating an object instead of a type.
336//The operators are defined in the macro itself instead of a class for
337//technical reasons. If someone determines a way to move them to one, please
338//do so.
339#define EndSubBitUnion(name) \
340 }; \
341 inline operator __StorageType () const \
342 { return __storage; } \
343 \
344 inline __StorageType operator = (const __StorageType & _storage) \
345 { return __storage = _storage;} \
346 } name;
347
348//Regular bitfields
349//These define macros for read/write regular bitfield based subbitfields.
350#define SubBitUnion(name, first, last) \
351 __SubBitUnion(name, Bitfield, first, last)
352
353//Regular bitfields
354//These define macros for read/write regular bitfield based subbitfields.
355#define SignedSubBitUnion(name, first, last) \
356 __SubBitUnion(name, SignedBitfield, first, last)
357
358//Use this to define an arbitrary type overlayed with bitfields.
359#define BitUnion(type, name) __BitUnion(type, name)
360
361//Use this to define conveniently sized values overlayed with bitfields.
362#define BitUnion64(name) __BitUnion(uint64_t, name)
363#define BitUnion32(name) __BitUnion(uint32_t, name)
364#define BitUnion16(name) __BitUnion(uint16_t, name)
365#define BitUnion8(name) __BitUnion(uint8_t, name)
366
367
368//These templates make it possible to define other templates related to
369//BitUnions without having to refer to internal typedefs or the BitfieldBackend
370//namespace.
371
372//To build a template specialization which works for all BitUnions, accept a
373//template argument T, and then use BitUnionType<T> as an argument in the
374//template. To refer to the basic type the BitUnion wraps, use
375//BitUnionBaseType<T>.
376
377//For example:
378//template <typename T>
379//void func(BitUnionType<T> u) { BitUnionBaseType<T> b = u; }
380
381//Also, BitUnionBaseType can be used on a BitUnion type directly.
382
383template <typename T>
384using BitUnionType = BitfieldBackend::BitUnionOperators<T>;
385
386namespace BitfieldBackend
387{
388 template<typename T>
389 struct BitUnionBaseType
390 {
391 typedef typename BitUnionType<T>::__StorageType Type;
392 };
393
394 template<typename T>
395 struct BitUnionBaseType<BitUnionType<T> >
396 {
397 typedef typename BitUnionType<T>::__StorageType Type;
398 };
399}
400
401template <typename T>
402using BitUnionBaseType = typename BitfieldBackend::BitUnionBaseType<T>::Type;
403
404
405//An STL style hash structure for hashing BitUnions based on their base type.
406namespace std
407{
408 template <typename T>
409 struct hash<BitUnionType<T> > : public hash<BitUnionBaseType<T> >
410 {
411 size_t
412 operator() (const BitUnionType<T> &val) const
413 {
414 return hash<BitUnionBaseType<T> >::operator()(val);
415 }
416 };
417}
418
419
420namespace BitfieldBackend
421{
1/*
2 * Copyright (c) 2007-2008 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Gabe Black
29 */
30
31#ifndef __BASE_BITUNION_HH__
32#define __BASE_BITUNION_HH__
33
34#include <functional>
35#include <iostream>
36#include <type_traits>
37#include <typeinfo>
38
39#include "base/bitfield.hh"
40
41// The following implements the BitUnion system of defining bitfields
42//on top of an underlying class. This is done through the pervasive use of
43//both named and unnamed unions which all contain the same actual storage.
44//Since they're unioned with each other, all of these storage locations
45//overlap. This allows all of the bitfields to manipulate the same data
46//without having to have access to each other. More details are provided with
47//the individual components.
48
49//This class wraps around another which defines getter/setter functions which
50//manipulate the underlying data. The type of the underlying data and the type
51//of the bitfield itself are inferred from the argument types of the setter
52//function.
53template<class Base>
54class BitfieldTypeImpl : public Base
55{
56 static_assert(std::is_empty<Base>::value,
57 "Bitfield base class must be empty.");
58
59 private:
60
61 struct TypeDeducer
62 {
63 template<typename>
64 struct T;
65
66 template<typename C, typename Type1, typename Type2>
67 struct T<void (C::*)(Type1 &, Type2)>
68 {
69 typedef Type1 Storage;
70 typedef Type2 Type;
71 };
72
73 struct Wrapper : public Base
74 {
75 using Base::setter;
76 };
77
78 typedef typename T<decltype(&Wrapper::setter)>::Storage Storage;
79 typedef typename T<decltype(&Wrapper::setter)>::Type Type;
80 };
81
82 protected:
83 typedef typename TypeDeducer::Storage Storage;
84 typedef typename TypeDeducer::Type Type;
85
86 Type getter(const Storage &storage) const = delete;
87 void setter(Storage &storage, Type val) = delete;
88
89 Storage __storage;
90
91 operator Type () const
92 {
93 return Base::getter(__storage);
94 }
95
96 Type
97 operator=(const Type val)
98 {
99 Base::setter(__storage, val);
100 return val;
101 }
102
103 Type
104 operator=(BitfieldTypeImpl<Base> const & other)
105 {
106 return *this = (Type)other;
107 }
108};
109
110//A wrapper for the above class which allows setting and getting.
111template<class Base>
112class BitfieldType : public BitfieldTypeImpl<Base>
113{
114 protected:
115 using Impl = BitfieldTypeImpl<Base>;
116 using typename Impl::Type;
117
118 public:
119 operator Type () const { return Impl::operator Type(); }
120 Type operator=(const Type val) { return Impl::operator=(val); }
121 Type
122 operator=(BitfieldType<Base> const & other)
123 {
124 return Impl::operator=(other);
125 }
126};
127
128//A wrapper which only supports getting.
129template<class Base>
130class BitfieldROType : public BitfieldTypeImpl<Base>
131{
132 public:
133 using Impl = BitfieldTypeImpl<Base>;
134 using typename Impl::Type;
135
136 Type operator=(BitfieldROType<Base> const &other) = delete;
137 operator Type () const { return Impl::operator Type(); }
138};
139
140//A wrapper which only supports setting.
141template <class Base>
142class BitfieldWOType : public BitfieldTypeImpl<Base>
143{
144 protected:
145 using Impl = BitfieldTypeImpl<Base>;
146 using typename Impl::Type;
147
148 public:
149 Type operator=(const Type val) { return Impl::operator=(val); }
150 Type
151 operator=(BitfieldWOType<Base> const & other)
152 {
153 return Impl::operator=(other);
154 }
155};
156
157//This namespace is for classes which implement the backend of the BitUnion
158//stuff. Don't use any of these directly.
159namespace BitfieldBackend
160{
161 template<class Storage, int first, int last>
162 class Unsigned
163 {
164 static_assert(first >= last,
165 "Bitfield ranges must be specified as <msb, lsb>");
166
167 protected:
168 uint64_t
169 getter(const Storage &storage) const
170 {
171 return bits(storage, first, last);
172 }
173
174 void
175 setter(Storage &storage, uint64_t val)
176 {
177 replaceBits(storage, first, last, val);
178 }
179 };
180
181 template<class Storage, int first, int last>
182 class Signed
183 {
184 static_assert(first >= last,
185 "Bitfield ranges must be specified as <msb, lsb>");
186
187 protected:
188 int64_t
189 getter(const Storage &storage) const
190 {
191 return sext<first - last + 1>(bits(storage, first, last));
192 }
193
194 void
195 setter(Storage &storage, int64_t val)
196 {
197 replaceBits(storage, first, last, val);
198 }
199 };
200
201 //This class contains the basic bitfield types which are automatically
202 //available within a BitUnion. They inherit their Storage type from the
203 //containing BitUnion.
204 template<class Storage>
205 class BitfieldTypes
206 {
207 protected:
208
209 template<int first, int last=first>
210 using Bitfield = BitfieldType<Unsigned<Storage, first, last> >;
211 template<int first, int last=first>
212 using BitfieldRO =
213 BitfieldROType<Unsigned<Storage, first, last> >;
214 template<int first, int last=first>
215 using BitfieldWO =
216 BitfieldWOType<Unsigned<Storage, first, last> >;
217
218 template<int first, int last=first>
219 using SignedBitfield =
220 BitfieldType<Signed<Storage, first, last> >;
221 template<int first, int last=first>
222 using SignedBitfieldRO =
223 BitfieldROType<Signed<Storage, first, last> >;
224 template<int first, int last=first>
225 using SignedBitfieldWO =
226 BitfieldWOType<Signed<Storage, first, last> >;
227 };
228
229 //When a BitUnion is set up, an underlying class is created which holds
230 //the actual union. This class then inherits from it, and provids the
231 //implementations for various operators. Setting things up this way
232 //prevents having to redefine these functions in every different BitUnion
233 //type. More operators could be implemented in the future, as the need
234 //arises.
235 template <class Base>
236 class BitUnionOperators : public Base
237 {
238 static_assert(sizeof(Base) == sizeof(typename Base::__StorageType),
239 "BitUnion larger than its storage type.");
240
241 public:
242 BitUnionOperators(typename Base::__StorageType const &val)
243 {
244 Base::__storage = val;
245 }
246
247 BitUnionOperators() {}
248
249 operator const typename Base::__StorageType () const
250 {
251 return Base::__storage;
252 }
253
254 typename Base::__StorageType
255 operator=(typename Base::__StorageType const &val)
256 {
257 Base::__storage = val;
258 return val;
259 }
260
261 typename Base::__StorageType
262 operator=(BitUnionOperators const &other)
263 {
264 Base::__storage = other;
265 return Base::__storage;
266 }
267
268 bool
269 operator<(Base const &base) const
270 {
271 return Base::__storage < base.__storage;
272 }
273
274 bool
275 operator==(Base const &base) const
276 {
277 return Base::__storage == base.__storage;
278 }
279 };
280}
281
282//This macro is a backend for other macros that specialize it slightly.
283//First, it creates/extends a namespace "BitfieldUnderlyingClasses" and
284//sticks the class which has the actual union in it, which
285//BitfieldOperators above inherits from. Putting these classes in a special
286//namespace ensures that there will be no collisions with other names as long
287//as the BitUnion names themselves are all distinct and nothing else uses
288//the BitfieldUnderlyingClasses namespace, which is unlikely. The class itself
289//creates a typedef of the "type" parameter called __StorageType. This allows
290//the type to propagate outside of the macro itself in a controlled way.
291//Finally, the base storage is defined which BitfieldOperators will refer to
292//in the operators it defines. This macro is intended to be followed by
293//bitfield definitions which will end up inside it's union. As explained
294//above, these is overlayed the __storage member in its entirety by each of the
295//bitfields which are defined in the union, creating shared storage with no
296//overhead.
297#define __BitUnion(type, name) \
298 class BitfieldUnderlyingClasses##name : \
299 public BitfieldBackend::BitfieldTypes<type> \
300 { \
301 protected: \
302 typedef type __StorageType; \
303 friend BitfieldBackend::BitUnionBaseType< \
304 BitfieldBackend::BitUnionOperators< \
305 BitfieldUnderlyingClasses##name> >; \
306 friend BitfieldBackend::BitUnionBaseType< \
307 BitfieldUnderlyingClasses##name>; \
308 public: \
309 union { \
310 type __storage;
311
312//This closes off the class and union started by the above macro. It is
313//followed by a typedef which makes "name" refer to a BitfieldOperator
314//class inheriting from the class and union just defined, which completes
315//building up the type for the user.
316#define EndBitUnion(name) \
317 }; \
318 }; \
319 typedef BitfieldBackend::BitUnionOperators< \
320 BitfieldUnderlyingClasses##name> name;
321
322//This sets up a bitfield which has other bitfields nested inside of it. The
323//__storage member functions like the "underlying storage" of the top level
324//BitUnion. Like everything else, it overlays with the top level storage, so
325//making it a regular bitfield type makes the entire thing function as a
326//regular bitfield when referred to by itself.
327#define __SubBitUnion(name, fieldType, ...) \
328 class \
329 { \
330 public: \
331 union { \
332 fieldType<__VA_ARGS__> __storage;
333
334//This closes off the union created above and gives it a name. Unlike the top
335//level BitUnion, we're interested in creating an object instead of a type.
336//The operators are defined in the macro itself instead of a class for
337//technical reasons. If someone determines a way to move them to one, please
338//do so.
339#define EndSubBitUnion(name) \
340 }; \
341 inline operator __StorageType () const \
342 { return __storage; } \
343 \
344 inline __StorageType operator = (const __StorageType & _storage) \
345 { return __storage = _storage;} \
346 } name;
347
348//Regular bitfields
349//These define macros for read/write regular bitfield based subbitfields.
350#define SubBitUnion(name, first, last) \
351 __SubBitUnion(name, Bitfield, first, last)
352
353//Regular bitfields
354//These define macros for read/write regular bitfield based subbitfields.
355#define SignedSubBitUnion(name, first, last) \
356 __SubBitUnion(name, SignedBitfield, first, last)
357
358//Use this to define an arbitrary type overlayed with bitfields.
359#define BitUnion(type, name) __BitUnion(type, name)
360
361//Use this to define conveniently sized values overlayed with bitfields.
362#define BitUnion64(name) __BitUnion(uint64_t, name)
363#define BitUnion32(name) __BitUnion(uint32_t, name)
364#define BitUnion16(name) __BitUnion(uint16_t, name)
365#define BitUnion8(name) __BitUnion(uint8_t, name)
366
367
368//These templates make it possible to define other templates related to
369//BitUnions without having to refer to internal typedefs or the BitfieldBackend
370//namespace.
371
372//To build a template specialization which works for all BitUnions, accept a
373//template argument T, and then use BitUnionType<T> as an argument in the
374//template. To refer to the basic type the BitUnion wraps, use
375//BitUnionBaseType<T>.
376
377//For example:
378//template <typename T>
379//void func(BitUnionType<T> u) { BitUnionBaseType<T> b = u; }
380
381//Also, BitUnionBaseType can be used on a BitUnion type directly.
382
383template <typename T>
384using BitUnionType = BitfieldBackend::BitUnionOperators<T>;
385
386namespace BitfieldBackend
387{
388 template<typename T>
389 struct BitUnionBaseType
390 {
391 typedef typename BitUnionType<T>::__StorageType Type;
392 };
393
394 template<typename T>
395 struct BitUnionBaseType<BitUnionType<T> >
396 {
397 typedef typename BitUnionType<T>::__StorageType Type;
398 };
399}
400
401template <typename T>
402using BitUnionBaseType = typename BitfieldBackend::BitUnionBaseType<T>::Type;
403
404
405//An STL style hash structure for hashing BitUnions based on their base type.
406namespace std
407{
408 template <typename T>
409 struct hash<BitUnionType<T> > : public hash<BitUnionBaseType<T> >
410 {
411 size_t
412 operator() (const BitUnionType<T> &val) const
413 {
414 return hash<BitUnionBaseType<T> >::operator()(val);
415 }
416 };
417}
418
419
420namespace BitfieldBackend
421{
422namespace
423{
422
424 template<typename T>
423 template<typename T>
425 std::ostream &
424 static inline std::ostream &
426 bitfieldBackendPrinter(std::ostream &os, const T &t)
427 {
428 os << t;
429 return os;
430 }
431
432 //Since BitUnions are generally numerical values and not character codes,
433 //these specializations attempt to ensure that they get cast to integers
434 //of the appropriate type before printing.
435 template <>
425 bitfieldBackendPrinter(std::ostream &os, const T &t)
426 {
427 os << t;
428 return os;
429 }
430
431 //Since BitUnions are generally numerical values and not character codes,
432 //these specializations attempt to ensure that they get cast to integers
433 //of the appropriate type before printing.
434 template <>
436 std::ostream &
435 inline std::ostream &
437 bitfieldBackendPrinter(std::ostream &os, const char &t)
438 {
439 os << (const int)t;
440 return os;
441 }
442
443 template <>
436 bitfieldBackendPrinter(std::ostream &os, const char &t)
437 {
438 os << (const int)t;
439 return os;
440 }
441
442 template <>
444 std::ostream &
443 inline std::ostream &
445 bitfieldBackendPrinter(std::ostream &os, const unsigned char &t)
446 {
447 os << (const unsigned int)t;
448 return os;
449 }
450}
444 bitfieldBackendPrinter(std::ostream &os, const unsigned char &t)
445 {
446 os << (const unsigned int)t;
447 return os;
448 }
449}
451}
452
453//A default << operator which casts a bitunion to its underlying type and
454//passes it to BitfieldBackend::bitfieldBackendPrinter.
455template <typename T>
456std::ostream &
457operator << (std::ostream &os, const BitUnionType<T> &bu)
458{
459 return BitfieldBackend::bitfieldBackendPrinter(
460 os, (BitUnionBaseType<T>)bu);
461}
462
463#endif // __BASE_BITUNION_HH__
450
451//A default << operator which casts a bitunion to its underlying type and
452//passes it to BitfieldBackend::bitfieldBackendPrinter.
453template <typename T>
454std::ostream &
455operator << (std::ostream &os, const BitUnionType<T> &bu)
456{
457 return BitfieldBackend::bitfieldBackendPrinter(
458 os, (BitUnionBaseType<T>)bu);
459}
460
461#endif // __BASE_BITUNION_HH__