mirror of
https://github.com/gamedig/node-gamedig.git
synced 2024-11-18 09:40:38 +01:00
171 lines
5 KiB
JavaScript
171 lines
5 KiB
JavaScript
const Iconv = require('iconv-lite'),
|
|
Long = require('long'),
|
|
Core = require('../protocols/core'),
|
|
Buffer = require('buffer'),
|
|
Varint = require('varint');
|
|
|
|
function readUInt64BE(buffer,offset) {
|
|
const high = buffer.readUInt32BE(offset);
|
|
const low = buffer.readUInt32BE(offset+4);
|
|
return new Long(low,high,true);
|
|
}
|
|
function readUInt64LE(buffer,offset) {
|
|
const low = buffer.readUInt32LE(offset);
|
|
const high = buffer.readUInt32LE(offset+4);
|
|
return new Long(low,high,true);
|
|
}
|
|
|
|
class Reader {
|
|
/**
|
|
* @param {Core} query
|
|
* @param {Buffer} buffer
|
|
**/
|
|
constructor(query,buffer) {
|
|
this.defaultEncoding = query.options.encoding || query.encoding;
|
|
this.defaultDelimiter = query.delimiter;
|
|
this.defaultByteOrder = query.byteorder;
|
|
this.buffer = buffer;
|
|
this.i = 0;
|
|
}
|
|
|
|
offset() {
|
|
return this.i;
|
|
}
|
|
|
|
skip(i) {
|
|
this.i += i;
|
|
}
|
|
|
|
pascalString(bytesForSize, adjustment=0) {
|
|
const length = this.uint(bytesForSize) + adjustment;
|
|
return this.string(length);
|
|
}
|
|
|
|
string(arg) {
|
|
let encoding = this.defaultEncoding;
|
|
let length = null;
|
|
let delimiter = this.defaultDelimiter;
|
|
|
|
if(typeof arg === 'string') delimiter = arg;
|
|
else if(typeof arg === 'number') length = arg;
|
|
else if(typeof arg === 'object') {
|
|
if ('encoding' in arg) encoding = arg.encoding;
|
|
if ('length' in arg) length = arg.length;
|
|
if ('delimiter' in arg) delimiter = arg.delimiter;
|
|
}
|
|
|
|
if(encoding === 'latin1') encoding = 'win1252';
|
|
|
|
const start = this.i;
|
|
let end = start;
|
|
if(length === null) {
|
|
// terminated by the delimiter
|
|
let delim = delimiter;
|
|
if (typeof delim === 'string') delim = delim.charCodeAt(0);
|
|
while (true) {
|
|
if (end >= this.buffer.length) {
|
|
end = this.buffer.length;
|
|
break;
|
|
}
|
|
if (this.buffer.readUInt8(end) === delim) break;
|
|
end++;
|
|
}
|
|
this.i = end + 1;
|
|
} else if (length <= 0) {
|
|
return '';
|
|
} else {
|
|
end = start+length;
|
|
if(end >= this.buffer.length) {
|
|
end = this.buffer.length;
|
|
}
|
|
this.i = end;
|
|
}
|
|
|
|
const slice = this.buffer.slice(start, end);
|
|
const enc = encoding;
|
|
if(enc === 'utf8' || enc === 'ucs2' || enc === 'binary') {
|
|
return slice.toString(enc);
|
|
} else {
|
|
return Iconv.decode(slice,enc);
|
|
}
|
|
}
|
|
|
|
int(bytes) {
|
|
let r = 0;
|
|
if(this.remaining() >= bytes) {
|
|
if(this.defaultByteOrder === 'be') {
|
|
if(bytes === 1) r = this.buffer.readInt8(this.i);
|
|
else if(bytes === 2) r = this.buffer.readInt16BE(this.i);
|
|
else if(bytes === 4) r = this.buffer.readInt32BE(this.i);
|
|
} else {
|
|
if(bytes === 1) r = this.buffer.readInt8(this.i);
|
|
else if(bytes === 2) r = this.buffer.readInt16LE(this.i);
|
|
else if(bytes === 4) r = this.buffer.readInt32LE(this.i);
|
|
}
|
|
}
|
|
this.i += bytes;
|
|
return r;
|
|
}
|
|
|
|
/** @returns {number} */
|
|
uint(bytes) {
|
|
let r = 0;
|
|
if(this.remaining() >= bytes) {
|
|
if(this.defaultByteOrder === 'be') {
|
|
if(bytes === 1) r = this.buffer.readUInt8(this.i);
|
|
else if(bytes === 2) r = this.buffer.readUInt16BE(this.i);
|
|
else if(bytes === 4) r = this.buffer.readUInt32BE(this.i);
|
|
else if(bytes === 8) r = readUInt64BE(this.buffer,this.i).toString();
|
|
} else {
|
|
if(bytes === 1) r = this.buffer.readUInt8(this.i);
|
|
else if(bytes === 2) r = this.buffer.readUInt16LE(this.i);
|
|
else if(bytes === 4) r = this.buffer.readUInt32LE(this.i);
|
|
else if(bytes === 8) r = readUInt64LE(this.buffer,this.i).toString();
|
|
}
|
|
}
|
|
this.i += bytes;
|
|
return r;
|
|
}
|
|
|
|
float() {
|
|
let r = 0;
|
|
if(this.remaining() >= 4) {
|
|
if(this.defaultByteOrder === 'be') r = this.buffer.readFloatBE(this.i);
|
|
else r = this.buffer.readFloatLE(this.i);
|
|
}
|
|
this.i += 4;
|
|
return r;
|
|
}
|
|
|
|
varint() {
|
|
const out = Varint.decode(this.buffer, this.i);
|
|
this.i += Varint.decode.bytes;
|
|
return out;
|
|
}
|
|
|
|
/** @returns Buffer */
|
|
part(bytes) {
|
|
let r;
|
|
if(this.remaining() >= bytes) {
|
|
r = this.buffer.slice(this.i,this.i+bytes);
|
|
} else {
|
|
r = Buffer.from([]);
|
|
}
|
|
this.i += bytes;
|
|
return r;
|
|
}
|
|
|
|
remaining() {
|
|
return this.buffer.length-this.i;
|
|
}
|
|
|
|
rest() {
|
|
return this.buffer.slice(this.i);
|
|
}
|
|
|
|
done() {
|
|
return this.i >= this.buffer.length;
|
|
}
|
|
}
|
|
|
|
module.exports = Reader;
|