// ----------------------------------------------------------------------------
// BitField is a help template for encoding and decode bitfield with
// unsigned content.
-template<class T, int shift, int size>
-class BitField {
+
+template<class T, int shift, int size, class U>
+class BitFieldBase {
public:
- // A uint32_t mask of bit field. To use all bits of a uint32 in a
- // bitfield without compiler warnings we have to compute 2^32 without
- // using a shift count of 32.
- static const uint32_t kMask = ((1U << shift) << size) - (1U << shift);
- static const uint32_t kShift = shift;
- static const uint32_t kSize = size;
+ // A type U mask of bit field. To use all bits of a type U of x bits
+ // in a bitfield without compiler warnings we have to compute 2^x
+ // without using a shift count of x in the computation.
+ static const U kOne = static_cast<U>(1U);
+ static const U kMask = ((kOne << shift) << size) - (kOne << shift);
+ static const U kShift = shift;
+ static const U kSize = size;
// Value for the field with all bits set.
static const T kMax = static_cast<T>((1U << size) - 1);
// Tells whether the provided value fits into the bit field.
static bool is_valid(T value) {
- return (static_cast<uint32_t>(value) & ~static_cast<uint32_t>(kMax)) == 0;
+ return (static_cast<U>(value) & ~static_cast<U>(kMax)) == 0;
}
- // Returns a uint32_t with the bit field value encoded.
- static uint32_t encode(T value) {
+ // Returns a type U with the bit field value encoded.
+ static U encode(T value) {
ASSERT(is_valid(value));
- return static_cast<uint32_t>(value) << shift;
+ return static_cast<U>(value) << shift;
}
- // Returns a uint32_t with the bit field value updated.
- static uint32_t update(uint32_t previous, T value) {
+ // Returns a type U with the bit field value updated.
+ static U update(U previous, T value) {
return (previous & ~kMask) | encode(value);
}
// Extracts the bit field from the value.
- static T decode(uint32_t value) {
+ static T decode(U value) {
return static_cast<T>((value & kMask) >> shift);
}
};
+template<class T, int shift, int size>
+class BitField : public BitFieldBase<T, shift, size, uint32_t> { };
+
+
+template<class T, int shift, int size>
+class BitField64 : public BitFieldBase<T, shift, size, uint64_t> { };
+
+
// ----------------------------------------------------------------------------
// Hash function.
CHECK_EQ(1e-106, StringToDouble(&uc, ".000001e-100", NO_FLAGS));
}
-class OneBit1: public BitField<uint32_t, 0, 1> {};
-class OneBit2: public BitField<uint32_t, 7, 1> {};
-class EightBit1: public BitField<uint32_t, 0, 8> {};
-class EightBit2: public BitField<uint32_t, 13, 8> {};
TEST(BitField) {
uint32_t x;
// One bit bit field can hold values 0 and 1.
+ class OneBit1: public BitField<uint32_t, 0, 1> {};
+ class OneBit2: public BitField<uint32_t, 7, 1> {};
CHECK(!OneBit1::is_valid(static_cast<uint32_t>(-1)));
CHECK(!OneBit2::is_valid(static_cast<uint32_t>(-1)));
for (int i = 0; i < 2; i++) {
CHECK(!OneBit2::is_valid(2));
// Eight bit bit field can hold values from 0 tp 255.
+ class EightBit1: public BitField<uint32_t, 0, 8> {};
+ class EightBit2: public BitField<uint32_t, 13, 8> {};
CHECK(!EightBit1::is_valid(static_cast<uint32_t>(-1)));
CHECK(!EightBit2::is_valid(static_cast<uint32_t>(-1)));
for (int i = 0; i < 256; i++) {
CHECK(!EightBit1::is_valid(256));
CHECK(!EightBit2::is_valid(256));
}
+
+
+TEST(BitField64) {
+ uint64_t x;
+
+ // Test most significant bits.
+ class UpperBits: public BitField64<int, 61, 3> {};
+ x = V8_2PART_UINT64_C(0xE0000000, 00000000);
+ CHECK(x == UpperBits::encode(7));
+ CHECK_EQ(7, UpperBits::decode(x));
+
+ // Test the 32/64-bit boundary bits.
+ class MiddleBits: public BitField64<int, 31, 2> {};
+ x = V8_2PART_UINT64_C(0x00000001, 80000000);
+ CHECK(x == MiddleBits::encode(3));
+ CHECK_EQ(3, MiddleBits::decode(x));
+}