diff options
Diffstat (limited to 'node_modules/xterm/src/common/parser/Params.ts')
-rw-r--r-- | node_modules/xterm/src/common/parser/Params.ts | 229 |
1 files changed, 229 insertions, 0 deletions
diff --git a/node_modules/xterm/src/common/parser/Params.ts b/node_modules/xterm/src/common/parser/Params.ts new file mode 100644 index 0000000..7071453 --- /dev/null +++ b/node_modules/xterm/src/common/parser/Params.ts @@ -0,0 +1,229 @@ +/** + * Copyright (c) 2019 The xterm.js authors. All rights reserved. + * @license MIT + */ +import { IParams, ParamsArray } from 'common/parser/Types'; + +// max value supported for a single param/subparam (clamped to positive int32 range) +const MAX_VALUE = 0x7FFFFFFF; +// max allowed subparams for a single sequence (hardcoded limitation) +const MAX_SUBPARAMS = 256; + +/** + * Params storage class. + * This type is used by the parser to accumulate sequence parameters and sub parameters + * and transmit them to the input handler actions. + * + * NOTES: + * - params object for action handlers is borrowed, use `.toArray` or `.clone` to get a copy + * - never read beyond `params.length - 1` (likely to contain arbitrary data) + * - `.getSubParams` returns a borrowed typed array, use `.getSubParamsAll` for cloned sub params + * - hardcoded limitations: + * - max. value for a single (sub) param is 2^31 - 1 (greater values are clamped to that) + * - max. 256 sub params possible + * - negative values are not allowed beside -1 (placeholder for default value) + * + * About ZDM (Zero Default Mode): + * ZDM is not orchestrated by this class. If the parser is in ZDM, + * it should add 0 for empty params, otherwise -1. This does not apply + * to subparams, empty subparams should always be added with -1. + */ +export class Params implements IParams { + // params store and length + public params: Int32Array; + public length: number; + + // sub params store and length + protected _subParams: Int32Array; + protected _subParamsLength: number; + + // sub params offsets from param: param idx --> [start, end] offset + private _subParamsIdx: Uint16Array; + private _rejectDigits: boolean; + private _rejectSubDigits: boolean; + private _digitIsSub: boolean; + + /** + * Create a `Params` type from JS array representation. + */ + public static fromArray(values: ParamsArray): Params { + const params = new Params(); + if (!values.length) { + return params; + } + // skip leading sub params + for (let i = (Array.isArray(values[0])) ? 1 : 0; i < values.length; ++i) { + const value = values[i]; + if (Array.isArray(value)) { + for (let k = 0; k < value.length; ++k) { + params.addSubParam(value[k]); + } + } else { + params.addParam(value); + } + } + return params; + } + + /** + * @param maxLength max length of storable parameters + * @param maxSubParamsLength max length of storable sub parameters + */ + constructor(public maxLength: number = 32, public maxSubParamsLength: number = 32) { + if (maxSubParamsLength > MAX_SUBPARAMS) { + throw new Error('maxSubParamsLength must not be greater than 256'); + } + this.params = new Int32Array(maxLength); + this.length = 0; + this._subParams = new Int32Array(maxSubParamsLength); + this._subParamsLength = 0; + this._subParamsIdx = new Uint16Array(maxLength); + this._rejectDigits = false; + this._rejectSubDigits = false; + this._digitIsSub = false; + } + + /** + * Clone object. + */ + public clone(): Params { + const newParams = new Params(this.maxLength, this.maxSubParamsLength); + newParams.params.set(this.params); + newParams.length = this.length; + newParams._subParams.set(this._subParams); + newParams._subParamsLength = this._subParamsLength; + newParams._subParamsIdx.set(this._subParamsIdx); + newParams._rejectDigits = this._rejectDigits; + newParams._rejectSubDigits = this._rejectSubDigits; + newParams._digitIsSub = this._digitIsSub; + return newParams; + } + + /** + * Get a JS array representation of the current parameters and sub parameters. + * The array is structured as follows: + * sequence: "1;2:3:4;5::6" + * array : [1, 2, [3, 4], 5, [-1, 6]] + */ + public toArray(): ParamsArray { + const res: ParamsArray = []; + for (let i = 0; i < this.length; ++i) { + res.push(this.params[i]); + const start = this._subParamsIdx[i] >> 8; + const end = this._subParamsIdx[i] & 0xFF; + if (end - start > 0) { + res.push(Array.prototype.slice.call(this._subParams, start, end)); + } + } + return res; + } + + /** + * Reset to initial empty state. + */ + public reset(): void { + this.length = 0; + this._subParamsLength = 0; + this._rejectDigits = false; + this._rejectSubDigits = false; + this._digitIsSub = false; + } + + /** + * Add a parameter value. + * `Params` only stores up to `maxLength` parameters, any later + * parameter will be ignored. + * Note: VT devices only stored up to 16 values, xterm seems to + * store up to 30. + */ + public addParam(value: number): void { + this._digitIsSub = false; + if (this.length >= this.maxLength) { + this._rejectDigits = true; + return; + } + if (value < -1) { + throw new Error('values lesser than -1 are not allowed'); + } + this._subParamsIdx[this.length] = this._subParamsLength << 8 | this._subParamsLength; + this.params[this.length++] = value > MAX_VALUE ? MAX_VALUE : value; + } + + /** + * Add a sub parameter value. + * The sub parameter is automatically associated with the last parameter value. + * Thus it is not possible to add a subparameter without any parameter added yet. + * `Params` only stores up to `subParamsLength` sub parameters, any later + * sub parameter will be ignored. + */ + public addSubParam(value: number): void { + this._digitIsSub = true; + if (!this.length) { + return; + } + if (this._rejectDigits || this._subParamsLength >= this.maxSubParamsLength) { + this._rejectSubDigits = true; + return; + } + if (value < -1) { + throw new Error('values lesser than -1 are not allowed'); + } + this._subParams[this._subParamsLength++] = value > MAX_VALUE ? MAX_VALUE : value; + this._subParamsIdx[this.length - 1]++; + } + + /** + * Whether parameter at index `idx` has sub parameters. + */ + public hasSubParams(idx: number): boolean { + return ((this._subParamsIdx[idx] & 0xFF) - (this._subParamsIdx[idx] >> 8) > 0); + } + + /** + * Return sub parameters for parameter at index `idx`. + * Note: The values are borrowed, thus you need to copy + * the values if you need to hold them in nonlocal scope. + */ + public getSubParams(idx: number): Int32Array | null { + const start = this._subParamsIdx[idx] >> 8; + const end = this._subParamsIdx[idx] & 0xFF; + if (end - start > 0) { + return this._subParams.subarray(start, end); + } + return null; + } + + /** + * Return all sub parameters as {idx: subparams} mapping. + * Note: The values are not borrowed. + */ + public getSubParamsAll(): {[idx: number]: Int32Array} { + const result: {[idx: number]: Int32Array} = {}; + for (let i = 0; i < this.length; ++i) { + const start = this._subParamsIdx[i] >> 8; + const end = this._subParamsIdx[i] & 0xFF; + if (end - start > 0) { + result[i] = this._subParams.slice(start, end); + } + } + return result; + } + + /** + * Add a single digit value to current parameter. + * This is used by the parser to account digits on a char by char basis. + */ + public addDigit(value: number): void { + let length; + if (this._rejectDigits + || !(length = this._digitIsSub ? this._subParamsLength : this.length) + || (this._digitIsSub && this._rejectSubDigits) + ) { + return; + } + + const store = this._digitIsSub ? this._subParams : this.params; + const cur = store[length - 1]; + store[length - 1] = ~cur ? Math.min(cur * 10 + value, MAX_VALUE) : value; + } +} |