UNPKG

jsboost

Version:

A tiny library that extends the capability of javascript

429 lines (349 loc) 8.87 kB
/** * Author: JCloudYu * Create: 2019/05/04 **/ import {UTF8String} from "./utf8string.esm.js"; const HEX_FORMAT = /^(0x)?([0-9a-fA-F]+)$/; const BIT_FORMAT = /^(0b|0B)?([01]+)$/; const HEX_MAP = "0123456789abcdef"; const HEX_MAP_R = { "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 }; export function PromiseWaitAll(promise_queue=[]) { if ( !Array.isArray(promise_queue) ){ promise_queue = [promise_queue]; } if( promise_queue.length === 0 ){ return Promise.resolve([]); } return new Promise((resolve, reject) =>{ let result_queue=[], ready_count=0, resolved = true; for(let idx=0; idx<promise_queue.length; idx++) { let item = {resolved:true, seq:idx, result:null}; result_queue.push(item); Promise.resolve(promise_queue[idx]).then( (result)=>{ resolved = (item.resolved = true) && resolved; item.result = result; }, (error)=>{ resolved = (item.resolved = false) && resolved; item.result = error; } ).then(()=>{ ready_count++; if ( promise_queue.length === ready_count ) { (resolved?resolve:reject)(result_queue); } }); } }); } export function FlattenedPromise() { const compact = {}; compact.promise = new Promise((resolve, reject)=>{ compact.resolve=resolve; compact.reject=reject; }); return compact; } export function ThrottledTimeout() { let _scheduled = null; let _executing = false; let _hTimeout = null; const timeout_cb = (cb, delay=0, ...args)=>{ _scheduled = {cb, delay, args}; if ( _executing ) return; if ( _hTimeout ) { clearTimeout(_hTimeout); _hTimeout = null; } __DO_TIMEOUT(); }; timeout_cb.clear=()=>{ _scheduled = null; if ( _hTimeout ) { clearTimeout(_hTimeout); _hTimeout = null; } }; return timeout_cb; function __DO_TIMEOUT() { if ( !_scheduled ) return; let {cb, delay, args} = _scheduled; _hTimeout = setTimeout(()=>{ _executing = true; Promise.resolve(cb(...args)) .then( ()=>{ _executing = false; _hTimeout = null; __DO_TIMEOUT(); }, (e)=>{ _executing = false; _hTimeout = null; _scheduled = null; throw e; } ); }, delay); _scheduled = null; } } export function TypeOf(input, resolveObj=false) { const type = typeof input; switch(type) { case "number": case "string": case "function": case "boolean": case "undefined": case "symbol": return type; } if ( input === null ) { return "null"; } if ( input instanceof String ) { return "string"; } if ( input instanceof Number ) { return "number"; } if ( input instanceof Boolean ) { return "boolean"; } if ( Array.isArray(input) ) { return "array"; } if ( !resolveObj ) { return "object"; } // None-primitive if ( input instanceof ArrayBuffer ) { return "array-buffer" } if ( input instanceof DataView ) { return "data-view"; } if ( input instanceof Uint8Array ) { return "uint8-array"; } if ( input instanceof Uint8ClampedArray ) { return "uint8-clamped-array"; } if ( input instanceof Int8Array ) { return "int8-array"; } if ( input instanceof Uint16Array ) { return "uint16-array"; } if ( input instanceof Int16Array ) { return "int16-array"; } if ( input instanceof Uint32Array ) { return "uint32-array"; } if ( input instanceof Int32Array ) { return "int32-array"; } if ( input instanceof Float32Array ) { return "float32-array"; } if ( input instanceof Float64Array ) { return "float64-array"; } if ( input instanceof Map ) { return "map"; } if ( input instanceof WeakMap ) { return "weak-map"; } if ( input instanceof Set ) { return "set"; } if ( input instanceof WeakSet ) { return "weak-set"; } if ( input instanceof RegExp ) { return "regexp" } if ( input instanceof Promise ) { return "promise"; } return "object"; } export function ExtractArrayBuffer(input) { if ( typeof Buffer !== "undefined" ) { 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; } throw new TypeError( "Cannot convert given input data into array buffer" ); } export function BuildArrayBuffer(input, conversion_info=null) { if ( typeof Buffer !== "undefined" ) { if ( input instanceof Buffer ) { let buff = Buffer.alloc(input.length); input.copy(buff, 0); return buff.buffer; } } if ( ArrayBuffer.isView(input) ) { return input.buffer.slice(0); } if ( input instanceof ArrayBuffer ) { return input.slice(0); } if ( Array.isArray(input) ) { const buffer = new Uint8Array(input); return buffer.buffer; } if ( typeof input === "number" ) { let data_buffer = null; switch(conversion_info) { case 'int8': data_buffer = new Int8Array([input]); break; case 'uint8': data_buffer = new Uint8Array([input]); break; case 'int16': data_buffer = new Int16Array([input]); break; case 'uint16': data_buffer = new Uint16Array([input]); break; case 'int32': data_buffer = new Int32Array([input]); break; case 'int64':{ const negative = input < 0; if ( negative ) { input = -input; } let upper = Math.floor(input/0xFFFFFFFF); let lower = input & 0xFFFFFFFF; if ( negative ) { lower = ((~lower)>>>0) + 1; upper = (~upper) + Math.floor(lower/0xFFFFFFFF); } data_buffer = new Uint32Array([lower, upper]); break; } case 'uint64': { const upper = Math.floor(input/0xFFFFFFFF); const lower = input & 0xFFFFFFFF; data_buffer = new Uint32Array([lower, upper]); break; } case 'float32': data_buffer = new Float32Array([input]); break; case 'float64': data_buffer = new Float64Array([input]); break; case 'uint32': default: data_buffer = new Uint32Array([input]); break; } return data_buffer.buffer; } if ( typeof input === "string" ) { if ( conversion_info === "hex" ) { const matches = input.match(HEX_FORMAT); if ( !matches ) { throw new RangeError( "Input argument is not a valid hex string!" ); } let [,,hex_string] = matches; if ( hex_string.length % 2 === 0 ) { hex_string = hex_string.toLowerCase(); } else { hex_string = '0' + hex_string.toLowerCase(); } const buff = new Uint8Array((hex_string.length/2)|0); for ( let i=0; i<buff.length; i++ ) { const offset = i * 2; buff[i] = HEX_MAP_R[hex_string[offset]]<<4 | (HEX_MAP_R[hex_string[offset+1]] & 0x0F); } return buff.buffer; } else if ( conversion_info === "bits" ) { const matches = input.match(BIT_FORMAT); if ( !matches ) { throw new RangeError( "Input argument is not a valid bit string!" ); } let [,,bit_string] = matches; if ( bit_string.length % 8 !== 0 ) { bit_string = '0'.repeat(bit_string.length%8) + bit_string; } const buff = new Uint8Array((bit_string.length/8)|0); for ( let i=0; i<buff.length; i++ ) { const offset = i * 8; let value = (bit_string[offset]==='1'?1:0); for (let k=1; k<8; k++) { value = (value << 1) | (bit_string[offset + k]==='1'?1:0); } buff[i] = value; } return buff.buffer; } else { return UTF8String.Encode(input).buffer; } } throw new TypeError( "Cannot convert given input data into array buffer!" ); } export function CastArrayBufferToString(input, format=16, padding=false) { if ( !(input instanceof ArrayBuffer) ) { throw new TypeError( "Given input must be an ArrayBuffer!" ); } const bytes = new Uint8Array(input); let result = ''; switch(format) { case 16: for(let i=0; i<bytes.length; i++) { const value = bytes[i]; result += HEX_MAP[(value&0xF0)>>>4] + HEX_MAP[value&0x0F]; } break; case 2: for(let i=0; i<bytes.length; i++) { const value = bytes[i]; for (let k=7; k>=0; k--) { result += ((value >>> k) & 0x01) ? '1' : '0'; } } break; default: throw new RangeError( "Unsupported numeric representation!" ); } return padding ? result : result.replace(/^0+/, ''); } export function ObjectAssignProperties(object, props, attr={configurable:false, enumerable:false, writable:false}) { for( const prop in props ) { if ( (props.hasOwnProperty && !props.hasOwnProperty(prop)) || (props[prop] === undefined) ) { continue; } Object.defineProperty(object, prop, { value:props[prop], configurable:!!attr.configurable, enumerable:!!attr.enumerable, writable:!!attr.writable }); } return object; }