Open EdwardZZZ opened 6 years ago
最后一位不操作,如果小于128停止读取,如果最后一位大于128则为负数,因此int64最长长度还是 9 个字节
const Range = {
16: [0x7fff, -0x8000, 2],
32: [0x7fffffff, -0x80000000, 4],
64: [0x7fffffffffffffff, -0x8000000000000000, 8],
};
readVarInt64(): string {
const [, , len] = Range[64];
let i = 0;
let b = this.buffer[this.pos + i++];
let result = Long.fromValue(b & 0x7f);
while (i < len + 1) {
if ((b & 0x80) !== 0) {
b = this.buffer[this.pos + i++];
if (i === 9) {
result = result.or(Long.fromValue(b).shiftLeft(56));
} else {
result = result.or(Long.fromValue(b & 0x7f).shiftLeft(7 * (i - 1)));
}
} else {
break;
}
}
this.pos += i;
return result.toString();
}
toBytes64LE(value: number | string): number[] {
if (value >= 0 && value < 128) return [+value];
const buf = [];
const longValue = Long.fromValue(value);
let r = longValue;
while (+r !== 0 && buf.length < 9) {
r = longValue.shiftRightUnsigned(7 * buf.length);
if ((r.gt(0x7f) || longValue.isNegative()) && buf.length < 8) {
buf.push(r.and(0x7f).or(0x80).toInt());
} else {
buf.push(r.toInt());
break;
}
}
return buf;
}
toBytesLE(value: number, n: number): number[] {
if (value >= 0 && value < 128) return [value];
const [, , len] = Range[n];
const buf = [];
let r = value;
while (r !== 0 && buf.length < len + 1) {
r = value >>> 7 * buf.length;
if ((r > 0x7f || value < 0) && buf.length < len) {
buf.push((r & 0x7f) | 0x80);
} else {
buf.push(n === 32 ? r : value >> 7 * buf.length);
break;
}
}
return buf;
}
const Range = {
16: [0x7fff, -0x8000, 2],
32: [0x7fffffff, -0x80000000, 4],
64: [0x7fffffffffffffff, -0x8000000000000000, 8],
};
readVarInt64(): string {
const [, , len] = Range[64];
let i = 0;
let b = this.buffer[this.pos + i++];
let result = BigInt(b & 0x7f);
while (i < len + 1) {
if ((b & 0x80) !== 0) {
b = this.buffer[this.pos + i++];
if (i === 9) {
result |= BigInt(b > 7 ? b - 256 : b) << 56n;
} else {
result |= BigInt(b & 0x7f) << BigInt(7 * (i - 1));
}
} else {
break;
}
}
this.pos += i;
return result.toString();
}
toBytes64LE(value: number | string): number[] {
if (value >= 0 && value < 128) return [+value];
const buff = [];
const longValue = BigInt(value);
let r = longValue;
while (r !== 0n && buff.length < 9) {
r = longValue >> BigInt(7 * buff.length);
if ((r > 0x7f || longValue < 0n ) && buff.length < 8) {
buff.push(Number(r & BigInt(0x7f) | BigInt(0x80)));
} else {
buff.push(Number(r) & 0xff);
break;
}
}
return buf;
}
toBytesLE(value: number, n: number): number[] {
if (value >= 0 && value < 128) return [value];
const [, , len] = Range[n];
const buf = [];
let r = value;
while (r !== 0 && buf.length < len + 1) {
r = value >>> 7 * buf.length;
if ((r > 0x7f || value < 0) && buf.length < len) {
buf.push((r & 0x7f) | 0x80);
} else {
buf.push(n === 32 ? r : value >> 7 * buf.length);
break;
}
}
return buf;
}
/**
* 扩展64位长整型写操作
* **/
function writeInt(type = 'LE', value, offset = 0, noAssert) {
if (!noAssert) {
const [max, min, ext] = range[64];
checkInt(this, value, offset, ext, max, min);
}
const val = bigInt(value).toArray(256);
let arr = val.value;
arr = type === 'LE' ? arr.reverse() : arr;
if(arr.length > 0){
for(let i = 0; i < 8; i++){
if ( val.isNegative ) {
if ( (type === 'LE' && i === 0) || (type === 'BE' && i === 7) ) {
this[ offset + i] = -arr[i] & 0xff;
} else {
this[ offset + i] = ~arr[i] & 0xff;
}
} else {
this[ offset + i] = arr[i];
}
}
}
return offset + 8;
}
function readInt(type = 'LE', offset = 0, noAssert) {
if (!noAssert)
checkOffset(offset, 8, this.length);
const signNum = type === 'LE' ? this[offset + 7] : this[offset];
const isNegative = signNum > 0x7f;
let arr = [];
for(let i =0; i < 8; i++){
if (isNegative) {
if ( (type === 'LE' && i === 0) || (type === 'BE' && i === 7) ) {
arr[i] = -this[ offset + i] & 0xff;
} else {
arr[i] = ~this[ offset + i] & 0xff;
}
} else {
arr[i] = this[offset + i];
}
}
this.__readOffset = offset + 8;
arr = type === 'LE' ? arr.reverse() : arr;
return bigInt.fromArray(arr, 256, isNegative).toString();
}
/**
* 写
* @param {*} type
* @param {*} n
* @param {*} value
* @param {*} offset
* @param {*} noAssert
*/
function writeVarInt(type = 'LE', n = 16, value, offset = 0, noAssert) {
const [max, min, ext] = range[n];
if (noAssert) {
checkInt(this, value, offset, ext, max, min);
}
let arr = bigInt(value).toArray(128);
let bytes = arr.value;
if (bytes.length > this.length || bytes.length > ext + 1) {
throw new RangeError(`ERR_INDEX_OUT_OF_RANGE int${n} value: ${value}`);
}
bytes = type === 'LE' ? bytes.reverse() : bytes;
if (arr.isNegative) {
bytes = bytes.concat(Array(ext + 1 - bytes.length).fill(0))
}
let _offset = offset;
bytes.forEach((byte, index) => {
// 处理用于判断首尾
if (arr.isNegative) {
if ((type === 'BE' && index === bytes.length - 1)
|| (type === 'LE' && index === 0)) {
this[_offset++] = -byte;
} else if ( n === 32 && byte < 0xf &&
( (type === 'BE' && index === 0) || (type === 'LE' && index === bytes.length - 1)) ) {
this[_offset++] = ~byte & 0xf;
} else {
this[_offset++] = ~byte;
}
} else {
if ((type === 'BE' && index === 0)
|| (type === 'LE' && index === bytes.length - 1)) {
this[_offset++] = byte;
} else {
this[_offset++] = byte | 0x80;
}
}
});
return _offset;
};
/**
* 读
* @param {*} type
* @param {*} offset
* @param {*} noAssert
*/
function readVarInt(type = 'LE', n = 16, offset = 0, noAssert) {
let _offset = offset;
if (this.length - _offset <= 0) {
return 0;
}
let arr = [];
/**
* 标记count,用于计算优化字节长度的限制,否则while循环有可能一直运算下去
* 当(count * 8) === n 时候,表示最大长度;分别是short:3、integer:5、long:9
* **/
let count = 0;
while (true) {
let b = this[_offset++];
if (b === undef) break;
if ((b & 0x80) !== 0x80 || (count << 3) === n ) {
if (type === 'LE') {
arr.push(b);
break;
} else {
if (offset + 1 === _offset) {
arr.push(b);
continue;
}
break;
}
}
arr.push(b);
count++;
}
if (type === 'LE') {
arr = arr.reverse();
}
// 是否是负数
const [max, min, ext] = range[n];
let isNegative = false;
if (count === 2 || count === 8) {
isNegative = (arr[0] & 0x80) !== 0;
}
if (count === 4 && n === 32) {
isNegative = arr[0] > 7;
}
// 处理返回新的数组
arr = arr.map((n, index) => {
if (isNegative) {
if (index === arr.length - 1) return -n & 0x7f;
if (index === 0 && count === 4) return ~n & 0xf;
return ~n & 0x7f
}
if (index === 0) return n;
return n & 0x7f;
});
this.__readOffset = _offset;
return (isNegative ? '-' : '') + bigInt.fromArray(arr, 128).toString();
}
const shortArr = [
[0, [0]],
[-1, [-1, -1, -1]],
[1, [1]],
[-0x80, [-128, -1, -1]],
[0x7f, [127]],
[0x80, [-128, 1]],
[-0x8000, [-128, -128, -2]],
[0x7fff, [-1, -1, 1]],
];
const intArr = [
[0, [0]],
[-1, [-1, -1, -1, -1, 15]],
[1, [1]],
[-0x80, [-128, -1, -1, -1, 15]],
[0x7f, [127]],
[0x80, [-128, 1]],
[-0x8000, [-128, -128, -2, -1, 15]],
[0x7fff, [-1, -1, 1]],
[-0x80000000, [-128, -128, -128, -128, 8]],
[0x7fffffff, [-1, -1, -1, -1, 7]],
];
const longArr = [
[0, [0]],
[-1, [-1, -1, -1, -1, -1, -1, -1, -1, -1]],
[1, [1]],
[-0x80, [-128, -1, -1, -1, -1, -1, -1, -1, -1]],
[0x7f, [127]],
[0x80, [-128, 1]],
[-0x8000, [-128, -128, -2, -1, -1, -1, -1, -1, -1]],
[0x7fff, [-1, -1, 1]],
[-0x80000000, [-128, -128, -128, -128, -8, -1, -1, -1, -1]],
[0x7fffffff, [-1, -1, -1, -1, 7]],
['-9223372036854775808', [-128, -128, -128, -128, -128, -128, -128, -128, -128]],
['9223372036854775807', [-1, -1, -1, -1, -1, -1, -1, -1, 127]],
];