I\'m working on a project that includes WebSockets, and data between the server (Node.js) and the client (Chrome) is sent using a custom (very simple) format for data exchan
We can get value we need by getting appropriate 16-bits integer and then bitshift it.
It is clear, that to get i-th value we should get 16-bits integer with offset in bytes that fits (bits * (i + 1) - 16)/8 <= offset <= (bits * i)/8.
Lets take M=bits*i/8, so we have M + bits/8 - 2<= offset <= M. Then we get minimal offset as ceil(M + bits/8 - 2) and calculate position of i-th value in the 16-bit integer by offsets. I have just wrote the following function
function getDataFromStream(buffer, bitsPerValue, endianness) {
var valuesCount = Math.floor(buffer.length * 8 / bitsPerValue);
var ret = new Buffer(valuesCount);
if (valuesCount > 0) {
for (var i = 0; i < valuesCount; i++) {
var offsetMin = Math.ceil(bitsPerValue * i / 8. + bitsPerValue / 8. - 2);
if (offsetMin < 0) {
offsetMin = 0;
}
if(endianness == 'BE')
var wordWithValue = buffer.readUInt16BE(offsetMin, true);
else
var wordWithValue = buffer.readUInt16LE(offsetMin, true);
var offsetInWord = bitsPerValue * i - offsetMin * 8;
var leftInWord = 16 - bitsPerValue - offsetInWord;
// then get value in the word by shifting and then remove other bits by "%"
ret[i] = (wordWithValue >> (endianness == 'BE' ? leftInWord : offsetInWord )) % Math.pow(2, bitsPerValue);
}
}
return ret;
}
And the following example to read 8 5-bit values off the Buffer with 5 bytes length.
// buffer with 5 bytes
var xx = new Buffer(5);
xx[0] = 255;
xx[1] = 255;
xx[2] = 255;
xx[3] = 255;
xx[4] = 250;
// get data, 5bits per value.
var yy = getDataFromStream(xx, 5, 'BE');
console.log('got buffer with length='+ yy.length);
for(i = 0; i < yy.length; i++){
console.log(i+'-'+yy[i]);
}
When I launch node test.js I got
got buffer with length=8
0-31
1-31
2-31
3-31
4-31
5-31
6-31
7-26