{"version":3,"file":"spc-parser.min.js","sources":["../node_modules/iobuffer/lib-esm/utf8.browser.js","../node_modules/iobuffer/lib-esm/IOBuffer.js","../src/dataBlock.js","../src/utility.js","../src/logBlock.js","../src/types.js","../src/mainHeader.js","../src/index.js"],"sourcesContent":["// eslint-disable-next-line import/no-unassigned-import\r\nimport './text-encoding-polyfill';\r\nconst decoder = new TextDecoder('utf-8');\r\nexport function decode(bytes) {\r\n return decoder.decode(bytes);\r\n}\r\nconst encoder = new TextEncoder();\r\nexport function encode(str) {\r\n return encoder.encode(str);\r\n}\r\n//# sourceMappingURL=utf8.browser.js.map","import { decode, encode } from './utf8';\r\nconst defaultByteLength = 1024 * 8;\r\nexport class IOBuffer {\r\n /**\r\n * @param data - The data to construct the IOBuffer with.\r\n * If data is a number, it will be the new buffer's length
\r\n * If data is `undefined`, the buffer will be initialized with a default length of 8Kb
\r\n * If data is an ArrayBuffer, SharedArrayBuffer, an ArrayBufferView (Typed Array), an IOBuffer instance,\r\n * or a Node.js Buffer, a view will be created over the underlying ArrayBuffer.\r\n * @param options\r\n */\r\n constructor(data = defaultByteLength, options = {}) {\r\n let dataIsGiven = false;\r\n if (typeof data === 'number') {\r\n data = new ArrayBuffer(data);\r\n }\r\n else {\r\n dataIsGiven = true;\r\n this.lastWrittenByte = data.byteLength;\r\n }\r\n const offset = options.offset ? options.offset >>> 0 : 0;\r\n const byteLength = data.byteLength - offset;\r\n let dvOffset = offset;\r\n if (ArrayBuffer.isView(data) || data instanceof IOBuffer) {\r\n if (data.byteLength !== data.buffer.byteLength) {\r\n dvOffset = data.byteOffset + offset;\r\n }\r\n data = data.buffer;\r\n }\r\n if (dataIsGiven) {\r\n this.lastWrittenByte = byteLength;\r\n }\r\n else {\r\n this.lastWrittenByte = 0;\r\n }\r\n this.buffer = data;\r\n this.length = byteLength;\r\n this.byteLength = byteLength;\r\n this.byteOffset = dvOffset;\r\n this.offset = 0;\r\n this.littleEndian = true;\r\n this._data = new DataView(this.buffer, dvOffset, byteLength);\r\n this._mark = 0;\r\n this._marks = [];\r\n }\r\n /**\r\n * Checks if the memory allocated to the buffer is sufficient to store more\r\n * bytes after the offset.\r\n * @param byteLength - The needed memory in bytes.\r\n * @returns `true` if there is sufficient space and `false` otherwise.\r\n */\r\n available(byteLength = 1) {\r\n return this.offset + byteLength <= this.length;\r\n }\r\n /**\r\n * Check if little-endian mode is used for reading and writing multi-byte\r\n * values.\r\n * @returns `true` if little-endian mode is used, `false` otherwise.\r\n */\r\n isLittleEndian() {\r\n return this.littleEndian;\r\n }\r\n /**\r\n * Set little-endian mode for reading and writing multi-byte values.\r\n */\r\n setLittleEndian() {\r\n this.littleEndian = true;\r\n return this;\r\n }\r\n /**\r\n * Check if big-endian mode is used for reading and writing multi-byte values.\r\n * @returns `true` if big-endian mode is used, `false` otherwise.\r\n */\r\n isBigEndian() {\r\n return !this.littleEndian;\r\n }\r\n /**\r\n * Switches to big-endian mode for reading and writing multi-byte values.\r\n */\r\n setBigEndian() {\r\n this.littleEndian = false;\r\n return this;\r\n }\r\n /**\r\n * Move the pointer n bytes forward.\r\n * @param n - Number of bytes to skip.\r\n */\r\n skip(n = 1) {\r\n this.offset += n;\r\n return this;\r\n }\r\n /**\r\n * Move the pointer to the given offset.\r\n * @param offset\r\n */\r\n seek(offset) {\r\n this.offset = offset;\r\n return this;\r\n }\r\n /**\r\n * Store the current pointer offset.\r\n * @see {@link IOBuffer#reset}\r\n */\r\n mark() {\r\n this._mark = this.offset;\r\n return this;\r\n }\r\n /**\r\n * Move the pointer back to the last pointer offset set by mark.\r\n * @see {@link IOBuffer#mark}\r\n */\r\n reset() {\r\n this.offset = this._mark;\r\n return this;\r\n }\r\n /**\r\n * Push the current pointer offset to the mark stack.\r\n * @see {@link IOBuffer#popMark}\r\n */\r\n pushMark() {\r\n this._marks.push(this.offset);\r\n return this;\r\n }\r\n /**\r\n * Pop the last pointer offset from the mark stack, and set the current\r\n * pointer offset to the popped value.\r\n * @see {@link IOBuffer#pushMark}\r\n */\r\n popMark() {\r\n const offset = this._marks.pop();\r\n if (offset === undefined) {\r\n throw new Error('Mark stack empty');\r\n }\r\n this.seek(offset);\r\n return this;\r\n }\r\n /**\r\n * Move the pointer offset back to 0.\r\n */\r\n rewind() {\r\n this.offset = 0;\r\n return this;\r\n }\r\n /**\r\n * Make sure the buffer has sufficient memory to write a given byteLength at\r\n * the current pointer offset.\r\n * If the buffer's memory is insufficient, this method will create a new\r\n * buffer (a copy) with a length that is twice (byteLength + current offset).\r\n * @param byteLength\r\n */\r\n ensureAvailable(byteLength = 1) {\r\n if (!this.available(byteLength)) {\r\n const lengthNeeded = this.offset + byteLength;\r\n const newLength = lengthNeeded * 2;\r\n const newArray = new Uint8Array(newLength);\r\n newArray.set(new Uint8Array(this.buffer));\r\n this.buffer = newArray.buffer;\r\n this.length = this.byteLength = newLength;\r\n this._data = new DataView(this.buffer);\r\n }\r\n return this;\r\n }\r\n /**\r\n * Read a byte and return false if the byte's value is 0, or true otherwise.\r\n * Moves pointer forward by one byte.\r\n */\r\n readBoolean() {\r\n return this.readUint8() !== 0;\r\n }\r\n /**\r\n * Read a signed 8-bit integer and move pointer forward by 1 byte.\r\n */\r\n readInt8() {\r\n return this._data.getInt8(this.offset++);\r\n }\r\n /**\r\n * Read an unsigned 8-bit integer and move pointer forward by 1 byte.\r\n */\r\n readUint8() {\r\n return this._data.getUint8(this.offset++);\r\n }\r\n /**\r\n * Alias for {@link IOBuffer#readUint8}.\r\n */\r\n readByte() {\r\n return this.readUint8();\r\n }\r\n /**\r\n * Read `n` bytes and move pointer forward by `n` bytes.\r\n */\r\n readBytes(n = 1) {\r\n const bytes = new Uint8Array(n);\r\n for (let i = 0; i < n; i++) {\r\n bytes[i] = this.readByte();\r\n }\r\n return bytes;\r\n }\r\n /**\r\n * Read a 16-bit signed integer and move pointer forward by 2 bytes.\r\n */\r\n readInt16() {\r\n const value = this._data.getInt16(this.offset, this.littleEndian);\r\n this.offset += 2;\r\n return value;\r\n }\r\n /**\r\n * Read a 16-bit unsigned integer and move pointer forward by 2 bytes.\r\n */\r\n readUint16() {\r\n const value = this._data.getUint16(this.offset, this.littleEndian);\r\n this.offset += 2;\r\n return value;\r\n }\r\n /**\r\n * Read a 32-bit signed integer and move pointer forward by 4 bytes.\r\n */\r\n readInt32() {\r\n const value = this._data.getInt32(this.offset, this.littleEndian);\r\n this.offset += 4;\r\n return value;\r\n }\r\n /**\r\n * Read a 32-bit unsigned integer and move pointer forward by 4 bytes.\r\n */\r\n readUint32() {\r\n const value = this._data.getUint32(this.offset, this.littleEndian);\r\n this.offset += 4;\r\n return value;\r\n }\r\n /**\r\n * Read a 32-bit floating number and move pointer forward by 4 bytes.\r\n */\r\n readFloat32() {\r\n const value = this._data.getFloat32(this.offset, this.littleEndian);\r\n this.offset += 4;\r\n return value;\r\n }\r\n /**\r\n * Read a 64-bit floating number and move pointer forward by 8 bytes.\r\n */\r\n readFloat64() {\r\n const value = this._data.getFloat64(this.offset, this.littleEndian);\r\n this.offset += 8;\r\n return value;\r\n }\r\n /**\r\n * Read a 1-byte ASCII character and move pointer forward by 1 byte.\r\n */\r\n readChar() {\r\n return String.fromCharCode(this.readInt8());\r\n }\r\n /**\r\n * Read `n` 1-byte ASCII characters and move pointer forward by `n` bytes.\r\n */\r\n readChars(n = 1) {\r\n let result = '';\r\n for (let i = 0; i < n; i++) {\r\n result += this.readChar();\r\n }\r\n return result;\r\n }\r\n /**\r\n * Read the next `n` bytes, return a UTF-8 decoded string and move pointer\r\n * forward by `n` bytes.\r\n */\r\n readUtf8(n = 1) {\r\n return decode(this.readBytes(n));\r\n }\r\n /**\r\n * Write 0xff if the passed value is truthy, 0x00 otherwise and move pointer\r\n * forward by 1 byte.\r\n */\r\n writeBoolean(value) {\r\n this.writeUint8(value ? 0xff : 0x00);\r\n return this;\r\n }\r\n /**\r\n * Write `value` as an 8-bit signed integer and move pointer forward by 1 byte.\r\n */\r\n writeInt8(value) {\r\n this.ensureAvailable(1);\r\n this._data.setInt8(this.offset++, value);\r\n this._updateLastWrittenByte();\r\n return this;\r\n }\r\n /**\r\n * Write `value` as an 8-bit unsigned integer and move pointer forward by 1\r\n * byte.\r\n */\r\n writeUint8(value) {\r\n this.ensureAvailable(1);\r\n this._data.setUint8(this.offset++, value);\r\n this._updateLastWrittenByte();\r\n return this;\r\n }\r\n /**\r\n * An alias for {@link IOBuffer#writeUint8}.\r\n */\r\n writeByte(value) {\r\n return this.writeUint8(value);\r\n }\r\n /**\r\n * Write all elements of `bytes` as uint8 values and move pointer forward by\r\n * `bytes.length` bytes.\r\n */\r\n writeBytes(bytes) {\r\n this.ensureAvailable(bytes.length);\r\n for (let i = 0; i < bytes.length; i++) {\r\n this._data.setUint8(this.offset++, bytes[i]);\r\n }\r\n this._updateLastWrittenByte();\r\n return this;\r\n }\r\n /**\r\n * Write `value` as a 16-bit signed integer and move pointer forward by 2\r\n * bytes.\r\n */\r\n writeInt16(value) {\r\n this.ensureAvailable(2);\r\n this._data.setInt16(this.offset, value, this.littleEndian);\r\n this.offset += 2;\r\n this._updateLastWrittenByte();\r\n return this;\r\n }\r\n /**\r\n * Write `value` as a 16-bit unsigned integer and move pointer forward by 2\r\n * bytes.\r\n */\r\n writeUint16(value) {\r\n this.ensureAvailable(2);\r\n this._data.setUint16(this.offset, value, this.littleEndian);\r\n this.offset += 2;\r\n this._updateLastWrittenByte();\r\n return this;\r\n }\r\n /**\r\n * Write `value` as a 32-bit signed integer and move pointer forward by 4\r\n * bytes.\r\n */\r\n writeInt32(value) {\r\n this.ensureAvailable(4);\r\n this._data.setInt32(this.offset, value, this.littleEndian);\r\n this.offset += 4;\r\n this._updateLastWrittenByte();\r\n return this;\r\n }\r\n /**\r\n * Write `value` as a 32-bit unsigned integer and move pointer forward by 4\r\n * bytes.\r\n */\r\n writeUint32(value) {\r\n this.ensureAvailable(4);\r\n this._data.setUint32(this.offset, value, this.littleEndian);\r\n this.offset += 4;\r\n this._updateLastWrittenByte();\r\n return this;\r\n }\r\n /**\r\n * Write `value` as a 32-bit floating number and move pointer forward by 4\r\n * bytes.\r\n */\r\n writeFloat32(value) {\r\n this.ensureAvailable(4);\r\n this._data.setFloat32(this.offset, value, this.littleEndian);\r\n this.offset += 4;\r\n this._updateLastWrittenByte();\r\n return this;\r\n }\r\n /**\r\n * Write `value` as a 64-bit floating number and move pointer forward by 8\r\n * bytes.\r\n */\r\n writeFloat64(value) {\r\n this.ensureAvailable(8);\r\n this._data.setFloat64(this.offset, value, this.littleEndian);\r\n this.offset += 8;\r\n this._updateLastWrittenByte();\r\n return this;\r\n }\r\n /**\r\n * Write the charCode of `str`'s first character as an 8-bit unsigned integer\r\n * and move pointer forward by 1 byte.\r\n */\r\n writeChar(str) {\r\n return this.writeUint8(str.charCodeAt(0));\r\n }\r\n /**\r\n * Write the charCodes of all `str`'s characters as 8-bit unsigned integers\r\n * and move pointer forward by `str.length` bytes.\r\n */\r\n writeChars(str) {\r\n for (let i = 0; i < str.length; i++) {\r\n this.writeUint8(str.charCodeAt(i));\r\n }\r\n return this;\r\n }\r\n /**\r\n * UTF-8 encode and write `str` to the current pointer offset and move pointer\r\n * forward according to the encoded length.\r\n */\r\n writeUtf8(str) {\r\n return this.writeBytes(encode(str));\r\n }\r\n /**\r\n * Export a Uint8Array view of the internal buffer.\r\n * The view starts at the byte offset and its length\r\n * is calculated to stop at the last written byte or the original length.\r\n */\r\n toArray() {\r\n return new Uint8Array(this.buffer, this.byteOffset, this.lastWrittenByte);\r\n }\r\n /**\r\n * Update the last written byte offset\r\n * @private\r\n */\r\n _updateLastWrittenByte() {\r\n if (this.offset > this.lastWrittenByte) {\r\n this.lastWrittenByte = this.offset;\r\n }\r\n }\r\n}\r\n//# sourceMappingURL=IOBuffer.js.map","/* eslint-disable no-control-regex */\nimport { equidistantArray, getSubFlagParameters } from './utility';\n\n/**\n * Parses the subheader of the current subfile\n *\n * @export\n * @param {object} buffer SPC buffer\n * @return {object} Current subfile's subheader\n */\nexport function subHeader(buffer) {\n const subHeader = {};\n subHeader.parameters = getSubFlagParameters(buffer.readUint8());\n subHeader.exponentY = buffer.readInt8();\n subHeader.indexNumber = buffer.readUint16();\n subHeader.startingZ = buffer.readFloat32();\n subHeader.endingZ = buffer.readFloat32();\n subHeader.noiseValue = buffer.readFloat32();\n subHeader.numberPoints = buffer.readUint32();\n subHeader.numberCoAddedScans = buffer.readUint32();\n subHeader.wAxisValue = buffer.readFloat32();\n subHeader.reserved = buffer.readChars(4).trim().replace(/\\x00/g, '');\n return subHeader;\n}\n\n/**\n * Reads the data block of the SPC file\n *\n * @export\n * @param {object} buffer spc buffer\n * @param {object} mainHeader main header\n * @return {array} Array containing the spectra\n */\nexport function readDataBlock(buffer, mainHeader) {\n let x;\n let y;\n let spectra = [];\n\n if (!mainHeader.parameters.xyxy && mainHeader.xy) {\n x = new Float32Array(mainHeader.numberPoints);\n for (let i = 0; i < mainHeader.numberPoints; i++) {\n x[i] = buffer.readFloat32();\n }\n } else if (!mainHeader.parameters.xy) {\n x = equidistantArray(\n mainHeader.startingX,\n mainHeader.endingX,\n mainHeader.numberPoints,\n );\n }\n let spectrum;\n for (\n let i = 0;\n i < mainHeader.spectra ||\n (mainHeader.fileVersion === 0x4d &&\n buffer.offset + mainHeader.numberPoints < buffer.length);\n i++\n ) {\n spectrum = {};\n spectrum.meta = subHeader(buffer);\n if (mainHeader.parameters.xyxy) {\n x = new Float32Array(spectrum.meta.numberPoints);\n for (let j = 0; j < spectrum.meta.numberPoints; j++) {\n x[j] = buffer.readFloat32();\n }\n }\n if (spectrum.meta.exponentY === 0) {\n spectrum.meta.exponentY = mainHeader.exponentY;\n }\n const yFactor = Math.pow(\n 2,\n spectrum.meta.exponentY -\n (mainHeader.parameters.y16BitPrecision ? 16 : 32),\n );\n\n const nbPoints = spectrum.meta.numberPoints\n ? spectrum.meta.numberPoints\n : mainHeader.numberPoints;\n\n if (mainHeader.parameters.y16BitPrecision) {\n y = new Float32Array(nbPoints);\n for (let j = 0; j < nbPoints; j++) {\n y[j] = buffer.readInt16() * yFactor;\n }\n } else {\n y = new Float32Array(nbPoints);\n for (let j = 0; j < nbPoints; j++) {\n if (mainHeader.fileVersion === 0x4d) {\n y[j] =\n ((buffer.readUint8() << 16) +\n (buffer.readInt8() << 24) +\n (buffer.readUint8() << 0) +\n (buffer.readUint8() << 8)) *\n yFactor;\n } else {\n if (spectrum.meta.exponentY !== -128) {\n y[j] = buffer.readInt32() * yFactor;\n } else {\n y[j] = buffer.readFloat32();\n }\n }\n }\n }\n const xAxis = mainHeader.xUnitsType.match(\n /(?