Function readPackedTwosComplement [src]
Read the value of x from a packed memory buffer.
Asserts that buffer is large enough to contain a value of bit-size bit_count
at offset bit_offset.
This is equivalent to loading the value of an integer with bit_count bits as
if it were a field in packed memory at the provided bit offset.
Prototype
pub fn readPackedTwosComplement( x: *Mutable, buffer: []const u8, bit_offset: usize, bit_count: usize, endian: Endian, signedness: Signedness, ) void
Parameters
x: *Mutable
buffer: []const u8
bit_offset: usize
bit_count: usize
endian: Endian
signedness: Signedness
Source
pub fn readPackedTwosComplement(
x: *Mutable,
buffer: []const u8,
bit_offset: usize,
bit_count: usize,
endian: Endian,
signedness: Signedness,
) void {
if (bit_count == 0) {
x.limbs[0] = 0;
x.len = 1;
x.positive = true;
return;
}
// Check whether the input is negative
var positive = true;
if (signedness == .signed) {
const total_bits = bit_offset + bit_count;
const last_byte = switch (endian) {
.little => ((total_bits + 7) / 8) - 1,
.big => buffer.len - ((total_bits + 7) / 8),
};
const sign_bit = @as(u8, 1) << @as(u3, @intCast((total_bits - 1) % 8));
positive = ((buffer[last_byte] & sign_bit) == 0);
}
// Copy all complete limbs
var carry: u1 = 1;
var limb_index: usize = 0;
var bit_index: usize = 0;
while (limb_index < bit_count / @bitSizeOf(Limb)) : (limb_index += 1) {
// Read one Limb of bits
var limb = mem.readPackedInt(Limb, buffer, bit_index + bit_offset, endian);
bit_index += @bitSizeOf(Limb);
// 2's complement (bitwise not, then add carry bit)
if (!positive) {
const ov = @addWithOverflow(~limb, carry);
limb = ov[0];
carry = ov[1];
}
x.limbs[limb_index] = limb;
}
// Copy the remaining bits
if (bit_count != bit_index) {
// Read all remaining bits
var limb = switch (signedness) {
.unsigned => mem.readVarPackedInt(Limb, buffer, bit_index + bit_offset, bit_count - bit_index, endian, .unsigned),
.signed => b: {
const SLimb = std.meta.Int(.signed, @bitSizeOf(Limb));
const limb = mem.readVarPackedInt(SLimb, buffer, bit_index + bit_offset, bit_count - bit_index, endian, .signed);
break :b @as(Limb, @bitCast(limb));
},
};
// 2's complement (bitwise not, then add carry bit)
if (!positive) {
const ov = @addWithOverflow(~limb, carry);
assert(ov[1] == 0);
limb = ov[0];
}
x.limbs[limb_index] = limb;
limb_index += 1;
}
x.positive = positive;
x.len = limb_index;
x.normalize(x.len);
}