I am trying to write bits to a Uint8Array buffer in JavaScript. I want to do this (pseudocode):
// write(buffer, offset, value, size)
write(buffer, 0, 3, 2) // 3 == 11 in bits
write(buffer, 2, 0, 2) // 0 == 0 in bits
I would then expect the following to be true:
buffer[0].toString(2) === '1100'
However, I am getting:
buffer[0].toString(2) === '11'
This to me means that it's not properly handling the zero case. (I added a zero which I wanted to take up 2 bits of space).
The code I have to write bits to the buffer is this:
const write = function(buffer, offset, value, num) {
let i = 0
console.log('value:', value.toString(2))
while (i < num) {
const remaining = num - i
const block_offset = offset & 7
const byteOffset = offset >> 3
const finished = Math.min(remaining, 8 - block_offset)
const first = 0xFF << finished
const mask = ~first
const writeBits = value & mask
value >>= finished
const second = mask << block_offset
const destMask = ~(second)
const byte = buffer[byteOffset]
buffer[byteOffset] = (byte & destMask) | (writeBits << block_offset)
console.log(`---
offset: ${offset.toString(2)}
num: ${num.toString(2)}
remaining: ${remaining.toString(2)}
block_offset: ${block_offset.toString(2)}
byteOffset: ${byteOffset.toString(2)}
finished: ${finished.toString(2)}
first: ${first.toString(2)}
mask: ${mask.toString(2)}
writeBits: ${writeBits.toString(2)}
value: ${value.toString(2)}
second: ${second.toString(2)}
destMask: ${destMask.toString(2)}
byte: ${byte.toString(2)}
buffer[byteOffset]: ${buffer[byteOffset].toString(2)}`)
offset += finished
i += finished
}
}
I am calling it like this:
let buffer = new Uint8Array(4096)
write(buffer, 0, 3, 2)
write(buffer, 2, 0, 2)
What it is logging is this:
value: 11
---
offset: 0
num: 10
remaining: 10
block_offset: 0
byteOffset: 0
finished: 10
first: 1111111100
mask: -1111111101
writeBits: 11
value: 0
second: -1111111101
destMask: 1111111100
byte: 0
buffer[byteOffset]: 11
value: 0
---
offset: 10
num: 10
remaining: 10
block_offset: 10
byteOffset: 0
finished: 10
first: 1111111100
mask: -1111111101
writeBits: 0
value: 0
second: -111111110100
destMask: 111111110011
byte: 11
buffer[byteOffset]: 11
Some things that seem off to me:
- Why is there a
-negative
value? I get that I negated the bits, but I would simply expecttoString(2)
to show the flipped bits. What did I do wrong here? - The first iteration seems correct to me, other than the negation stuff.
- The
first
seems wrong in the second iteration. Shouldn't it be1111110000
instead of1111111100
?
I don't really understand what second
and destMask
are doing yet, still need to spend time on that. But do you have any idea how to get this working? That is, so it writes 1100
to the first byte after these two calls?