blob: 7a91bb8bfdbb307e41d472f49f1536404a9580b5 [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/// BitRange specifies the [start] and [end] position values for [Bitfield64].
class BitRange {
/// Least significant bit to be accessed.
final int start;
/// Most significant bit to be accessed.
final int end;
/// Range-sized bitmask starting at bit 0.
final int maskAt0;
/// Creates and sets the BitRange.
///
/// Throws if [start] < 0, [end] > 63, or [start] > [end].
///
/// The mask computation relies on the fact that 1 << 64 == 0 in Dart, and
/// 0 - 1 == 0xffffffffffffffff in 2's complement arithmetic.
BitRange(this.start, this.end) : maskAt0 = ((1 << (end - start + 1)) - 1) {
if (end < start) {
throw ArgumentError('End must be >= start.');
}
if (start < 0) {
throw ArgumentError("Starting bit can't be less than zero.");
}
if (end > 63) {
throw ArgumentError('There are only 64 bits.');
}
}
}
/// Bitfield64 stores a 64-bit value, and reads and writes bitfields on it.
class Bitfield64 {
/// The full 64-bit value. It acts like a little endian number.
int value = 0;
/// Creates a bitfield initialized to a value.
Bitfield64([this.value = 0]);
/// Returns value of bits.
///
/// For example, <value of next-to-smallest byte> = read(BitRange(8, 15)).
// When reading, shift first and then mask; masking and then
// shifting when bit 63 == 1 makes the return value negative.
int read(BitRange range) => (value >> range.start) & range.maskAt0;
/// Writes the lowest bits of [value] to the indicated range.
void write(BitRange range, int value) {
this.value &= ~(range.maskAt0 << range.start);
this.value |= (value & range.maskAt0) << range.start;
}
}