Skip to content

Instantly share code, notes, and snippets.

@aisouard
Last active May 5, 2021 09:53
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save aisouard/4ffc0bd2b992cf65e432e86d8471b83c to your computer and use it in GitHub Desktop.
Save aisouard/4ffc0bd2b992cf65e432e86d8471b83c to your computer and use it in GitHub Desktop.
Reading an EBML variable-length integer
/**
* Read an EBML tag header or length and return their respective values into
* single numbers.
*
* @example
* var tagHeader = new Uint8Array([0x1A, 0x45, 0xDF, 0xA3, 0x01, 0x00, 0x00,
* 0x00, 0x00, 0x00, 0x00, 0x1F]);
* var tagId = readVariableInt(tagHeader, 4, 0);
* console.log('The current tag ID is: ', tagId.value, ', skipping ', tagId.size, ' bytes.');
* // The current tag ID is: 172351395, skipping 4 bytes.
*
* var tagLength = readVariableInt(tagHeader, 8, tagId.size);
* console.log('The tag\'s length is: ', tagLength.value, ', skipping ', tagLength.size, ' bytes.');
* // The tag's length is 31, skipping 8 bytes.
*
* @param {Uint8Array} bytes
* @param {number} maxSize
* @param {number} offset
* @returns {{size: number, value: number}}
*/
function readVariableInt(bytes, maxSize, offset) {
var index = (offset && offset > 0) ? offset : 0;
var count = 1;
var length = bytes[index];
var bytesRead = 1;
var lengthMask = 0x80;
if (!length) {
return null;
}
while (bytesRead <= maxSize && !(length & lengthMask)) {
bytesRead++;
lengthMask >>= 1;
}
if (bytesRead > maxSize) {
return null;
}
length &= ~lengthMask;
while (count++ < bytesRead) {
length = (length << 8) | bytes[++index];
}
return {
size: bytesRead,
value: length
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment