1 //////////////////////////////////////////////////////////////////////////////// 2 // The Loki Library 3 // Copyright (c) 2009 by Fedor Pikus & Rich Sposato 4 // The copyright on this file is protected under the terms of the MIT license. 5 // 6 // Permission to use, copy, modify, distribute and sell this software for any 7 // purpose is hereby granted without fee, provided that the above copyright 8 // notice appear in all copies and that both that copyright notice and this 9 // permission notice appear in supporting documentation. 10 // 11 // The author makes no claims about the suitability of this software for any 12 // purpose. It is provided "as is" without express or implied warranty. 13 //////////////////////////////////////////////////////////////////////////////// 14 15 // $Id$ 16 17 18 #ifndef LOKI_INCLUDED_SAFE_BIT_FIELDS_H 19 #define LOKI_INCLUDED_SAFE_BIT_FIELDS_H 20 21 #include <cstdlib> 22 #include <assert.h> 23 #include <loki/static_check.h> 24 25 26 namespace Loki 27 { 28 29 /* 30 ========================================================================================================================================== 31 SafeBitField - type-safe class for bit fields. 32 SafeBitConst - type-safe class for bit constants. 33 SafeBitField is designed to be a [almost] drop-in replacement for integer flags and bit fields where individual bits are set and checked 34 using symbolic names for flags: 35 36 typedef unsigned long Labels_t; 37 Labels_t labels; 38 const Labels_t Label_A = 0x00000001; 39 const Labels_t Label_B = 0x00000002; 40 ... 41 labels |= Label_B; 42 if ( labels & Label_A ) { ... } 43 44 Such code offers no protection against mismatching bit constants and bit fields: 45 46 typedef unsigned long Kinds_t; 47 Kinds_t kinds; 48 const Kinds_t Kind_A = 0x00000004; 49 ... 50 if ( kinds & Label_A ) { ... } // Error but compiles 51 52 SafeBitField is a drop-in replacement which generates a unique type for each bit field. Bit fields of different types cannot be applied 53 to each other: 54 55 LOKI_BIT_FIELD( unsigned long ) Labels_t; 56 Labels_t labels; 57 LOKI_BIT_CONST( Labels_t, Label_A, 1 ); // 0x0001 - 1st bit is set 58 LOKI_BIT_CONST( Labels_t, Label_B, 2 ); // 0x0002 - 1st bit is set 59 ... 60 LOKI_BIT_FIELD( unsigned long ) Kinds_t; 61 Kinds_t kinds; 62 LOKI_BIT_CONST( Kinds_t, Kind_A, 3 ); // 0x0004 - 1st bit is set 63 ... 64 if ( kinds & Label_A ) { ... } // Does not compile 65 66 Several other kinds of bit field misuse are caught by safe bit fields: 67 68 if ( kinds & Kind_A == 0 ) { ... } 69 if ( kinds && Kind_A ) { ... } 70 71 There are few cases where drop-in replacement does not work: 72 73 1. Operations involving bit fields and unnamed integers. Usually the integer in question is 0: 74 75 Labels_t labels = 0; // No longer compiles 76 if ( ( labels & Label_A ) == 0 ) { ... } // Also does not compile 77 78 The solution is to use named bit constants, including the one for 0: 79 80 LOKI_BIT_CONST( Labels_t, Label_None, 0 ); // 0x0000 - No bit is set 81 Labels_t labels = Label_None; // Or just Labels_t labels; - constructor initializes to 0 82 if ( ( labels & Label_A ) == Label_None ) { ... } // // Or just if ( labels & Label_A ) { ... } 83 84 2. I/O and other operations which require integer variables and cannot be modified: 85 86 void write_to_db( unsigned int word ); 87 Labels_t labels; 88 write_to_db( labels ); // No longer compiles 89 90 This problem is solved by reinterpreting the bit fields as an integer, the user is responsible for using the right 91 type of integer: 92 93 write_to_db( *((Labels_t::bit_word_t*)(&labels)) ); 94 95 ========================================================================================================================================== 96 */ 97 98 /// @par Non-Templated Initialization. 99 /// Not all compilers support template member functions where the template 100 /// arguments are not deduced but explicitly specified. For these broken 101 /// compilers, a non-template make_bit_const() function is provided instead of 102 /// the template one. The only downside is that instead of compile-time checking 103 /// of the index argument, it does runtime checking. 104 #if defined(__SUNPRO_CC) || ( defined(__GNUC__) && (__GNUC__ < 3) ) 105 #define LOKI_BIT_FIELD_NONTEMPLATE_INIT 106 #endif 107 108 /// @par Forbidding Conversions. 109 /// This incomplete type prevents compilers from instantiating templates for 110 /// type conversions which should not happen. This incomplete type must be a 111 /// template: if the type is incomplete at the point of template definition, 112 /// the template is illegal (although the standard allows compilers to accept 113 /// or reject such code, §14.6/, so some compilers will not issue diagnostics 114 /// unless template is instantiated). The standard-compliant way is to defer 115 /// binding to the point of instantiation by making the incomplete type itself 116 /// a template. 117 template < typename > struct Forbidden_conversion; // This struct must not be defined! 118 119 /// Forward declaration of the field type. 120 template < 121 unsigned int unique_index, 122 typename word_t = unsigned long 123 > class SafeBitField; 124 125 //////////////////////////////////////////////////////////////////////////////// 126 /// \class SafeBitConst Bit constants. 127 /// This class defines a bit-field constant - a collection of unchanging bits 128 /// used to compare to bit-fields. Instances of this class are intended to act 129 /// as labels for bit-fields. 130 /// 131 /// \par Safety 132 /// - This class provides operations used for comparisons and conversions, but 133 /// no operations which may modify the value. 134 /// - As a templated class, it provides type-safety so bit values and constants 135 /// used for different reasons may not be unknowingly compared to each other. 136 /// - The unique_index template parameter insures the unique type of each bit 137 /// bit-field. It shares the unique_index with a similar SafeBitField. 138 /// - Its operations only allow comparisons to other bit-constants and 139 /// bit-fields of the same type. 140 //////////////////////////////////////////////////////////////////////////////// 141 142 template 143 < 144 unsigned int unique_index, 145 typename word_t = unsigned long 146 > 147 class SafeBitConst 148 { 149 public: 150 151 /// Type of the bit field is available if needed. 152 typedef word_t bit_word_t; 153 /// Corresponding field type. 154 typedef SafeBitField< unique_index, word_t > field_t; 155 /// Typedef is not allowed in friendship declaration. 156 friend class SafeBitField< unique_index, word_t >; 157 158 // Static factory constructor, creates a bit constant with one bit set. The position of the bit is given by the template parameter, 159 // bit 1 is the junior bit, i.e. make_bit_const<1>() returns 1. Bit index 0 is a special case and returns 0. 160 // This function should be used only to initialize the static bit constant objects. 161 // This function will not compile if the bit index is outside the vaild range. 162 // There is also a compile-time assert to make sure the size of the class is the same as the size of the underlaying integer type. 163 // This assert could go into the constructor, but aCC does not seem to understand sizeof(SafeBitConst) in the constructor. 164 // 165 #ifndef LOKI_BIT_FIELD_NONTEMPLATE_INIT make_bit_const()166 template < unsigned int i > static SafeBitConst make_bit_const() 167 { 168 LOKI_STATIC_CHECK( i <= ( 8 * sizeof(word_t) ), Index_is_beyond_size_of_data ); 169 LOKI_STATIC_CHECK( sizeof(SafeBitConst) == sizeof(word_t), Object_size_does_not_match_data_size ); 170 // Why check for ( i > 0 ) again inside the shift if the shift 171 // can never be evaluated for i == 0? Some compilers see shift by ( i - 1 ) 172 // and complain that for i == 0 the number is invalid, without 173 // checking that shift needs evaluating. 174 return SafeBitConst( ( i > 0 ) ? ( word_t(1) << ( ( i > 0 ) ? ( i - 1 ) : 0 ) ) : 0 ); 175 } 176 #else make_bit_const(unsigned int i)177 static SafeBitConst make_bit_const( unsigned int i ) 178 { 179 LOKI_STATIC_CHECK( sizeof(SafeBitConst) == sizeof(word_t), Object_size_does_not_match_data_size ); 180 assert( i <= ( 8 * sizeof(word_t) ) ); // Index is beyond size of data. 181 // Why check for ( i > 0 ) again inside the shift if the shift 182 // can never be evaluated for i == 0? Some compilers see shift by ( i - 1 ) 183 // and complain that for i == 0 the number is invalid, without 184 // checking that shift needs evaluating. 185 return SafeBitConst( ( i > 0 ) ? ( word_t(1) << ( ( i > 0 ) ? ( i - 1 ) : 0 ) ) : 0 ); 186 } 187 #endif 188 189 /// Default constructor allows client code to construct bit fields on the stack. SafeBitConst()190 SafeBitConst() : word( 0 ) {} 191 192 /// Copy constructor. SafeBitConst(const SafeBitConst & rhs)193 SafeBitConst( const SafeBitConst& rhs ) : word( rhs.word ) {} 194 195 /// Comparison operators which take a constant bit value. 196 bool operator == ( const SafeBitConst & rhs ) const { return word == rhs.word; } 197 bool operator != ( const SafeBitConst & rhs ) const { return word != rhs.word; } 198 bool operator < ( const SafeBitConst & rhs ) const { return word < rhs.word; } 199 bool operator > ( const SafeBitConst & rhs ) const { return word > rhs.word; } 200 bool operator <= ( const SafeBitConst & rhs ) const { return word <= rhs.word; } 201 bool operator >= ( const SafeBitConst & rhs ) const { return word >= rhs.word; } 202 203 /// Comparision operators for mutable bit fields. 204 bool operator == ( const field_t & rhs ) const { return word == rhs.word; } 205 bool operator != ( const field_t & rhs ) const { return word != rhs.word; } 206 bool operator < ( const field_t & rhs ) const { return word < rhs.word; } 207 bool operator > ( const field_t & rhs ) const { return word > rhs.word; } 208 bool operator <= ( const field_t & rhs ) const { return word <= rhs.word; } 209 bool operator >= ( const field_t & rhs ) const { return word >= rhs.word; } 210 211 /// Bitwise operations. Operation-assignment operators are not needed, 212 /// since bit constants cannot be changed after they are initialized. 213 const SafeBitConst operator | ( const SafeBitConst & rhs ) const { return SafeBitConst( word | rhs.word ); } 214 const SafeBitConst operator & ( const SafeBitConst & rhs ) const { return SafeBitConst( word & rhs.word ); } 215 const SafeBitConst operator ^ ( const SafeBitConst & rhs ) const { return SafeBitConst( word ^ rhs.word ); } 216 const SafeBitConst operator ~ ( void ) const { return SafeBitConst( ~word ); } 217 218 /// These bitwise operators return a bit-field instead of a bit-const. 219 field_t operator | ( const field_t & rhs ) const { return field_t( word | rhs.word ); } 220 field_t operator & ( const field_t & rhs ) const { return field_t( word & rhs.word ); } 221 field_t operator ^ ( const field_t & rhs ) const { return field_t( word ^ rhs.word ); } 222 223 /// The shift operators move bits inside the bit field. These are useful in 224 /// loops which act over bit fields and increment them. 225 const SafeBitConst operator << ( unsigned int s ) const { return SafeBitConst( word << s ); } 226 const SafeBitConst operator >> ( unsigned int s ) const { return SafeBitConst( word >> s ); } 227 228 /// Word size is also the maximum number of different bit fields for a given word type. size()229 static size_t size() { return ( 8 * sizeof( word_t ) ); } 230 231 private: 232 233 /// Copy-assignment operator is not implemented since it does not make sense 234 /// for a constant object. 235 SafeBitConst operator = ( const SafeBitConst & rhs ); 236 237 // Private constructor from an integer type. SafeBitConst(word_t init)238 explicit SafeBitConst( word_t init ) : word( init ) {} 239 240 /// This data stores a single bit value. It is declared const to enforce 241 // constness for all functions of this class. 242 const word_t word; 243 244 // Here comes the interesting stuff: all the operators designed to 245 // trap unintended conversions and make them not compile. 246 // Operators below handle code like this: 247 // SafeBitField<1> label1; 248 // SafeBitField<2> label2; 249 // if ( label1 & label2 ) { ... } 250 251 // These operators are private, and will not instantiate in any 252 // event because of the incomplete Forbidden_conversion struct. 253 template < typename T > SafeBitConst operator|( T ) const { Forbidden_conversion< T > wrong; return *this; } 254 template < typename T > SafeBitConst operator&( T ) const { Forbidden_conversion< T > wrong; return *this; } 255 template < typename T > SafeBitConst operator^( T ) const { Forbidden_conversion< T > wrong; return *this; } 256 template < typename T > SafeBitConst operator|=( T ) const { Forbidden_conversion< T > wrong; return *this; } 257 template < typename T > SafeBitConst operator&=( T ) const { Forbidden_conversion< T > wrong; return *this; } 258 template < typename T > SafeBitConst operator^=( T ) const { Forbidden_conversion< T > wrong; return *this; } 259 260 // And the same thing for comparisons: private and unusable. 261 // if ( label1 == label2 ) { ... } 262 template < typename T > bool operator==( const T ) const { Forbidden_conversion< T > wrong; return true; } 263 template < typename T > bool operator!=( const T ) const { Forbidden_conversion< T > wrong; return true; } 264 template < typename T > bool operator<( const T ) const { Forbidden_conversion< T > wrong; return true; } 265 template < typename T > bool operator>( const T ) const { Forbidden_conversion< T > wrong; return true; } 266 template < typename T > bool operator<=( const T ) const { Forbidden_conversion< T > wrong; return true; } 267 template < typename T > bool operator>=( const T ) const { Forbidden_conversion< T > wrong; return true; } 268 }; 269 270 271 //////////////////////////////////////////////////////////////////////////////// 272 /// \class SafeBitConst Bit constants. 273 /// This class defines a bit-field constant - a collection of unchanging bits 274 /// used to compare to bit-fields. Instances of this class are intended to 275 /// store bit values. 276 /// 277 /// \par Safety 278 /// - This class provides operations used for comparisons and conversions, and 279 /// also operations which may safely modify the value. 280 /// - As a templated class, it provides type-safety so bit values and constants 281 /// used for different reasons may not be unknowingly compared to each other. 282 /// - The unique_index template parameter insures the unique type of each bit 283 /// bit-field. It shares the unique_index with a similar SafeBitConst. 284 /// - Its operations only allow comparisons to other bit-constants and 285 /// bit-fields of the same type. 286 //////////////////////////////////////////////////////////////////////////////// 287 288 template 289 < 290 unsigned int unique_index, 291 typename word_t 292 > 293 class SafeBitField 294 { 295 public: 296 297 /// Type of the bit field is available if needed. 298 typedef word_t bit_word_t; 299 /// Corresponding field type. 300 typedef SafeBitConst< unique_index, word_t > const_t; 301 /// Typedef is not allowed in friendship declaration. 302 friend class SafeBitConst<unique_index, word_t>; 303 304 /// Default constructor allows client code to construct bit fields on the stack. SafeBitField()305 SafeBitField() : word( 0 ) {} 306 307 /// Copy constructor and assignment operators. SafeBitField(const SafeBitField & rhs)308 SafeBitField( const SafeBitField & rhs ) : word( rhs.word ) {} 309 SafeBitField & operator = ( const SafeBitField & rhs ) { word = rhs.word; return *this; } 310 311 /// Copy constructor and assignment operators from constant bit fields. SafeBitField(const const_t & rhs)312 SafeBitField( const const_t & rhs ) : word( rhs.word ) {} 313 SafeBitField & operator = ( const const_t & rhs ) { word = rhs.word; return *this; } 314 315 /// These comparison operators act on bit-fields of the same type. 316 bool operator == ( const SafeBitField & rhs ) const { return word == rhs.word; } 317 bool operator != ( const SafeBitField & rhs ) const { return word != rhs.word; } 318 bool operator < ( const SafeBitField & rhs ) const { return word < rhs.word; } 319 bool operator > ( const SafeBitField & rhs ) const { return word > rhs.word; } 320 bool operator <= ( const SafeBitField & rhs ) const { return word <= rhs.word; } 321 bool operator >= ( const SafeBitField & rhs ) const { return word >= rhs.word; } 322 323 /// These comparison operators act on bit-constants of a similar type. 324 bool operator == ( const const_t & rhs ) const { return word == rhs.word; } 325 bool operator != ( const const_t & rhs ) const { return word != rhs.word; } 326 bool operator < ( const const_t & rhs ) const { return word < rhs.word; } 327 bool operator > ( const const_t & rhs ) const { return word > rhs.word; } 328 bool operator <= ( const const_t & rhs ) const { return word <= rhs.word; } 329 bool operator >= ( const const_t & rhs ) const { return word >= rhs.word; } 330 331 /// Bitwise operations that use bit-fields. 332 SafeBitField operator | ( const SafeBitField & rhs ) const { return SafeBitField( word | rhs.word ); } 333 SafeBitField operator & ( const SafeBitField & rhs ) const { return SafeBitField( word & rhs.word ); } 334 SafeBitField operator ^ ( const SafeBitField & rhs ) const { return SafeBitField( word ^ rhs.word ); } 335 SafeBitField operator ~ ( void ) const { return SafeBitField( ~word ); } 336 SafeBitField operator |= ( const SafeBitField & rhs ) { word |= rhs.word; return SafeBitField( *this ); } 337 SafeBitField operator &= ( const SafeBitField & rhs ) { word &= rhs.word; return SafeBitField( *this ); } 338 SafeBitField operator ^= ( const SafeBitField & rhs ) { word ^= rhs.word; return SafeBitField( *this ); } 339 340 /// Bitwise operators that use bit-constants. 341 SafeBitField operator | ( const_t rhs ) const { return SafeBitField( word | rhs.word ); } 342 SafeBitField operator & ( const_t rhs ) const { return SafeBitField( word & rhs.word ); } 343 SafeBitField operator ^ ( const_t rhs ) const { return SafeBitField( word ^ rhs.word ); } 344 SafeBitField operator |= ( const_t rhs ) { word |= rhs.word; return SafeBitField( *this ); } 345 SafeBitField operator &= ( const_t rhs ) { word &= rhs.word; return SafeBitField( *this ); } 346 SafeBitField operator ^= ( const_t rhs ) { word ^= rhs.word; return SafeBitField( *this ); } 347 348 // Conversion to bool. 349 // This is a major source of headaches, but it's required to support code like this: 350 // const static SafeBitConst<1> Label_value = SafeBitConst<1>::make_bit_const<1>(); 351 // SafeBitField<1> label; 352 // if ( label & Label_value ) { ... } // Nice... 353 // 354 // The downside is that this allows all sorts of nasty conversions. Without additional precautions, bit fields of different types 355 // can be converted to bool and then compared or operated on: 356 // SafeBitField<1> label1; 357 // SafeBitField<2> label2; 358 // if ( label1 == label2 ) { ... } // Yuck! 359 // if ( label1 & label2 ) { ... } // Blech! 360 // 361 // It is somewhat safer to convert to a pointer, at least pointers to different types cannot be readilly compared, and there are no 362 // bitwise operations on pointers, but the conversion from word_t to a pointer can have run-time cost if they are of different size. 363 // 364 operator const bool() const { return ( 0 != word ); } 365 366 // Shift operators shift bits inside the bit field. Does not make 367 // sense, most of the time, except perhaps to loop over labels and 368 // increment them. 369 SafeBitField operator << ( unsigned int s ) { return SafeBitField( word << s ); } 370 SafeBitField operator >> ( unsigned int s ) { return SafeBitField( word >> s ); } 371 SafeBitField operator <<= ( unsigned int s ) { word <<= s; return *this; } 372 SafeBitField operator >>= ( unsigned int s ) { word >>= s; return *this; } 373 374 // Word size is also the maximum number of different bit fields for 375 // a given word type. size(void)376 static size_t size( void ) { return ( 8 * sizeof( word_t ) ); } 377 378 private: 379 380 /// Private constructor from an integer type. Don't put too much stock into 381 /// explicit declaration, it's better than nothing but does not solve all 382 /// problems with undesired conversions because SafeBitField coverts to bool. SafeBitField(word_t init)383 explicit SafeBitField( word_t init ) : word( init ) {} 384 385 /// This stores the bits. 386 word_t word; 387 388 // Here comes the interesting stuff: all the operators designed to 389 // trap unintended conversions and make them not compile. 390 // Operators below handle code like this: 391 // SafeBitField<1> label1; 392 // SafeBitField<2> label2; 393 // if ( label1 & label2 ) { ... } 394 395 // These operators are private, and will not instantiate in any 396 // event because of the incomplete Forbidden_conversion struct. 397 template < typename T > SafeBitField operator | ( T ) const { Forbidden_conversion< T > wrong; return *this; } 398 template < typename T > SafeBitField operator & ( T ) const { Forbidden_conversion< T > wrong; return *this; } 399 template < typename T > SafeBitField operator ^ ( T ) const { Forbidden_conversion< T > wrong; return *this; } 400 template < typename T > SafeBitField operator |= ( T ) const { Forbidden_conversion< T > wrong; return *this; } 401 template < typename T > SafeBitField operator &= ( T ) const { Forbidden_conversion< T > wrong; return *this; } 402 template < typename T > SafeBitField operator ^= ( T ) const { Forbidden_conversion< T > wrong; return *this; } 403 404 // And the same thing for comparisons: 405 // if ( label1 == label2 ) { ... } 406 template < typename T > bool operator == ( const T ) const { Forbidden_conversion< T > wrong; return true; } 407 template < typename T > bool operator != ( const T ) const { Forbidden_conversion< T > wrong; return true; } 408 template < typename T > bool operator < ( const T ) const { Forbidden_conversion< T > wrong; return true; } 409 template < typename T > bool operator > ( const T ) const { Forbidden_conversion< T > wrong; return true; } 410 template < typename T > bool operator <= ( const T ) const { Forbidden_conversion< T > wrong; return true; } 411 template < typename T > bool operator >= ( const T ) const { Forbidden_conversion< T > wrong; return true; } 412 }; 413 414 // The above template member operators catch errors when the first 415 // argument to a binary operator is a label, but they don't work when 416 // the first argument is an integer and the second one is a label: the 417 // label converts to bool and the operator is performed on two integers. 418 // These operators catch errors like this: 419 // SafeBitField<1> label1; 420 // SafeBitField<2> label2; 421 // if ( !label1 & label2 ) { ... } 422 // where the first label is converted to bool (these errors cannot be 423 // caught by member operators of SafeBitField class because the first 424 // argument is not SafeBitField but bool. 425 // 426 // If used, these operators will not instantiate because of the 427 // incomplete Forbidden_conversion struct. 428 429 template < unsigned int unique_index, typename word_t > 430 inline SafeBitField< unique_index, word_t > operator & ( bool, SafeBitField< unique_index, word_t > rhs ) 431 { 432 Forbidden_conversion<word_t> wrong; 433 return rhs; 434 } 435 436 template < unsigned int unique_index, typename word_t > 437 inline SafeBitField< unique_index, word_t > operator | ( bool, SafeBitField< unique_index, word_t > rhs ) 438 { 439 Forbidden_conversion< word_t > wrong; 440 return rhs; 441 } 442 443 template < unsigned int unique_index, typename word_t > 444 inline SafeBitField< unique_index, word_t > operator ^ ( bool, SafeBitField< unique_index, word_t > rhs ) 445 { 446 Forbidden_conversion< word_t > wrong; 447 return rhs; 448 } 449 450 template < unsigned int unique_index, typename word_t > 451 inline SafeBitField< unique_index, word_t > operator == ( bool, SafeBitField< unique_index, word_t > rhs ) 452 { 453 Forbidden_conversion< word_t > wrong; 454 return rhs; 455 } 456 457 template < unsigned int unique_index, typename word_t > 458 inline SafeBitField< unique_index, word_t > operator != ( bool, SafeBitField< unique_index, word_t > rhs ) 459 { 460 Forbidden_conversion< word_t > wrong; 461 return rhs; 462 } 463 464 // Finally, few macros. All macros are conditionally defined to use the SafeBitField classes if LOKI_SAFE_BIT_FIELD is defined. Otherwise, 465 // the macros fall back on the use of typedefs and integer constants. This provides no addititonal safety but allows the code to support the 466 // mixture of compilers which are broken to different degrees. 467 #define LOKI_SAFE_BIT_FIELD 468 469 // The first macro helps to declare new bit field types: 470 // LOKI_BIT_FIELD( ulong ) field_t; 471 // This creates a typedef field_t for SafeBitField<unique_index, ulong> where index is the current line number. Since line numbers __LINE__ are counted 472 // separately for all header files, this ends up being the same type in all files using the header which defines field_t. 473 #ifdef LOKI_SAFE_BIT_FIELD 474 #define LOKI_BIT_FIELD( word_t ) typedef SafeBitField<__LINE__, word_t> 475 #else 476 #define LOKI_BIT_FIELD( word_t ) typedef word_t 477 #endif // LOKI_SAFE_BIT_FIELD 478 479 // The second macro helps to declare static bit constants: 480 // LOKI_BIT_CONST( field_t, Label_1, 1 ); 481 // creates new bit field object named Label_1 of type field_t which represents the field with the 1st (junior) bit set. 482 #ifdef LOKI_SAFE_BIT_FIELD 483 #ifndef LOKI_BIT_FIELD_NONTEMPLATE_INIT 484 #define LOKI_BIT_CONST( field_t, label, bit_index ) \ 485 static const field_t::const_t label = field_t::const_t::make_bit_const<bit_index>() 486 #else 487 #define LOKI_BIT_CONST( field_t, label, bit_index ) \ 488 static const field_t::const_t label = field_t::const_t::make_bit_const( bit_index ) 489 #endif // LOKI_BIT_FIELD_NONTEMPLATE_INIT 490 #else make_bit_const(size_t i)491 inline size_t make_bit_const( size_t i ) { return ( i > 0 ) ? ( size_t(1) << ( ( i > 0 ) ? ( i - 1 ) : 0 ) ) : 0; } 492 #define LOKI_BIT_CONST( field_t, label, bit_index ) static const field_t label = make_bit_const( bit_index ) 493 #endif // LOKI_SAFE_BIT_FIELD 494 495 // The third macro helps to declare complex bit constants which are combination of several bits: 496 // LOKI_BIT_CONSTS( field_t, Label12 ) = Label_1 | Label_2; 497 #ifdef LOKI_SAFE_BIT_FIELD 498 #define LOKI_BIT_CONSTS( field_t, label ) static const field_t::const_t label 499 #else 500 #define LOKI_BIT_CONSTS( field_t, label ) static const field_t label 501 #endif // LOKI_SAFE_BIT_FIELD 502 503 // The fourth macro helps to declare the maximum number of bit constants for a given type: 504 // static const size_t count = LOKI_BIT_FIELD_COUNT( field_t ); 505 // declared a variable "count" initialized to field_t::size() 506 #ifdef LOKI_SAFE_BIT_FIELD 507 #define LOKI_BIT_FIELD_COUNT( field_t ) field_t::size() 508 #else 509 #define LOKI_BIT_FIELD_COUNT( field_t ) ( 8 * sizeof(field_t) ) 510 #endif // LOKI_SAFE_BIT_FIELD 511 512 } // namespace Loki 513 514 #endif // LOKI_INCLUDED_SAFE_BIT_FIELDS_H 515