UNPKG

@robotical/ricjs

Version:

Javascript/TS library for Robotical RIC

341 lines 11.4 kB
"use strict"; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // RICJS // Communications Library // // Rob Dobson & Chris Greening 2020-2022 // (C) 2020-2022 // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// Object.defineProperty(exports, "__esModule", { value: true }); exports.RICStruct = void 0; class RICStruct { constructor(format) { this._rechk = /^([<>])?(([1-9]\d*)?([xcbB?hHiIfdsp]))*$/; this._refmt = /([1-9]\d*)?([xcbB?hHiIfdsp])/g; this._format = ''; this._outBufferDataView = new DataView(new Uint8Array(0).buffer); this._outBufPos = 0; this._inBufferDataView = new DataView(new Uint8Array(0).buffer); this._inBufPos = 0; this._strPos = 0; this._formedStr = ''; this._argIdx = 0; this._littleEndian = false; // Validate format const regexRslt = this._rechk.exec(format); if (!regexRslt) { throw new RangeError('Invalid format string'); } // Format processing let fPos = 0; this._format = ''; // Check for endian-ness indicator if (fPos < format.length) { if (format.charAt(fPos) == '<') { this._littleEndian = true; fPos++; } else if (format.charAt(fPos) == '>') { this._littleEndian = false; fPos++; } } // Expand numbers in the format while (fPos < format.length) { // Process current position in the format code let repeatLenCode = parseInt(format.substr(fPos), 10); if (isNaN(repeatLenCode)) { repeatLenCode = 1; } else { while (fPos < format.length && format.charAt(fPos) >= '0' && format.charAt(fPos) <= '9') fPos++; } // Expand the single char to multiple (even in the case of string) for (let i = 0; i < repeatLenCode; i++) { this._format += format[fPos]; } // In the case of strings we need to know when to move on to the next variable if (format[fPos] == 's') this._format += '0'; // Next fPos++; } } size() { let outLen = 0; let fPos = 0; while (fPos < this._format.length) { let elLen = 0; switch (this._format[fPos]) { case 'x': { elLen = 1; break; } case '?': { elLen = 1; break; } case 'c': { elLen = 1; break; } case 'b': { elLen = 1; break; } case 'B': { elLen = 1; break; } case 'h': { elLen = 2; break; } case 'H': { elLen = 2; break; } case 'i': { elLen = 4; break; } case 'I': { elLen = 4; break; } case 'f': { elLen = 4; break; } case 'd': { elLen = 8; break; } case 's': { elLen = 1; break; } // this code used to indicate string end case '0': { elLen = 0; break; } } outLen += elLen; fPos += 1; } return outLen; } _packElem(fPos, arg) { // Handle struct code let argInc = 1; switch (this._format[fPos]) { case 'x': { // Skip this._outBufPos++; argInc = 0; break; } case '?': { // Boolean byte value this._outBufferDataView.setInt8(this._outBufPos, arg ? -1 : 0); this._outBufPos++; break; } case 'c': { // Char this._outBufferDataView.setInt8(this._outBufPos, arg.charCodeAt(0)); this._outBufPos++; break; } case 'b': { // Signed byte this._outBufferDataView.setInt8(this._outBufPos, Number(arg)); this._outBufPos++; break; } case 'B': { // Unsigned byte this._outBufferDataView.setUint8(this._outBufPos, Number(arg)); this._outBufPos++; break; } case 'h': { // Signed 16 bit this._outBufferDataView.setInt16(this._outBufPos, Number(arg), this._littleEndian); this._outBufPos += 2; break; } case 'H': { // Unsigned 16 bit this._outBufferDataView.setUint16(this._outBufPos, Number(arg), this._littleEndian); this._outBufPos += 2; break; } case 'i': { // Signed 32 bit this._outBufferDataView.setInt32(this._outBufPos, Number(arg), this._littleEndian); this._outBufPos += 4; break; } case 'I': { // Unsigned 16 bit this._outBufferDataView.setUint32(this._outBufPos, Number(arg), this._littleEndian); this._outBufPos += 4; break; } case 'f': { // Float (32 bit) this._outBufferDataView.setFloat32(this._outBufPos, Number(arg), this._littleEndian); this._outBufPos += 4; break; } case 'd': { // Double (64 bit) this._outBufferDataView.setFloat64(this._outBufPos, Number(arg), this._littleEndian); this._outBufPos += 8; break; } case 's': { const inStr = arg; const chVal = inStr.length >= this._strPos ? inStr.charCodeAt(this._strPos++) : 0; this._outBufferDataView.setUint8(this._outBufPos, chVal); this._outBufPos += 1; argInc = 0; break; } case '0': { // This is to indicate string termination this._strPos = 0; } } this._argIdx += argInc; return fPos + 1; } packInto(buffer, offset, ...args) { this._outBufPos = offset; this._outBufferDataView = new DataView(buffer.buffer); this._strPos = 0; // Iterate format string this._argIdx = 0; let fPos = 0; while (fPos < this._format.length) { if (this._argIdx >= args.length) break; fPos = this._packElem(fPos, args[this._argIdx]); } } pack(...args) { // Generate out buffer const outBuffer = new Uint8Array(this.size()); this.packInto(outBuffer, 0, ...args); return outBuffer; } _unpackElem(fPos, outArray) { // Handle struct code switch (this._format[fPos]) { case 'x': { // Skip this._inBufPos += 1; break; } case '?': { // Boolean byte value outArray.push(this._inBufferDataView.getUint8(this._inBufPos) != 0 ? true : false); this._inBufPos += 1; break; } case 'c': { // Character const charCode = this._inBufferDataView.getInt8(this._inBufPos); outArray.push(String.fromCharCode(charCode)); this._inBufPos += 1; break; } case 'b': { // Signed 8 bit outArray.push(this._inBufferDataView.getInt8(this._inBufPos)); this._inBufPos += 1; break; } case 'B': { // Unsigned 8 bit outArray.push(this._inBufferDataView.getUint8(this._inBufPos)); this._inBufPos += 1; break; } case 'h': { // Signed 16 bit outArray.push(this._inBufferDataView.getInt16(this._inBufPos, this._littleEndian)); this._inBufPos += 2; break; } case 'H': { // Unsigned 16 bit outArray.push(this._inBufferDataView.getUint16(this._inBufPos, this._littleEndian)); this._inBufPos += 2; break; } case 'i': { // Signed 32 bit outArray.push(this._inBufferDataView.getInt32(this._inBufPos, this._littleEndian)); this._inBufPos += 4; break; } case 'I': { // Unsigned 32 bit outArray.push(this._inBufferDataView.getUint32(this._inBufPos, this._littleEndian)); this._inBufPos += 4; break; } case 'f': { // Float (32 bit) outArray.push(this._inBufferDataView.getFloat32(this._inBufPos, this._littleEndian)); this._inBufPos += 4; break; } case 'd': { // Double (64 bit) outArray.push(this._inBufferDataView.getFloat64(this._inBufPos, this._littleEndian)); this._inBufPos += 8; break; } case 's': { // String const chCode = this._inBufferDataView.getInt8(this._inBufPos); this._formedStr += String.fromCharCode(chCode); this._inBufPos += 1; break; } case '0': { // String termination outArray.push(this._formedStr); this._formedStr = ''; } } return fPos + 1; } unpackFrom(buffer, offset) { // Get DataView onto input buffer this._inBufferDataView = new DataView(buffer.buffer); const outArray = new Array(); this._formedStr = ''; // Iterate format string let fPos = offset; this._inBufPos = 0; while (fPos < this._format.length) { fPos = this._unpackElem(fPos, outArray); } return outArray; } unpack(inBuf) { return this.unpackFrom(inBuf, 0); } } exports.RICStruct = RICStruct; //# sourceMappingURL=RICStruct.js.map