UNPKG

beson

Version:

Yet an another binary representation of json format

1,018 lines (825 loc) 23.8 kB
/** * Author: JCloudYu * Create: 2018/10/30 **/ //@export=helper const HAS_NODE_BUFFER = (typeof Buffer !== "undefined"); const DATA_TYPE = Object.freeze({ NULL: 1, FALSE: 2, TRUE: 3, STRING: 4, INT8: 5, INT16: 6, INT32: 7, INT64: 8, INT128: 9, INT256: 10, INT512: 11, // INTVAR: 12, UINT8: 13, UINT16: 14, UINT32: 15, UINT64: 16, UINT128: 17, UINT256: 18, UINT512: 19, // UINTVAR: 20, FLOAT32: 21, FLOAT64: 22, ARRAY: 23, SET: 24, OBJECT: 25, MAP: 26, ARRAY_BUFFER: 27, INT8_ARRAY: 28, UINT8_ARRAY: 29, INT16_ARRAY: 30, UINT16_ARRAY: 31, INT32_ARRAY: 32, UINT32_ARRAY: 33, FLOAT32_ARRAY: 34, FLOAT64_ARRAY: 35, DATA_VIEW: 36, SPECIAL_BUFFER: 37, DATE: 38, REGEX: 39, END: 99, BINARIZABLE: 100, }); const TYPE_HEADER = Object.freeze({ END: 0x00, NULL: 0x10, FALSE: 0x20, TRUE: 0x21, STRING: 0x30, INT8: 0x40, INT16: 0x41, INT32: 0x42, INT64: 0x43, INT128: 0x44, INT256: 0x45, INT512: 0x46, // INTVAR: 0x4F, UINT8: 0x50, UINT16: 0x51, UINT32: 0x52, UINT64: 0x53, UINT128: 0x54, UINT256: 0x55, UINT512: 0x56, // UINTVAR: 0x5F, FLOAT32: 0x60, FLOAT64: 0x61, ARRAY: 0x70, SET: 0x71, OBJECT: 0x80, MAP: 0x81, ARRAY_BUFFER: 0x90, INT8_ARRAY: 0x91, UINT8_ARRAY: 0x92, INT16_ARRAY: 0x93, UINT16_ARRAY: 0x94, INT32_ARRAY: 0x95, UINT32_ARRAY: 0x96, FLOAT32_ARRAY: 0x97, FLOAT64_ARRAY: 0x98, DATA_VIEW: 0x9E, SPECIAL_BUFFER: 0x9F, DATE: 0xA0, REGEX: 0xA1 }); const HEX_FORMAT_CHECKER = /^0x([0-9a-fA-F]{2})+$/; const BIN_FORMAT_CHECKER = /^0b([01]{8})+$/; const INT_FORMAT_CHECKER = /^[+-]?\d+$/; const DECIMAL_STEPPER = new Uint8Array([0x00, 0xCA, 0x9A, 0x3B]); // 1000000000 ( 0x3B9ACA00 ) const HEX_MAP_INVERSE = { 0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, a: 10, b: 11, c: 12, d: 13, e: 14, f: 15, A: 10, B: 11, C: 12, D: 13, E: 14, F: 15 }; const UTF8_DECODE_CHUNK_SIZE = 100; function ReadBuffer(input){ if( HAS_NODE_BUFFER ){ if( input instanceof Buffer ){ let buff = Buffer.alloc(input.length); input.copy(buff, 0); return buff.buffer; } } if( ArrayBuffer.isView(input) ){ return input.buffer; } if( input instanceof ArrayBuffer ){ return input; } return null; } function MergeArrayBuffers(...array_buffers) { if( !array_buffers[0] instanceof ArrayBuffer ) { throw new TypeError("Given inputs must be ArrayBuffers!"); } if ( Array.isArray(array_buffers[0]) ) { array_buffers = array_buffers[0]; } let totalLength = 0; for( let ab of array_buffers ) { totalLength += ab.byteLength; } // NOTE: Copy all data const newInst = new Uint8Array(totalLength); let offset = 0; for( let ab of array_buffers ){ newInst.set(new Uint8Array(ab), offset); offset += ab.byteLength; } return newInst.buffer; } function HexToBuffer(inputStr, length = null){ if( !HEX_FORMAT_CHECKER.test(inputStr) ){ throw new SyntaxError("Given hex string is not a valid hex string!"); } inputStr = inputStr.slice(2); if( inputStr.length % 2 === 1 ){ inputStr = '0' + inputStr; } let buffer = new Uint8Array(inputStr.length / 2); for( let pointer = 0; pointer < buffer.length; pointer++ ){ let offset = pointer * 2; buffer[pointer] = HEX_MAP_INVERSE[inputStr[offset + 1]] | (HEX_MAP_INVERSE[inputStr[offset]] << 4); } return buffer.buffer; } function UTF8Encode(str){ let codePoints = []; let i=0; while( i < str.length ) { let codePoint = str.codePointAt(i); // 1-byte sequence if( (codePoint & 0xffffff80) === 0 ) { codePoints.push(codePoint); } // 2-byte sequence else if( (codePoint & 0xfffff800) === 0 ) { codePoints.push( 0xc0 | (0x1f & (codePoint >> 6)), 0x80 | (0x3f & codePoint) ); } // 3-byte sequence else if( (codePoint & 0xffff0000) === 0 ) { codePoints.push( 0xe0 | (0x0f & (codePoint >> 12)), 0x80 | (0x3f & (codePoint >> 6)), 0x80 | (0x3f & codePoint) ); } // 4-byte sequence else if( (codePoint & 0xffe00000) === 0 ) { codePoints.push( 0xf0 | (0x07 & (codePoint >> 18)), 0x80 | (0x3f & (codePoint >> 12)), 0x80 | (0x3f & (codePoint >> 6)), 0x80 | (0x3f & codePoint) ); } i += (codePoint>0xFFFF) ? 2 : 1; } return new Uint8Array(codePoints); } function UTF8Decode(buffer){ let uint8 = new Uint8Array(buffer); let codePoints = []; let i = 0; while( i < uint8.length ) { let codePoint = uint8[i] & 0xff; // 1-byte sequence (0 ~ 127) if( (codePoint & 0x80) === 0 ){ codePoints.push(codePoint); i += 1; } // 2-byte sequence (192 ~ 223) else if( (codePoint & 0xE0) === 0xC0 ){ codePoint = ((0x1f & uint8[i]) << 6) | (0x3f & uint8[i + 1]); codePoints.push(codePoint); i += 2; } // 3-byte sequence (224 ~ 239) else if( (codePoint & 0xf0) === 0xe0 ){ codePoint = ((0x0f & uint8[i]) << 12) | ((0x3f & uint8[i + 1]) << 6) | (0x3f & uint8[i + 2]); codePoints.push(codePoint); i += 3; } // 4-byte sequence (249 ~ ) else if( (codePoint & 0xF8) === 0xF0 ){ codePoint = ((0x07 & uint8[i]) << 18) | ((0x3f & uint8[i + 1]) << 12) | ((0x3f & uint8[i + 2]) << 6) | (0x3f & uint8[i + 3]); codePoints.push(codePoint); i += 4; } else { i += 1; } } let result_string = ""; while(codePoints.length > 0) { const chunk = codePoints.splice(0, UTF8_DECODE_CHUNK_SIZE); result_string += String.fromCodePoint(...chunk); } return result_string; } function BitwiseNot(input){ input = ReadBuffer(input); if( input === null ){ throw new TypeError("Given input must be an ArrayBuffer!"); } const buffer = new Uint8Array(input); for( let off = 0; off < buffer.length; off++ ){ buffer[off] = ~buffer[off]; } } function BitwiseAnd(a, b){ a = ReadBuffer(a); b = ReadBuffer(b); if( a === null || b === null ){ throw new TypeError("Given inputs must be ArrayBuffers!"); } const bufferA = new Uint8Array(a); const bufferB = new Uint8Array(b); for( let off = 0; off < bufferA.length; off++ ){ bufferA[off] = bufferA[off] & (bufferB[off] || 0); } } function BitwiseOr(a, b){ a = ReadBuffer(a); b = ReadBuffer(b); if( a === null || b === null ){ throw new TypeError("Given inputs must be ArrayBuffers!"); } const bufferA = new Uint8Array(a); const bufferB = new Uint8Array(b); for( let off = 0; off < bufferA.length; off++ ){ bufferA[off] = bufferA[off] | (bufferB[off] || 0); } } function BitwiseXor(a, b){ a = ReadBuffer(a); b = ReadBuffer(b); if( a === null || b === null ){ throw new TypeError("Given inputs must be ArrayBuffers!"); } const bufferA = new Uint8Array(a); const bufferB = new Uint8Array(b); for( let off = 0; off < bufferA.length; off++ ){ bufferA[off] = bufferA[off] ^ (bufferB[off] || 0); } } function BitwiseIsZero(input){ const buff = new Uint8Array(ReadBuffer(input)); let isZero = true; for( let i = 0; i < buff.length; i++ ){ isZero = isZero && (buff[i] === 0); } return isZero; } function __COPY_BYTES(target, source, length, source_start=0, target_start=0) { for(let i=0; i<length; i++) { target[target_start+i] = source[source_start+i]; } } function ___SET_BINARY_BUFFER(array_buffer){ if( !(array_buffer instanceof ArrayBuffer) ){ throw new TypeError("Given input must be an ArrayBuffer!"); } this._ab = array_buffer; this._ba = new Uint8Array(this._ab); return this; } // region [ Little Endian Operations ] function BufferFromHexStrLE(inputStr, size = null){ if( !HEX_FORMAT_CHECKER.test(inputStr) ){ throw new SyntaxError("Given hex string is not a valid hex string!"); } inputStr = inputStr.slice(2); if( inputStr.length % 2 === 1 ){ inputStr = '0' + inputStr; } let inputLen = Math.floor(inputStr.length / 2); if( arguments.length <= 1 ){ size = inputLen; } else if( size < 0 ){ throw new RangeError("Given buffer size should greater than or equal to 0!"); } let buffer = new Uint8Array(size); for( let pointer = 0; pointer < inputLen; pointer++ ){ let offset = (inputLen - pointer - 1) * 2; buffer[pointer] = HEX_MAP_INVERSE[inputStr[offset + 1]] | (HEX_MAP_INVERSE[inputStr[offset]] << 4); } return buffer; } function BufferFromBinStrLE(inputStr, size = null){ if( !BIN_FORMAT_CHECKER.test(inputStr) ){ throw new SyntaxError("Given hex string is not a valid hex string!"); } inputStr = inputStr.slice(2); let inputLen = Math.floor(inputStr.length / 8); if( arguments.length <= 1 ){ size = inputLen; } else if( size < 0 ){ throw new RangeError("Given buffer size should greater than or equal to 0!"); } let buffer = new Uint8Array(size); for( let pointer = 0; pointer < inputLen; pointer++ ){ let offset = (inputLen - pointer - 1) * 8; buffer[pointer] = Number.parseInt(inputStr.substring(offset, offset + 8), 2); } return buffer; } function DumpHexStringLE(input){ let val = new Uint8Array(ReadBuffer(input)); let str = ''; for( let i = val.length - 1; i >= 0; i-- ){ let value = val[i].toString(16); str += `${ value.length === 1 ? '0' : '' }${ value }`; } return str; } function DumpBinaryStringLE(input){ let val = new Uint8Array(ReadBuffer(input)); let str = ''; for( let i = val.length - 1; i >= 0; i-- ){ let value = val[i]; for( let s = 0; s < 8; s++ ){ str += ((value << s) & 0x80) ? '1' : '0'; } } return str; } function BitwiseCompareLE(a, b){ a = ReadBuffer(a); b = ReadBuffer(b); if( a === null || b === null ){ throw new TypeError("Given inputs must be ArrayBuffers!"); } // NOTE: Compare nothing... if( a.byteLength === 0 && b.byteLength === 0 ){ return 0; } let A = new Uint8Array(a); let B = new Uint8Array(b); let valA, valB; for( let i = Math.max(A.length, B.length); i > 0; i-- ){ valA = A[i-1] || 0; valB = B[i-1] || 0; if( valA === valB ){ continue; } return valA > valB ? 1 : -1; } return 0; } function BitwiseRightShiftLE(value, shift, padding = 0){ if( typeof shift !== "number" ){ throw new TypeError("Shift bits number must be a number"); } value = ReadBuffer(value); if( value === null ){ throw new TypeError("Given value must be an ArrayBuffer!"); } const buffer = new Uint8Array(value); if( shift > 0 ){ padding = padding ? 0xFF : 0x00; if( shift >= buffer.byteLength * 8 ){ buffer.fill(padding); } else{ const OFFSET = (shift / 8) | 0; const REAL_SHIFT = shift % 8; const REAL_SHIFT_I = 8 - REAL_SHIFT; const HI_MASK = REAL_SHIFT ? ___GEN_8BITS_MASK(REAL_SHIFT) : 0; const LOOP_END = buffer.byteLength - OFFSET; for( let off = 0; off < LOOP_END; off++ ){ let shift = off + OFFSET; if( REAL_SHIFT === 0 ){ buffer[off] = buffer[shift]; } else{ let shiftVal = buffer[shift]; let next = (shift >= buffer.byteLength - 1) ? padding : buffer[shift + 1]; buffer[off] = (shiftVal >>> REAL_SHIFT) | ((next & HI_MASK) << REAL_SHIFT_I); } } for( let off = LOOP_END; off < buffer.byteLength; off++ ){ buffer[off] = padding; } } } } function BitwiseLeftShiftLE(value, shift, padding = 0){ if( typeof shift !== "number" ){ throw new TypeError("Shift bits must be a number!"); } value = ReadBuffer(value); if( value === null ){ throw new TypeError("Given value must be an ArrayBuffer!"); } const buffer = new Uint8Array(value); if( shift > 0 ){ padding = padding ? 0xFF : 0x00; if( shift >= buffer.byteLength * 8 ){ buffer.fill(padding); } else{ const OFFSET = (shift / 8) | 0; const REAL_SHIFT = shift % 8; const REAL_SHIFT_I = 8 - REAL_SHIFT; const LO_MASK = REAL_SHIFT ? (___GEN_8BITS_MASK(REAL_SHIFT) << REAL_SHIFT_I) : 0; for( let off = buffer.byteLength - 1; off >= OFFSET; off-- ){ let shift = off - OFFSET; if( REAL_SHIFT === 0 ){ buffer[off] = buffer[shift]; } else{ let shiftVal = buffer[shift]; let next = (shift <= 0) ? padding : buffer[shift - 1]; buffer[off] = (shiftVal << REAL_SHIFT) | ((next & LO_MASK) >> REAL_SHIFT_I); } } buffer.fill(padding, 0, OFFSET); } } } function BitwiseIsNegativeLE(input){ const buff = new Uint8Array(ReadBuffer(input)); return ((buff[buff.length - 1] & 0x80) !== 0) } // region [ Little Endian exclusive functions ] function BufferFromIntStrLE(inputStr, size = null){ if( !INT_FORMAT_CHECKER.test(inputStr) ){ throw new SyntaxError("Given hex string is not a valid hex string!"); } let negative = false; if( inputStr[0] === "-" ){ negative = true; inputStr = inputStr.substring(1); } else if( inputStr[0] === "+" ){ inputStr = inputStr.substring(1); } let force_size = true; let inputLen = Math.ceil(Math.ceil(inputStr.length * Math.log2(10)) / 8); if( arguments.length <= 1 ){ force_size = false; size = inputLen; } else if( size < 0 ){ throw new RangeError("Given buffer size should greater than or equal to 0!"); } const inputs = []; while( inputStr.length > 0 ){ let anchor = inputStr.length - 9; inputs.push(Number.parseInt(inputStr.substring(anchor), 10)); inputStr = inputStr.substring(0, anchor); } inputs.reverse(); const buffer = new Uint8Array(size); const part = new Uint32Array(1); for( let i = 0; i < inputs.length; i++ ){ part[0] = inputs[i]; BitwiseMultiplicationLE(buffer, DECIMAL_STEPPER); BitwiseAdditionLE(buffer, part); } // NOTE: In case that the highest bit is 1 ( the size is not efficient to represent the value ) let _result = buffer; if( !force_size ){ let real_len = size - 1; while( (real_len > 0) && ((buffer[real_len] & 0xFF) === 0) ){ real_len--; } if( (buffer[real_len] & 0x80) !== 0 ){ real_len++; } _result = (real_len === size) ? buffer : buffer.slice(0, real_len + 1); } if( negative ){ BitwiseTwoComplimentLE(_result); } return _result; } function DumpIntStringLE(input, unsigned = false){ let is_negative = false; const value = new Uint8Array(ReadBuffer(input).slice(0)); if( !unsigned && BitwiseIsNegativeLE(value) ){ BitwiseTwoComplimentLE(value); is_negative = true; } let result = ''; const remainder = new Uint8Array(value.length); const stepper = new Uint8Array(value.length); stepper[0] = 100; BitwiseDivisionLE(value, stepper, true, remainder); while( !BitwiseIsZero(value) ){ let part = remainder[0].toString(10); result = ((part.length === 1) ? `0${ part }` : part) + result; BitwiseDivisionLE(value, stepper, true, remainder); } return (is_negative ? '-' : '') + remainder[0].toString(10) + result; } function BitwiseMultiplicationLE(multiplier, multiplicand){ const a = new Uint8Array(ReadBuffer(multiplier)); const b = new Uint8Array(ReadBuffer(multiplicand)); const res = new Uint8Array(a.length); let carriage = 0; for( let i = 0; i < res.length; i++ ){ for( let j = 0; j <= i; j++ ){ carriage += a[j] * (b[i - j] || 0) } res[i] = carriage; carriage = (carriage / 256) | 0; } a.set(res); } function BitwiseAdditionLE(addend_a, addend_b){ let a = new Uint8Array(ReadBuffer(addend_a)); let b = new Uint8Array(ReadBuffer(addend_b)); let carriage = 0; for( let i = 0; i < a.length; i++ ){ carriage += a[i] + (b[i] || 0); a[i] = carriage; carriage = (carriage / 256) | 0; } } function BitwiseSubtractionLE(minuend, subtrahend){ const a = new Uint8Array(ReadBuffer(minuend)); const b = new Uint8Array(ReadBuffer(subtrahend)); const negB = new Uint8Array(b); BitwiseTwoComplimentLE(negB); BitwiseAdditionLE(a, negB); } function BitwiseDivisionLE(dividend, divisor, unsigned = false, remainder_buff = null){ const raw_a = new Uint8Array(ReadBuffer(dividend)); const raw_b = new Uint8Array(ReadBuffer(divisor)); const a = raw_a; const b = new Uint8Array(a.length); b.set(raw_b); if( BitwiseIsZero(b) ){ throw new TypeError("Dividing zero is not allowed!"); } let neg_dividend = 0x00, neg_divisor = 0x00; if( !unsigned ){ neg_dividend = BitwiseIsNegativeLE(a) ? 0x01 : 0x00; if( neg_dividend ){ BitwiseTwoComplimentLE(a); } neg_divisor = BitwiseIsNegativeLE(b) ? 0x01 : 0x00; if( neg_divisor ){ BitwiseTwoComplimentLE(b); } } const remainder = new Uint8Array((remainder_buff !== null) ? ReadBuffer(remainder_buff) : a.length); remainder.set(a); const quotient = a; quotient.fill(0); if( BitwiseCompareLE(remainder, b) >= 0 ){ let _remainder = remainder.slice(0); let _divisor = b; // region [ Align divisor and remainder ] let d_padding = 0, r_padding = 0, count = _remainder.length * 8; while( count-- > 0 ){ if( (_remainder[_remainder.length - 1] & 0x80) !== 0 ){ break; } BitwiseLeftShiftLE(_remainder, 1); r_padding++; } _remainder = remainder; count = _divisor.length * 8; while( count-- > 0 ){ if( (_divisor[_divisor.length - 1] & 0x80) !== 0 ){ break; } BitwiseLeftShiftLE(_divisor, 1); d_padding++; } BitwiseRightShiftLE(_divisor, r_padding); // endregion // region [ Calc division ] count = d_padding - r_padding + 1; while( count-- > 0 ){ if( BitwiseCompareLE(_remainder, _divisor) >= 0 ){ BitwiseSubtractionLE(_remainder, _divisor); quotient[0] = quotient[0] | 0x01; } if( count > 0 ){ BitwiseLeftShiftLE(quotient, 1); BitwiseRightShiftLE(_divisor, 1); } } // endregion } if( neg_divisor ^ neg_dividend ){ BitwiseTwoComplimentLE(quotient); } return remainder; } function BitwiseTwoComplimentLE(input){ input = ReadBuffer(input); if( input === null ){ throw new TypeError("Given input must be an ArrayBuffer!"); } const buffer = new Uint8Array(input); let carriage = 1; for( let off = 0; off < buffer.length; off++ ){ carriage += ((~buffer[off] >>> 0) & 0xFF); buffer[off] = carriage; carriage = (carriage / 256) | 0; } } // endregion // endregion // region [ Big Endian Operations ] function BufferFromHexStrBE(inputStr, size = 0){ if( !HEX_FORMAT_CHECKER.test(inputStr) ){ throw new SyntaxError("Given hex string is not a valid hex string!"); } inputStr = inputStr.slice(2); if( inputStr.length % 2 === 1 ){ inputStr = '0' + inputStr; } if( arguments.length <= 1 ){ size = Math.floor(inputStr.length / 2); } else if( size < 0 ){ throw new RangeError("Given buffer size should greater than or equal to 0!"); } let buffer = new Uint8Array(size); for( let pointer = 0; pointer < buffer.length; pointer++ ){ let offset = pointer * 2; buffer[pointer] = HEX_MAP_INVERSE[inputStr[offset + 1]] | (HEX_MAP_INVERSE[inputStr[offset]] << 4); } return buffer; } function BufferFromBinStrBE(inputStr, size = null){ if( !BIN_FORMAT_CHECKER.test(inputStr) ){ throw new SyntaxError("Given hex string is not a valid hex string!"); } inputStr = inputStr.slice(2); if( arguments.length <= 1 ){ size = Math.floor(inputStr.length / 8); } else if( size < 0 ){ throw new RangeError("Given buffer size should greater than or equal to 0!"); } let buffer = new Uint8Array(size); for( let pointer = 0; pointer < buffer.length; pointer++ ){ let offset = pointer * 8; buffer[pointer] = Number.parseInt(inputStr.substring(offset, offset + 8), 2); } return buffer; } function DumpHexStringBE(input){ let val = new Uint8Array(ReadBuffer(input)); const length = val.length; let str = ''; for( let i = 0; i < length; i++ ){ let value = val[i].toString(16); str += `${ value.length === 1 ? '0' : '' }${ value }`; } return str; } function DumpBinaryStringBE(input){ let val = new Uint8Array(ReadBuffer(input)); const length = val.length; let str = ''; for( let i = 0; i < length; i++ ){ let value = val[i]; for( let s = 0; s < 8; s++ ){ str += ((value << s) & 0x80) ? '1' : '0'; } } return str; } function BitwiseIsNegativeBE(input){ const buff = new Uint8Array(ReadBuffer(input)); return ((buff[0] & 0x80) !== 0) } function BitwiseCompareBE(a, b){ a = ReadBuffer(a); b = ReadBuffer(b); if( a === null || b === null ){ throw new TypeError("Given inputs must be ArrayBuffers!"); } // NOTE: Compare nothing... if( a.byteLength === 0 && b.byteLength === 0 ){ return 0; } let A = new Uint8Array(a); let B = new Uint8Array(b); let valA, valB, max = Math.max(A.length, B.length); for( let i = 0; i < max; i++ ){ valA = A[i] || 0; valB = B[i] || 0; if( valA === valB ){ continue; } return valA > valB ? 1 : -1; } return 0; } function BitwiseRightShiftBE(value, shift, padding = 0){ if( typeof shift !== "number" ){ throw new TypeError("Shift bits number must be a number"); } value = ReadBuffer(value); if( value === null ){ throw new TypeError("Given value must be an ArrayBuffer!"); } const buffer = new Uint8Array(value); if( shift > 0 ){ padding = padding ? 0xFF : 0x00; if( shift >= buffer.byteLength * 8 ){ for( let off = 0; off < buffer.length; off++ ){ buffer.fill(padding); } } else{ const OFFSET = (shift / 8) | 0; const REAL_SHIFT = shift % 8; const REAL_SHIFT_I = 8 - REAL_SHIFT; const HI_MASK = REAL_SHIFT ? ___GEN_8BITS_MASK(REAL_SHIFT) : 0; for( let off = (buffer.byteLength - 1); off >= OFFSET; off-- ){ let shift = off - OFFSET; if( REAL_SHIFT === 0 ){ buffer[off] = buffer[shift]; } else{ let shiftVal = buffer[shift]; let next = (shift === 0) ? padding : buffer[shift - 1]; buffer[off] = (shiftVal >>> REAL_SHIFT) | ((next & HI_MASK) << REAL_SHIFT_I); } } for( let off = OFFSET - 1; off >= 0; off-- ){ buffer[off] = padding; } } } } function BitwiseLeftShiftBE(value, shift, padding = 0){ if( typeof shift !== "number" ){ throw new TypeError("Shift bits must be a number!"); } value = ReadBuffer(value); if( value === null ){ throw new TypeError("Given value must be an ArrayBuffer!"); } const buffer = new Uint8Array(value); if( shift > 0 ){ padding = padding ? 0xFF : 0x00; if( shift >= buffer.byteLength * 8 ){ for( let off = 0; off < buffer.length; off++ ){ buffer.fill(padding); } } else{ const OFFSET = (shift / 8) | 0; const LAST_OFFSET = buffer.byteLength - OFFSET; const REAL_SHIFT = shift % 8; const REAL_SHIFT_I = 8 - REAL_SHIFT; const LO_MASK = REAL_SHIFT ? (___GEN_8BITS_MASK(REAL_SHIFT) << REAL_SHIFT_I) : 0; for( let off = 0; off < LAST_OFFSET; off++ ){ let shift = off + OFFSET; if( REAL_SHIFT === 0 ){ buffer[off] = buffer[shift]; } else{ let shiftVal = buffer[shift]; let next = shift >= (buffer.byteLength - 1) ? padding : buffer[shift + 1]; buffer[off] = (shiftVal << REAL_SHIFT) | ((next & LO_MASK) >> REAL_SHIFT_I); } } for( let off = LAST_OFFSET; off < buffer.byteLength; off++ ){ buffer[off] = padding; } } } } // endregion /** * Generate a 8-bits mask * @param {Number} BITS * @private **/ function ___GEN_8BITS_MASK(BITS){ if( BITS > 8 ) return 0xFF; if( BITS < 0 ) return 0; let val = 0; while( BITS-- > 0 ){ val = ((val << 1) | 1) >>> 0; } return val; } //@endexport export {HAS_NODE_BUFFER, DATA_TYPE, TYPE_HEADER, ReadBuffer, MergeArrayBuffers, HexToBuffer, UTF8Encode, UTF8Decode, BitwiseNot, BitwiseAnd, BitwiseOr, BitwiseXor, BitwiseIsZero, __COPY_BYTES, ___SET_BINARY_BUFFER, BufferFromHexStrLE, BufferFromBinStrLE, DumpHexStringLE, DumpBinaryStringLE, BitwiseCompareLE, BitwiseRightShiftLE, BitwiseLeftShiftLE, BitwiseIsNegativeLE, BufferFromIntStrLE, DumpIntStringLE, BitwiseMultiplicationLE, BitwiseAdditionLE, BitwiseSubtractionLE, BitwiseDivisionLE, BitwiseTwoComplimentLE, BufferFromHexStrBE, BufferFromBinStrBE, DumpHexStringBE, DumpBinaryStringBE, BitwiseIsNegativeBE, BitwiseCompareBE, BitwiseRightShiftBE, BitwiseLeftShiftBE};