@aidin36/xmp
Version:
Read and write XMP metadata from/to various media formats
135 lines (134 loc) • 4.96 kB
JavaScript
;
/*
* This file is part of @aidin36/xmp Javascript package.
*
* @aidin36/xmp is free software: you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* @aidin36/xmp is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details
*
* You should have received a copy of the GNU Lesser General Public License
* along with @aidin26/xmp. If not, see <https://www.gnu.org/licenses/>.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.uint64ToBytes = exports.concatArrays = exports.cloneUint8Array = exports.uint32ToBytes = exports.uint16ToBytes = exports.bytes2Uint64 = exports.bytes2Uint32 = exports.bytes2Uint16 = exports.binArray2String = void 0;
/* eslint-disable no-bitwise */
// At the moment we don't support numbers larger than max UINT32.
// The reason is we have to store them in a bingint, and we can't use biging
// as our array's index.
const maxSupportedInt64 = 4294967295;
const maxUint32 = 4294967295;
const fourZeros = new Uint8Array([0x00, 0x00, 0x00, 0x00]);
/**
* @internal
*
* Javascript strings are UTF-16. But our data is UTF-8.
* We only use this method to decode ASCII strings. e.g. ID of the Boxes, etc.
*/
const binArray2String = (array) => array.reduce((acc, byte) => acc + String.fromCharCode(byte), '');
exports.binArray2String = binArray2String;
/**
* @internal
*
* Converts two bytes in big-endian format to an "unsigned 16-bit integer".
*
* @param bytes - should have at least 2 bytes in it. The function picks up the first 2 bytes.
*/
const bytes2Uint16 = (bytes) => ((bytes[0] << 8) | bytes[1]) >>> 0;
exports.bytes2Uint16 = bytes2Uint16;
/**
* @internal
* Length of 'bytes' should be at least 4. It picks up the first 4 bytes of the array.
*/
const bytes2Uint32 = (bytes) =>
// The >>> 0 is to ensure it's interpreted as unsigned
((bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3]) >>> 0;
exports.bytes2Uint32 = bytes2Uint32;
/**
* @internal
* Length of 'bytes' should be at least 8. It picks up the first 8 bytes of the array.
*/
const bytes2Uint64 = (bytes) => {
if (bytes[3] > 0 || bytes[2] > 0 || bytes[1] > 0 || bytes[0] > 0) {
throw Error(`bytes2Uint64: The library can't handle numbers greater than ${maxSupportedInt64}`);
}
// Javascript doesn't have <<< (unsigned left shift). >>>0 used as a workaround.
// See: https://stackoverflow.com/questions/6798111/bitwise-operations-on-32-bit-unsigned-ints
return (((bytes[0] << 56) |
(bytes[1] << 48) |
(bytes[2] << 40) |
(bytes[3] << 32) |
(bytes[4] << 24) |
(bytes[5] << 16) |
(bytes[6] << 8) |
bytes[7]) >>>
0);
};
exports.bytes2Uint64 = bytes2Uint64;
/**
* @internal
*
* Converts Unsigned 16 bits number to big-endian binary array.
*/
const uint16ToBytes = (num) => {
const array = new Uint8Array(2);
// >>> is used cause it's unsigned
array[0] = (num >>> 8) & 0xff;
array[1] = num & 0xff;
return array;
};
exports.uint16ToBytes = uint16ToBytes;
/**
* @internal
*
* Converts Unsigned 32 bits number to big-endian binary array.
*/
const uint32ToBytes = (num) => {
if (num > maxUint32) {
throw Error(`uint32ToBytes: ${num} is larger than maximum UINT32`);
}
const array = new Uint8Array(4);
// >>> is used cause it's unsigned
array[0] = (num >>> 24) & 0xff;
array[1] = (num >>> 16) & 0xff;
array[2] = (num >>> 8) & 0xff;
array[3] = num & 0xff;
return array;
};
exports.uint32ToBytes = uint32ToBytes;
const cloneUint8Array = (array) => {
const result = new Uint8Array(array.length);
result.set(array, 0);
return result;
};
exports.cloneUint8Array = cloneUint8Array;
const concatArrays = (...arrays) => {
// It's 10 times faster than other methods.
const totalLength = arrays.reduce((sum, arr) => sum + arr.length, 0);
const result = new Uint8Array(totalLength);
let offset = 0;
// Copy each Uint8Array into the result array
for (let i = 0; i < arrays.length; i++) {
result.set(arrays[i], offset);
offset += arrays[i].length;
}
return result;
};
exports.concatArrays = concatArrays;
/**
* @internal
*
* Converts Unsigned 64 bits number to big-endian binary array.
*/
const uint64ToBytes = (num) => {
if (num > maxSupportedInt64) {
throw Error(`uint64ToBytes: The library can't handle numbers greater than ${maxSupportedInt64}`);
}
// At the moment, we don't support any numbers above uint32.
return (0, exports.concatArrays)(fourZeros, (0, exports.uint32ToBytes)(num));
};
exports.uint64ToBytes = uint64ToBytes;