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