kontainer-js
Version:
A media file format generator/parser that exposes a React-like API.
234 lines (189 loc) • 6.75 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
var _slicedToArray2 = require('babel-runtime/helpers/slicedToArray');
var _slicedToArray3 = _interopRequireDefault(_slicedToArray2);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function writeByte(byte, buffer, offset) {
var mask = arguments.length <= 3 || arguments[3] === undefined ? 0xFF : arguments[3];
var or = arguments[4];
if (buffer) {
if (or) {
buffer[offset] |= byte & mask;
} else {
buffer[offset] = byte & mask;
}
}
}
function writeCharacter(charCode, buffer, offset) {
var base = offset;
if (charCode < 0x80) {
// 1 byte
writeByte(charCode, buffer, base++);
} else if (charCode >= 0x80 && charCode < 0x800) {
// 2 bytes
writeByte(0xC0 | charCode >> 6 & 0x1F, buffer, base++);
writeByte(0x80 | charCode >> 0 & 0x3F, buffer, base++);
} else if (charCode >= 0x800 && charCode < 0x10000) {
// 3 bytes
writeByte(0xE0 | charCode >> 12 & 0x0F, buffer, base++);
writeByte(0x80 | charCode >> 6 & 0x3F, buffer, base++);
writeByte(0x80 | charCode >> 0 & 0x3F, buffer, base++);
} else if (charCode >= 0x10000 && charCode < 0x200000) {
// 4 bytes
writeByte(0xF0 | charCode >> 18 & 0x07, buffer, base++);
writeByte(0x80 | charCode >> 12 & 0x3F, buffer, base++);
writeByte(0x80 | charCode >> 6 & 0x3F, buffer, base++);
writeByte(0x80 | charCode >> 0 & 0x3F, buffer, base++);
} else if (charCode >= 0x200000 && charCode < 0x4000000) {
// 5 bytes
writeByte(0xF8 | charCode >> 24 & 0x03, buffer, base++);
writeByte(0x80 | charCode >> 18 & 0x3F, buffer, base++);
writeByte(0x80 | charCode >> 12 & 0x3F, buffer, base++);
writeByte(0x80 | charCode >> 6 & 0x3F, buffer, base++);
writeByte(0x80 | charCode >> 0 & 0x3F, buffer, base++);
} else if (charCode >= 0x4000000 && charCode < 0x80000000) {
// 6 bytes
writeByte(0xFC | charCode >> 30 & 0x01, buffer, base++);
writeByte(0x80 | charCode >> 24 & 0x3F, buffer, base++);
writeByte(0x80 | charCode >> 18 & 0x3F, buffer, base++);
writeByte(0x80 | charCode >> 12 & 0x3F, buffer, base++);
writeByte(0x80 | charCode >> 6 & 0x3F, buffer, base++);
writeByte(0x80 | charCode >> 0 & 0x3F, buffer, base++);
} else {
console.error('Writer.writeCharacter: Invalid char code - ' + charCode);
}
return base - offset;
}
function writeString(str, buffer, offset, length) {
var lowerLimit = offset + (length || 0);
var upperLimit = offset + (length || Infinity);
var nullTerminationNeeded = length === void 0;
var base = offset;
for (var i = 0, il = str.length; i < il; i++) {
base += writeCharacter(str.charCodeAt(i), buffer, base);
if (base > upperLimit) {
base = upperLimit;
break;
}
}
// padding
while (base < lowerLimit) {
writeByte(0, buffer, base++);
}
if (nullTerminationNeeded) {
writeByte(0, buffer, base++);
}
return base - offset;
}
function writeNumber(num, buffer, offset) {
var length = arguments.length <= 3 || arguments[3] === undefined ? 4 : arguments[3];
var left = num / 4294967296;
var right = num % 4294967296;
var base = offset,
byte = void 0,
i = void 0;
if (num >= 0 && length > 4) {
for (i = length - 4 - 1; i >= 0; i--) {
byte = left >> 8 * i & 0xFF;
writeByte(byte, buffer, base++);
}
length = 4;
}
for (i = length - 1; i >= 0; i--) {
byte = right >> 8 * i & 0xFF;
writeByte(byte, buffer, base++);
}
return base - offset;
}
function makeBitMask(start, len) {
var mask = 0;
for (var i = start + len - 1; i >= start; i--) {
mask |= 1 << i;
}
return mask;
}
function writeBits(num, buffer, byteOffset, bitOffset, totalBitsToWrite) {
var base = byteOffset;
var start = bitOffset;
var remainingBits = totalBitsToWrite;
var len = void 0,
mask = void 0,
byte = void 0,
oddBitsNum = 0;
//console.log(`\twriteBits(num=${num} byteOffset=${byteOffset} bitOffset=${bitOffset} totalBitsToWrite=${totalBitsToWrite})`);
while (remainingBits > 0) {
len = Math.min(remainingBits, 8 - start);
byte = num >>> Math.max(remainingBits - 8, 0) & 0xFF;
mask = makeBitMask(start, len);
//console.log(`\t\twriteByte(byte=${(byte << start) & 0xFF} base=${base} mask=${mask} or=${!!start}`);
writeByte(byte << start & 0xFF, buffer, base, mask, !!start);
remainingBits -= len;
oddBitsNum = Math.max(8 - start - len, 0);
if (oddBitsNum) {
break;
}
base++;
start = 0;
}
//console.log(`\t<<<< return [${base - byteOffset} ${oddBitsNum}];`);
return [base - byteOffset, oddBitsNum];
}
function writeFixedNumber(num, buffer, offset) {
var length = arguments.length <= 3 || arguments[3] === undefined ? 4 : arguments[3];
var left = num > 0 ? Math.floor(num) : Math.ceil(num);
var halfBitsNum = Math.min(length, 8) * 8 / 2;
var base = offset;
var right = parseFloat('0.' + String(num).split('.')[1]);
var writtenBytesNum = 0,
unreadBitsNum = 0;
//console.log(`writeFixedNumber(${num} ${offset} ${length})`);
var _writeBits = writeBits(left, buffer, base, (8 - unreadBitsNum) % 8, halfBitsNum);
var _writeBits2 = (0, _slicedToArray3.default)(_writeBits, 2);
writtenBytesNum = _writeBits2[0];
unreadBitsNum = _writeBits2[1];
base += writtenBytesNum;
if (halfBitsNum === 28 && right >= 0.9999999) {
// ugly
right = 0xFFFFFFFF;
} else if (halfBitsNum === 32 && right >= 0.999999) {
// ugly
right = 0xFFFFFFFF;
} else {
right = Math.round(right * Math.pow(2, halfBitsNum));
}
var _writeBits3 = writeBits(right, buffer, base, (8 - unreadBitsNum) % 8, halfBitsNum);
var _writeBits4 = (0, _slicedToArray3.default)(_writeBits3, 2);
writtenBytesNum = _writeBits4[0];
unreadBitsNum = _writeBits4[1];
base += writtenBytesNum;
//console.log(`<<<< return ${base - offset};`);
return base - offset;
}
function writeIso639Lang(language, buffer, offset) {
var base = offset,
charCode = void 0,
num = 0;
if (language.length !== 3) {
console.error('Writer.writeIso639Lang: Invalid language code - ' + language);
return 0;
}
for (var i = 0; i < 3; i++) {
charCode = language.charCodeAt(i) - 0x60;
if (charCode > 0x1F) {
console.error('Writer.writeIso639Lang: Invalid character - ' + language[i]);
return 0;
}
num <<= 5;
num |= charCode;
}
base += writeNumber(num, buffer, base, 2);
return base - offset;
}
exports.default = {
writeString: writeString,
writeNumber: writeNumber,
writeFixedNumber: writeFixedNumber,
writeIso639Lang: writeIso639Lang
};