patternjavascriptMajor
Pack and unpack bytes to strings
Viewed 0 times
packbytesunpackandstrings
Problem
I need to write a function that "packs" an array of bytes (integers between 0 and 255) into a string. I also need to be able to perform the reverse operation, to get my byte array from the string that it was packed into. This needs to be done as fast as possible. Seeing as JavaScript has 16-bit strings, I packed two bytes per character. Here is my code and tests:
And the output to that is:
I have a few things I'd like feedback on:
function pack(bytes) {
var str = "";
for(var i = 0; i >> 8);
bytes.push(char & 0xFF);
}
return bytes;
}
var tests = [
[],
[126, 0],
[0, 65],
[12, 34, 56],
[0, 50, 100, 150, 200, 250]
];
console.log("starting tests");
tests.forEach(function(v) {
var p = pack(v);
console.log(v, p, unpack(p));
});And the output to that is:
starting tests
[] "" []
[126, 0] "縀" [126, 0]
[0, 65] "A" [0, 65]
[12, 34, 56] "ఢ㠀" [12, 34, 56, 0]
[0, 50, 100, 150, 200, 250] "2撖죺" [0, 50, 100, 150, 200, 250]I have a few things I'd like feedback on:
- This was the first time I used bitwise operators. Is this how it should be done?
- Are there any speed improvements that could be made?
- Can you guys think of any way to discard that last 0 byte when encoding then decoding an array with an odd number of bytes? (see test #4)
Solution
function pack(bytes) {
var str = "";
// You could make it faster by reading bytes.length once.
for(var i = 0; i >> 8, char & 0xff);
bytes.push(char >>> 8);
bytes.push(char & 0xFF);
}
return bytes;
}so to put it all together
function pack(bytes) {
var chars = [];
for(var i = 0, n = bytes.length; i >> 8, char & 0xFF);
}
return bytes;
}Code Snippets
function pack(bytes) {
var str = "";
// You could make it faster by reading bytes.length once.
for(var i = 0; i < bytes.length; i += 2) {
// If you're using signed bytes, you probably need to mask here.
var char = bytes[i] << 8;
// (undefined | 0) === 0 so you can save a test here by doing
// var char = (bytes[i] << 8) | (bytes[i + 1] & 0xff);
if (bytes[i + 1])
char |= bytes[i + 1];
// Instead of using string += you could push char onto an array
// and take advantage of the fact that String.fromCharCode can
// take any number of arguments to do
// String.fromCharCode.apply(null, chars);
str += String.fromCharCode(char);
}
return str;
}
function unpack(str) {
var bytes = [];
for(var i = 0; i < str.length; i++) {
var char = str.charCodeAt(i);
// You can combine both these calls into one,
// bytes.push(char >>> 8, char & 0xff);
bytes.push(char >>> 8);
bytes.push(char & 0xFF);
}
return bytes;
}function pack(bytes) {
var chars = [];
for(var i = 0, n = bytes.length; i < n;) {
chars.push(((bytes[i++] & 0xff) << 8) | (bytes[i++] & 0xff));
}
return String.fromCharCode.apply(null, chars);
}
function unpack(str) {
var bytes = [];
for(var i = 0, n = str.length; i < n; i++) {
var char = str.charCodeAt(i);
bytes.push(char >>> 8, char & 0xFF);
}
return bytes;
}Context
StackExchange Code Review Q#3569, answer score: 20
Revisions (0)
No revisions yet.