bitunion.hh (12453:424595e0a14e) bitunion.hh (12454:277c1f58ab6d)
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 <iostream>
35#include <type_traits>
36
37#include "base/bitfield.hh"
38
39// The following implements the BitUnion system of defining bitfields
40//on top of an underlying class. This is done through the pervasive use of
41//both named and unnamed unions which all contain the same actual storage.
42//Since they're unioned with each other, all of these storage locations
43//overlap. This allows all of the bitfields to manipulate the same data
44//without having to have access to each other. More details are provided with
45//the individual components.
46
47//This class wraps around another which defines getter/setter functions which
48//manipulate the underlying data. The type of the underlying data and the type
49//of the bitfield itself are inferred from the argument types of the setter
50//function.
51template<class Base>
52class BitfieldTypeImpl : public Base
53{
54 static_assert(std::is_empty<Base>::value,
55 "Bitfield base class must be empty.");
56
57 private:
58 using Base::setter;
59
60 template<typename T>
61 struct TypeDeducer;
62
63 template<typename T>
64 friend class TypeDeducer;
65
66 template<typename Type1, typename Type2>
67 struct TypeDeducer<void (Base::*)(Type1 &, Type2)>
68 {
69 typedef Type1 Storage;
70 typedef Type2 Type;
71 };
72
73 protected:
74 typedef typename TypeDeducer<
75 decltype(&BitfieldTypeImpl<Base>::setter)>::Storage Storage;
76 typedef typename TypeDeducer<
77 decltype(&BitfieldTypeImpl<Base>::setter)>::Type Type;
78
79 Type getter(const Storage &storage) const = delete;
80 void setter(Storage &storage, Type val) = delete;
81
82 Storage __storage;
83
84 operator Type () const
85 {
86 return Base::getter(__storage);
87 }
88
89 Type
90 operator=(const Type val)
91 {
92 Base::setter(__storage, val);
93 return val;
94 }
95
96 Type
97 operator=(BitfieldTypeImpl<Base> const & other)
98 {
99 return *this = (Type)other;
100 }
101};
102
103//A wrapper for the above class which allows setting and getting.
104template<class Base>
105class BitfieldType : public BitfieldTypeImpl<Base>
106{
107 protected:
108 using Impl = BitfieldTypeImpl<Base>;
109 using typename Impl::Type;
110
111 public:
112 operator Type () const { return Impl::operator Type(); }
113 Type operator=(const Type val) { return Impl::operator=(val); }
114 Type
115 operator=(BitfieldType<Base> const & other)
116 {
117 return Impl::operator=(other);
118 }
119};
120
121//A wrapper which only supports getting.
122template<class Base>
123class BitfieldROType : public BitfieldTypeImpl<Base>
124{
125 public:
126 using Impl = BitfieldTypeImpl<Base>;
127 using typename Impl::Type;
128
129 Type operator=(BitfieldROType<Base> const &other) = delete;
130 operator Type () const { return Impl::operator Type(); }
131};
132
133//A wrapper which only supports setting.
134template <class Base>
135class BitfieldWOType : public BitfieldTypeImpl<Base>
136{
137 protected:
138 using Impl = BitfieldTypeImpl<Base>;
139 using typename Impl::Type;
140
141 public:
142 Type operator=(const Type val) { return Impl::operator=(val); }
143 Type
144 operator=(BitfieldWOType<Base> const & other)
145 {
146 return Impl::operator=(other);
147 }
148};
149
150//This namespace is for classes which implement the backend of the BitUnion
151//stuff. Don't use any of these directly.
152namespace BitfieldBackend
153{
154 template<class Storage, int first, int last>
155 class Unsigned
156 {
157 static_assert(first >= last,
158 "Bitfield ranges must be specified as <msb, lsb>");
159
160 protected:
161 uint64_t
162 getter(const Storage &storage) const
163 {
164 return bits(storage, first, last);
165 }
166
167 void
168 setter(Storage &storage, uint64_t val)
169 {
170 replaceBits(storage, first, last, val);
171 }
172 };
173
174 template<class Storage, int first, int last>
175 class Signed
176 {
177 static_assert(first >= last,
178 "Bitfield ranges must be specified as <msb, lsb>");
179
180 protected:
181 int64_t
182 getter(const Storage &storage) const
183 {
184 return sext<first - last + 1>(bits(storage, first, last));
185 }
186
187 void
188 setter(Storage &storage, int64_t val)
189 {
190 replaceBits(storage, first, last, val);
191 }
192 };
193
194 //This class contains the basic bitfield types which are automatically
195 //available within a BitUnion. They inherit their Storage type from the
196 //containing BitUnion.
197 template<class Storage>
198 class BitfieldTypes
199 {
200 protected:
201
202 template<int first, int last=first>
203 using Bitfield = BitfieldType<Unsigned<Storage, first, last> >;
204 template<int first, int last=first>
205 using BitfieldRO =
206 BitfieldROType<Unsigned<Storage, first, last> >;
207 template<int first, int last=first>
208 using BitfieldWO =
209 BitfieldWOType<Unsigned<Storage, first, last> >;
210
211 template<int first, int last=first>
212 using SignedBitfield =
213 BitfieldType<Signed<Storage, first, last> >;
214 template<int first, int last=first>
215 using SignedBitfieldRO =
216 BitfieldROType<Signed<Storage, first, last> >;
217 template<int first, int last=first>
218 using SignedBitfieldWO =
219 BitfieldWOType<Signed<Storage, first, last> >;
220 };
221
222 //When a BitUnion is set up, an underlying class is created which holds
223 //the actual union. This class then inherits from it, and provids the
224 //implementations for various operators. Setting things up this way
225 //prevents having to redefine these functions in every different BitUnion
226 //type. More operators could be implemented in the future, as the need
227 //arises.
228 template <class Base>
229 class BitUnionOperators : public Base
230 {
231 static_assert(sizeof(Base) == sizeof(typename Base::__StorageType),
232 "BitUnion larger than its storage type.");
233
234 public:
235 BitUnionOperators(typename Base::__StorageType const &val)
236 {
237 Base::__storage = val;
238 }
239
240 BitUnionOperators() {}
241
242 operator const typename Base::__StorageType () const
243 {
244 return Base::__storage;
245 }
246
247 typename Base::__StorageType
248 operator=(typename Base::__StorageType const &val)
249 {
250 Base::__storage = val;
251 return val;
252 }
253
254 typename Base::__StorageType
255 operator=(BitUnionOperators const &other)
256 {
257 Base::__storage = other;
258 return Base::__storage;
259 }
260
261 bool
262 operator<(Base const &base) const
263 {
264 return Base::__storage < base.__storage;
265 }
266
267 bool
268 operator==(Base const &base) const
269 {
270 return Base::__storage == base.__storage;
271 }
272 };
273}
274
275//This macro is a backend for other macros that specialize it slightly.
276//First, it creates/extends a namespace "BitfieldUnderlyingClasses" and
277//sticks the class which has the actual union in it, which
278//BitfieldOperators above inherits from. Putting these classes in a special
279//namespace ensures that there will be no collisions with other names as long
280//as the BitUnion names themselves are all distinct and nothing else uses
281//the BitfieldUnderlyingClasses namespace, which is unlikely. The class itself
282//creates a typedef of the "type" parameter called __StorageType. This allows
283//the type to propagate outside of the macro itself in a controlled way.
284//Finally, the base storage is defined which BitfieldOperators will refer to
285//in the operators it defines. This macro is intended to be followed by
286//bitfield definitions which will end up inside it's union. As explained
287//above, these is overlayed the __storage member in its entirety by each of the
288//bitfields which are defined in the union, creating shared storage with no
289//overhead.
290#define __BitUnion(type, name) \
291 class BitfieldUnderlyingClasses##name : \
292 public BitfieldBackend::BitfieldTypes<type> \
293 { \
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 <iostream>
35#include <type_traits>
36
37#include "base/bitfield.hh"
38
39// The following implements the BitUnion system of defining bitfields
40//on top of an underlying class. This is done through the pervasive use of
41//both named and unnamed unions which all contain the same actual storage.
42//Since they're unioned with each other, all of these storage locations
43//overlap. This allows all of the bitfields to manipulate the same data
44//without having to have access to each other. More details are provided with
45//the individual components.
46
47//This class wraps around another which defines getter/setter functions which
48//manipulate the underlying data. The type of the underlying data and the type
49//of the bitfield itself are inferred from the argument types of the setter
50//function.
51template<class Base>
52class BitfieldTypeImpl : public Base
53{
54 static_assert(std::is_empty<Base>::value,
55 "Bitfield base class must be empty.");
56
57 private:
58 using Base::setter;
59
60 template<typename T>
61 struct TypeDeducer;
62
63 template<typename T>
64 friend class TypeDeducer;
65
66 template<typename Type1, typename Type2>
67 struct TypeDeducer<void (Base::*)(Type1 &, Type2)>
68 {
69 typedef Type1 Storage;
70 typedef Type2 Type;
71 };
72
73 protected:
74 typedef typename TypeDeducer<
75 decltype(&BitfieldTypeImpl<Base>::setter)>::Storage Storage;
76 typedef typename TypeDeducer<
77 decltype(&BitfieldTypeImpl<Base>::setter)>::Type Type;
78
79 Type getter(const Storage &storage) const = delete;
80 void setter(Storage &storage, Type val) = delete;
81
82 Storage __storage;
83
84 operator Type () const
85 {
86 return Base::getter(__storage);
87 }
88
89 Type
90 operator=(const Type val)
91 {
92 Base::setter(__storage, val);
93 return val;
94 }
95
96 Type
97 operator=(BitfieldTypeImpl<Base> const & other)
98 {
99 return *this = (Type)other;
100 }
101};
102
103//A wrapper for the above class which allows setting and getting.
104template<class Base>
105class BitfieldType : public BitfieldTypeImpl<Base>
106{
107 protected:
108 using Impl = BitfieldTypeImpl<Base>;
109 using typename Impl::Type;
110
111 public:
112 operator Type () const { return Impl::operator Type(); }
113 Type operator=(const Type val) { return Impl::operator=(val); }
114 Type
115 operator=(BitfieldType<Base> const & other)
116 {
117 return Impl::operator=(other);
118 }
119};
120
121//A wrapper which only supports getting.
122template<class Base>
123class BitfieldROType : public BitfieldTypeImpl<Base>
124{
125 public:
126 using Impl = BitfieldTypeImpl<Base>;
127 using typename Impl::Type;
128
129 Type operator=(BitfieldROType<Base> const &other) = delete;
130 operator Type () const { return Impl::operator Type(); }
131};
132
133//A wrapper which only supports setting.
134template <class Base>
135class BitfieldWOType : public BitfieldTypeImpl<Base>
136{
137 protected:
138 using Impl = BitfieldTypeImpl<Base>;
139 using typename Impl::Type;
140
141 public:
142 Type operator=(const Type val) { return Impl::operator=(val); }
143 Type
144 operator=(BitfieldWOType<Base> const & other)
145 {
146 return Impl::operator=(other);
147 }
148};
149
150//This namespace is for classes which implement the backend of the BitUnion
151//stuff. Don't use any of these directly.
152namespace BitfieldBackend
153{
154 template<class Storage, int first, int last>
155 class Unsigned
156 {
157 static_assert(first >= last,
158 "Bitfield ranges must be specified as <msb, lsb>");
159
160 protected:
161 uint64_t
162 getter(const Storage &storage) const
163 {
164 return bits(storage, first, last);
165 }
166
167 void
168 setter(Storage &storage, uint64_t val)
169 {
170 replaceBits(storage, first, last, val);
171 }
172 };
173
174 template<class Storage, int first, int last>
175 class Signed
176 {
177 static_assert(first >= last,
178 "Bitfield ranges must be specified as <msb, lsb>");
179
180 protected:
181 int64_t
182 getter(const Storage &storage) const
183 {
184 return sext<first - last + 1>(bits(storage, first, last));
185 }
186
187 void
188 setter(Storage &storage, int64_t val)
189 {
190 replaceBits(storage, first, last, val);
191 }
192 };
193
194 //This class contains the basic bitfield types which are automatically
195 //available within a BitUnion. They inherit their Storage type from the
196 //containing BitUnion.
197 template<class Storage>
198 class BitfieldTypes
199 {
200 protected:
201
202 template<int first, int last=first>
203 using Bitfield = BitfieldType<Unsigned<Storage, first, last> >;
204 template<int first, int last=first>
205 using BitfieldRO =
206 BitfieldROType<Unsigned<Storage, first, last> >;
207 template<int first, int last=first>
208 using BitfieldWO =
209 BitfieldWOType<Unsigned<Storage, first, last> >;
210
211 template<int first, int last=first>
212 using SignedBitfield =
213 BitfieldType<Signed<Storage, first, last> >;
214 template<int first, int last=first>
215 using SignedBitfieldRO =
216 BitfieldROType<Signed<Storage, first, last> >;
217 template<int first, int last=first>
218 using SignedBitfieldWO =
219 BitfieldWOType<Signed<Storage, first, last> >;
220 };
221
222 //When a BitUnion is set up, an underlying class is created which holds
223 //the actual union. This class then inherits from it, and provids the
224 //implementations for various operators. Setting things up this way
225 //prevents having to redefine these functions in every different BitUnion
226 //type. More operators could be implemented in the future, as the need
227 //arises.
228 template <class Base>
229 class BitUnionOperators : public Base
230 {
231 static_assert(sizeof(Base) == sizeof(typename Base::__StorageType),
232 "BitUnion larger than its storage type.");
233
234 public:
235 BitUnionOperators(typename Base::__StorageType const &val)
236 {
237 Base::__storage = val;
238 }
239
240 BitUnionOperators() {}
241
242 operator const typename Base::__StorageType () const
243 {
244 return Base::__storage;
245 }
246
247 typename Base::__StorageType
248 operator=(typename Base::__StorageType const &val)
249 {
250 Base::__storage = val;
251 return val;
252 }
253
254 typename Base::__StorageType
255 operator=(BitUnionOperators const &other)
256 {
257 Base::__storage = other;
258 return Base::__storage;
259 }
260
261 bool
262 operator<(Base const &base) const
263 {
264 return Base::__storage < base.__storage;
265 }
266
267 bool
268 operator==(Base const &base) const
269 {
270 return Base::__storage == base.__storage;
271 }
272 };
273}
274
275//This macro is a backend for other macros that specialize it slightly.
276//First, it creates/extends a namespace "BitfieldUnderlyingClasses" and
277//sticks the class which has the actual union in it, which
278//BitfieldOperators above inherits from. Putting these classes in a special
279//namespace ensures that there will be no collisions with other names as long
280//as the BitUnion names themselves are all distinct and nothing else uses
281//the BitfieldUnderlyingClasses namespace, which is unlikely. The class itself
282//creates a typedef of the "type" parameter called __StorageType. This allows
283//the type to propagate outside of the macro itself in a controlled way.
284//Finally, the base storage is defined which BitfieldOperators will refer to
285//in the operators it defines. This macro is intended to be followed by
286//bitfield definitions which will end up inside it's union. As explained
287//above, these is overlayed the __storage member in its entirety by each of the
288//bitfields which are defined in the union, creating shared storage with no
289//overhead.
290#define __BitUnion(type, name) \
291 class BitfieldUnderlyingClasses##name : \
292 public BitfieldBackend::BitfieldTypes<type> \
293 { \
294 public: \
294 protected: \
295 typedef type __StorageType; \
295 typedef type __StorageType; \
296 friend BitfieldBackend::BitUnionBaseType< \
297 BitfieldBackend::BitUnionOperators< \
298 BitfieldUnderlyingClasses##name> >; \
299 friend BitfieldBackend::BitUnionBaseType< \
300 BitfieldUnderlyingClasses##name>; \
301 public: \
296 union { \
297 type __storage;
298
299//This closes off the class and union started by the above macro. It is
300//followed by a typedef which makes "name" refer to a BitfieldOperator
301//class inheriting from the class and union just defined, which completes
302//building up the type for the user.
303#define EndBitUnion(name) \
304 }; \
305 }; \
306 typedef BitfieldBackend::BitUnionOperators< \
307 BitfieldUnderlyingClasses##name> name;
308
309//This sets up a bitfield which has other bitfields nested inside of it. The
310//__storage member functions like the "underlying storage" of the top level
311//BitUnion. Like everything else, it overlays with the top level storage, so
312//making it a regular bitfield type makes the entire thing function as a
313//regular bitfield when referred to by itself.
314#define __SubBitUnion(name, fieldType, ...) \
315 class \
316 { \
317 public: \
318 union { \
319 fieldType<__VA_ARGS__> __storage;
320
321//This closes off the union created above and gives it a name. Unlike the top
322//level BitUnion, we're interested in creating an object instead of a type.
323//The operators are defined in the macro itself instead of a class for
324//technical reasons. If someone determines a way to move them to one, please
325//do so.
326#define EndSubBitUnion(name) \
327 }; \
328 inline operator __StorageType () const \
329 { return __storage; } \
330 \
331 inline __StorageType operator = (const __StorageType & _storage) \
332 { return __storage = _storage;} \
333 } name;
334
335//Regular bitfields
336//These define macros for read/write regular bitfield based subbitfields.
337#define SubBitUnion(name, first, last) \
338 __SubBitUnion(name, Bitfield, first, last)
339
340//Regular bitfields
341//These define macros for read/write regular bitfield based subbitfields.
342#define SignedSubBitUnion(name, first, last) \
343 __SubBitUnion(name, SignedBitfield, first, last)
344
345//Use this to define an arbitrary type overlayed with bitfields.
346#define BitUnion(type, name) __BitUnion(type, name)
347
348//Use this to define conveniently sized values overlayed with bitfields.
349#define BitUnion64(name) __BitUnion(uint64_t, name)
350#define BitUnion32(name) __BitUnion(uint32_t, name)
351#define BitUnion16(name) __BitUnion(uint16_t, name)
352#define BitUnion8(name) __BitUnion(uint8_t, name)
353
354
355//These templates make it possible to define other templates related to
356//BitUnions without having to refer to internal typedefs or the BitfieldBackend
357//namespace.
358
359//To build a template specialization which works for all BitUnions, accept a
360//template argument T, and then use BitUnionType<T> as an argument in the
361//template. To refer to the basic type the BitUnion wraps, use
362//BitUnionBaseType<T>.
363
364//For example:
365//template <typename T>
366//void func(BitUnionType<T> u) { BitUnionBaseType<T> b = u; }
367
368//Also, BitUnionBaseType can be used on a BitUnion type directly.
369
370template <typename T>
371using BitUnionType = BitfieldBackend::BitUnionOperators<T>;
372
373namespace BitfieldBackend
374{
375 template<typename T>
376 struct BitUnionBaseType
377 {
378 typedef typename BitUnionType<T>::__StorageType Type;
379 };
380
381 template<typename T>
382 struct BitUnionBaseType<BitUnionType<T> >
383 {
384 typedef typename BitUnionType<T>::__StorageType Type;
385 };
386}
387
388template <typename T>
389using BitUnionBaseType = typename BitfieldBackend::BitUnionBaseType<T>::Type;
390
302 union { \
303 type __storage;
304
305//This closes off the class and union started by the above macro. It is
306//followed by a typedef which makes "name" refer to a BitfieldOperator
307//class inheriting from the class and union just defined, which completes
308//building up the type for the user.
309#define EndBitUnion(name) \
310 }; \
311 }; \
312 typedef BitfieldBackend::BitUnionOperators< \
313 BitfieldUnderlyingClasses##name> name;
314
315//This sets up a bitfield which has other bitfields nested inside of it. The
316//__storage member functions like the "underlying storage" of the top level
317//BitUnion. Like everything else, it overlays with the top level storage, so
318//making it a regular bitfield type makes the entire thing function as a
319//regular bitfield when referred to by itself.
320#define __SubBitUnion(name, fieldType, ...) \
321 class \
322 { \
323 public: \
324 union { \
325 fieldType<__VA_ARGS__> __storage;
326
327//This closes off the union created above and gives it a name. Unlike the top
328//level BitUnion, we're interested in creating an object instead of a type.
329//The operators are defined in the macro itself instead of a class for
330//technical reasons. If someone determines a way to move them to one, please
331//do so.
332#define EndSubBitUnion(name) \
333 }; \
334 inline operator __StorageType () const \
335 { return __storage; } \
336 \
337 inline __StorageType operator = (const __StorageType & _storage) \
338 { return __storage = _storage;} \
339 } name;
340
341//Regular bitfields
342//These define macros for read/write regular bitfield based subbitfields.
343#define SubBitUnion(name, first, last) \
344 __SubBitUnion(name, Bitfield, first, last)
345
346//Regular bitfields
347//These define macros for read/write regular bitfield based subbitfields.
348#define SignedSubBitUnion(name, first, last) \
349 __SubBitUnion(name, SignedBitfield, first, last)
350
351//Use this to define an arbitrary type overlayed with bitfields.
352#define BitUnion(type, name) __BitUnion(type, name)
353
354//Use this to define conveniently sized values overlayed with bitfields.
355#define BitUnion64(name) __BitUnion(uint64_t, name)
356#define BitUnion32(name) __BitUnion(uint32_t, name)
357#define BitUnion16(name) __BitUnion(uint16_t, name)
358#define BitUnion8(name) __BitUnion(uint8_t, name)
359
360
361//These templates make it possible to define other templates related to
362//BitUnions without having to refer to internal typedefs or the BitfieldBackend
363//namespace.
364
365//To build a template specialization which works for all BitUnions, accept a
366//template argument T, and then use BitUnionType<T> as an argument in the
367//template. To refer to the basic type the BitUnion wraps, use
368//BitUnionBaseType<T>.
369
370//For example:
371//template <typename T>
372//void func(BitUnionType<T> u) { BitUnionBaseType<T> b = u; }
373
374//Also, BitUnionBaseType can be used on a BitUnion type directly.
375
376template <typename T>
377using BitUnionType = BitfieldBackend::BitUnionOperators<T>;
378
379namespace BitfieldBackend
380{
381 template<typename T>
382 struct BitUnionBaseType
383 {
384 typedef typename BitUnionType<T>::__StorageType Type;
385 };
386
387 template<typename T>
388 struct BitUnionBaseType<BitUnionType<T> >
389 {
390 typedef typename BitUnionType<T>::__StorageType Type;
391 };
392}
393
394template <typename T>
395using BitUnionBaseType = typename BitfieldBackend::BitUnionBaseType<T>::Type;
396
397
398//An STL style hash structure for hashing BitUnions based on their base type.
391namespace std
392{
393 template <typename T>
394 struct hash;
395
396 template <typename T>
397 struct hash<BitUnionType<T> > : public hash<BitUnionBaseType<T> >
398 {
399 size_t
400 operator() (const BitUnionType<T> &val) const
401 {
402 return hash<BitUnionBaseType<T> >::operator()(val);
403 }
404 };
405}
406
407#endif // __BASE_BITUNION_HH__
399namespace std
400{
401 template <typename T>
402 struct hash;
403
404 template <typename T>
405 struct hash<BitUnionType<T> > : public hash<BitUnionBaseType<T> >
406 {
407 size_t
408 operator() (const BitUnionType<T> &val) const
409 {
410 return hash<BitUnionBaseType<T> >::operator()(val);
411 }
412 };
413}
414
415#endif // __BASE_BITUNION_HH__