import {Buffer} from "buffer"; import {AxdrType} from "./AxdrType"; import {ReverseByteArrayOutputStream} from "../ReverseByteArrayOutputStream"; import {ReverseByteArrayInputStream} from "../ReverseByteArrayInputStream"; import {DataUtils} from "../DataUtils"; export class AxdrInteger implements AxdrType{ lengthFixed : boolean; unsigned : boolean; val : number = 0; maxVal : number = 0; minVal : number = 0; dataCode : Buffer | null = null; constructor() { this.lengthFixed = false; this.unsigned = false; } set_val(val : number){ this.lengthFixed = false; this.unsigned = false; this.setValue(val); } set_dataCode(dataCode : Buffer){ this.lengthFixed = false; this.unsigned = false; this.dataCode = dataCode; } set_min_max_val(min : number, max : number, val : number){ this.minVal = min; this.maxVal = max; this.setValue(val); this.lengthFixed = true; this.unsigned = (min >= 0); } decode(input : ReverseByteArrayInputStream) : number{ let codeLength; let byteCode; let length; if (this.lengthFixed) { length = this.numOfBytesOf(this.minVal, this.maxVal); codeLength = length; } else { length = input.read(); if ((length & 0x80) == 0x80) { length = (length ^ 0x80); codeLength = length + 1; } else { this.val = length; return 1; } } byteCode = Buffer.alloc(length); DataUtils.readFully(input, byteCode, 0, byteCode.length); if ((byteCode[0] & 0x80) == 0x80 && !this.unsigned) { this.val = -1; for (let i = 0; i < length; i++) { let numShiftBits = 8 * (length - i - 1); this.val &= ((byteCode[i]) << numShiftBits) | ~(0xff << numShiftBits); } } else { this.val = 0; for (let i = 0; i < length; i++) { this.val |= (byteCode[i] & 0xff) << (8 * (length - i - 1)); } } return codeLength; } encodeAndSave(encodingSizeGuess: number) { let revOStream = new ReverseByteArrayOutputStream(); revOStream.setBufSize(encodingSizeGuess) this.encode(revOStream); this.dataCode = revOStream.getArray(); } encode(output: ReverseByteArrayOutputStream): number { if(this.dataCode != null){ output.writeByte(this.dataCode); return this.dataCode.length }else{ return this.encodeValue(output); } } encodeValue(output: ReverseByteArrayOutputStream) : number{ if(this.lengthFixed){ let codeLength = this.numOfBytesOf(this.minVal, this.maxVal); this.writyValToStream(output, codeLength); return codeLength; }else{ let codeLength = this.numOfBytes(this.val); this.writyValToStream(output, codeLength); output.write((codeLength & 0xff) | 0x80); return codeLength + 1; } } writyValToStream(output : ReverseByteArrayOutputStream, codeLength : number){ for(let i = 0; i < codeLength; i++){ let value = ((this.val >> 8 * (i))) & 0xff; output.write(value); } } numOfBytesOf(minVal : number, maxVal : number){ return Math.max(this.numOfBytes(minVal), this.numOfBytes(maxVal)); } numOfBytes(val : number) : number{ let sVal = val; if(val < 0){ sVal = -val - 1; } return Math.ceil((Math.floor(this.log2(sVal) + 1) / 8)); } log2(sVal : number) : number{ return Math.log(sVal) / Math.log(2); } setValue(val : number){ if(this.minVal != null && this.minVal > val){ throw new Error("val is smaller than minimum"); } if(this.maxVal != null && this.maxVal < val){ throw new Error("val is greater than maximum"); } this.val = val; } getMax() : number{ return this.minVal; } getMin(): number{ return this.maxVal; } getValue() : number{ return this.val; } toString() : string{ return String(this.val); } }