UNPKG

limber-firebird-client

Version:

Cliente JavaScript/Typescrypt para Node.js de acesso a banco de dados Firebird charset ISO8859_1 e UTF8

515 lines (419 loc) 12.4 kB
var Long = require('long'); function align(n) { return (n + 3) & ~3; } /*************************************** * * BLR Writer * ***************************************/ const MAX_STRING_SIZE = 255; var BlrWriter = exports.BlrWriter = function (size) { this.buffer = Buffer.alloc(size || 32); this.pos = 0; }; BlrWriter.prototype.addByte = function (b) { this.ensure(1); this.buffer.writeUInt8(b, this.pos); this.pos++; }; BlrWriter.prototype.addShort = function (b) { this.ensure(1); this.buffer.writeInt8(b, this.pos); this.pos++; }; BlrWriter.prototype.addSmall = function (b) { this.ensure(2); this.buffer.writeInt16LE(b, this.pos); this.pos += 2; }; BlrWriter.prototype.addWord = function (b) { this.ensure(2); this.buffer.writeUInt16LE(b, this.pos); this.pos += 2; }; BlrWriter.prototype.addInt32 = function (b) { this.ensure(4); this.buffer.writeUInt32LE(b, this.pos); this.pos += 4; }; BlrWriter.prototype.addByteInt32 = function (c, b) { this.addByte(c); this.ensure(4); this.buffer.writeUInt32LE(b, this.pos); this.pos += 4; }; BlrWriter.prototype.addNumeric = function (c, v) { if (v < 256) { this.ensure(3); this.buffer.writeUInt8(c, this.pos); this.pos++; this.buffer.writeUInt8(1, this.pos); this.pos++; this.buffer.writeUInt8(v, this.pos); this.pos++; return; } this.ensure(6); this.buffer.writeUInt8(c, this.pos); this.pos++; this.buffer.writeUInt8(4, this.pos); this.pos++; this.buffer.writeInt32BE(v, this.pos); this.pos += 4; }; BlrWriter.prototype.addBytes = function (b) { this.ensure(b.length); for (var i = 0, length = b.length; i < length; i++) { this.buffer.writeUInt8(b[i], this.pos); this.pos++; } }; BlrWriter.prototype.addString = function (c, s, encoding) { this.addByte(c); var len = Buffer.byteLength(s, encoding); if (len > MAX_STRING_SIZE) { throw new Error('blr string is too big'); } this.ensure(len + 1); this.buffer.writeUInt8(len, this.pos); this.pos++; this.buffer.write(s, this.pos, len, encoding); this.pos += len; }; BlrWriter.prototype.addBuffer = function (b) { this.addSmall(b.length); this.ensure(b.length); b.copy(this.buffer, this.pos); this.pos += b.length; }; BlrWriter.prototype.addString2 = function (c, s, encoding) { this.addByte(c); var len = Buffer.byteLength(s, encoding); if (len > MAX_STRING_SIZE * MAX_STRING_SIZE) { throw new Error('blr string is too big'); } this.ensure(len + 2); this.buffer.writeUInt16LE(len, this.pos); this.pos += 2; this.buffer.write(s, this.pos, len, encoding); this.pos += len; }; BlrWriter.prototype.addMultiblockPart = function (c, s, encoding) { var buff = Buffer.from(s, encoding); var remaining = buff.length; var step = 0; while (remaining > 0) { var toWrite = Math.min(remaining, 254); this.addByte(c); this.addByte(toWrite + 1); this.addByte(step); buff.copy(this.buffer, this.pos, step * 254, (step * 254) + toWrite); step++; remaining -= toWrite; this.pos += toWrite; } }; /*************************************** * * BLR Reader * ***************************************/ var BlrReader = exports.BlrReader = function (buffer) { this.buffer = buffer; this.pos = 0; }; BlrReader.prototype.readByteCode = function () { return this.buffer.readUInt8(this.pos++); }; BlrReader.prototype.readInt32 = function () { var value = this.buffer.readUInt32LE(this.pos); this.pos += 4; return value; } BlrReader.prototype.readInt = function () { var len = this.buffer.readUInt16LE(this.pos); this.pos += 2; var value; switch (len) { case 1: value = this.buffer.readInt8(this.pos); break; case 2: value = this.buffer.readInt16LE(this.pos); break; case 4: value = this.buffer.readInt32LE(this.pos) } this.pos += len; return value; }; BlrReader.prototype.readString = function (encoding) { var len = this.buffer.readUInt16LE(this.pos); var str; this.pos += 2; if (len <= 0) { return ''; } str = this.buffer.toString(encoding, this.pos, this.pos + len); this.pos += len; return str; }; BlrReader.prototype.readBuffer = function (encoding) { let len = this.buffer.readUInt16LE(this.pos); this.pos += 2; if (len <= 0) { return Buffer.alloc(0); } let ret = new Buffer(len); this.buffer.copy(ret, 0, this.pos, this.pos + len); this.pos += len; return ret; }; BlrReader.prototype.readSegment = function () { var ret, tmp; var len = this.buffer.readUInt16LE(this.pos); this.pos += 2; while (len > 0) { if (ret) { tmp = ret; ret = Buffer.alloc(tmp.length + len); tmp.copy(ret); this.buffer.copy(ret, tmp.length, this.pos, this.pos + len); } else { ret = Buffer.alloc(len); this.buffer.copy(ret, 0, this.pos, this.pos + len); } this.pos += len; if (this.pos === this.buffer.length) { break; } len = this.buffer.readUInt16LE(this.pos); this.pos += 2; } return ret ? ret : Buffer.alloc(0); }; /*************************************** * * XDR Writer * ***************************************/ var XdrWriter = exports.XdrWriter = function (size) { this.buffer = Buffer.alloc(size || 32); this.pos = 0; }; XdrWriter.prototype.ensure = BlrWriter.prototype.ensure = function (len) { var newlen = this.buffer.length; while (newlen < this.pos + len) { newlen *= 2 } if (this.buffer.length >= newlen) { return; } var b = Buffer.alloc(newlen); this.buffer.copy(b); delete (this.buffer); this.buffer = b; }; XdrWriter.prototype.addInt = function (value) { this.ensure(4); this.buffer.writeInt32BE(value, this.pos); this.pos += 4; }; XdrWriter.prototype.addInt64 = function (value) { this.ensure(8); var l = Long.fromNumber(value); this.buffer.writeInt32BE(l.high, this.pos); this.pos += 4; this.buffer.writeInt32BE(l.low, this.pos); this.pos += 4; }; XdrWriter.prototype.addUInt = function (value) { this.ensure(4); this.buffer.writeUInt32BE(value, this.pos); this.pos += 4; }; XdrWriter.prototype.addString = function (s, encoding) { var len = Buffer.byteLength(s, encoding); var alen = align(len); this.ensure(alen + 4); this.buffer.writeInt32BE(len, this.pos); this.pos += 4; this.buffer.write(s, this.pos, len, encoding); this.pos += alen; }; XdrWriter.prototype.addText = function (s, encoding) { var len = Buffer.byteLength(s, encoding); var alen = align(len); this.ensure(alen); this.buffer.write(s, this.pos, len, encoding); this.pos += alen; }; XdrWriter.prototype.addBlr = function (blr) { var alen = align(blr.pos); this.ensure(alen + 4); this.buffer.writeInt32BE(blr.pos, this.pos); this.pos += 4; blr.buffer.copy(this.buffer, this.pos); this.pos += alen; }; XdrWriter.prototype.getData = function () { return this.buffer.slice(0, this.pos); }; XdrWriter.prototype.addDouble = function (value) { this.ensure(8); this.buffer.writeDoubleBE(value, this.pos); this.pos += 8; }; XdrWriter.prototype.addQuad = function (quad) { this.ensure(8); var b = this.buffer; b.writeInt32BE(quad.high, this.pos); this.pos += 4; b.writeInt32BE(quad.low, this.pos); this.pos += 4; }; XdrWriter.prototype.addBuffer = function (buffer) { this.ensure(buffer.length); buffer.copy(this.buffer, this.pos, 0, buffer.length); this.pos += buffer.length; } XdrWriter.prototype.addAlignment = function (len) { var alen = (4 - len) & 3; this.ensure(alen); this.buffer.write('ffffff', this.pos, alen, 'hex'); this.pos += alen; } /*************************************** * * XDR Reader * ***************************************/ var XdrReader = exports.XdrReader = function (buffer) { this.buffer = buffer; this.pos = 0; }; XdrReader.prototype.readInt = function () { var r = this.buffer.readInt32BE(this.pos); this.pos += 4; return r; }; XdrReader.prototype.readUInt = function () { var r = this.buffer.readUInt32BE(this.pos); this.pos += 4; return r; }; XdrReader.prototype.readInt64 = function () { var high = this.buffer.readInt32BE(this.pos); this.pos += 4; var low = this.buffer.readInt32BE(this.pos); this.pos += 4; return new Long(low, high).toNumber(); }; XdrReader.prototype.readShort = function () { var r = this.buffer.readInt16BE(this.pos); this.pos += 2; return r; }; XdrReader.prototype.readQuad = function () { var b = this.buffer; var high = b.readInt32BE(this.pos); this.pos += 4; var low = b.readInt32BE(this.pos); this.pos += 4; return {low: low, high: high} }; XdrReader.prototype.readFloat = function () { var r = this.buffer.readFloatBE(this.pos); this.pos += 4; return r; }; XdrReader.prototype.readDouble = function () { var r = this.buffer.readDoubleBE(this.pos); this.pos += 8; return r; }; XdrReader.prototype.readArray = function () { var len = this.readInt(); if (!len) { return; } var r = this.buffer.slice(this.pos, this.pos + len); this.pos += align(len); return r; }; XdrReader.prototype.readBuffer = function (len, toAlign = true) { if (!arguments.length) { len = this.readInt(); } if (len !== null && len !== undefined) { if (len <= 0){ return Buffer.alloc(0); } var r = this.buffer.slice(this.pos, this.pos + len); this.pos += toAlign ? align(len) : len; return r; } }; XdrReader.prototype.readString = function (encoding) { var len = this.readInt(); return this.readText(len, encoding); }; XdrReader.prototype.readText = function (len, encoding) { if (len <= 0) { return ''; } var r = this.buffer.toString(encoding, this.pos, this.pos + len); this.pos += align(len); return r; }; /*************************************** * * BitSet * ***************************************/ var WORD_LOG = 5; var BUFFER_BITS = 8; var BIT_ON = 1; var BIT_OFF = 0; var BitSet = exports.BitSet = function (buffer) { this.data = []; if (buffer) { this.scale(buffer.length * BUFFER_BITS); for (var i = 0; i < buffer.length; i++) { var n = buffer[i]; for (var j = 0; j < BUFFER_BITS; j++) { var k = i * BUFFER_BITS + j; this.data[k >>> WORD_LOG] |= (n >> j & BIT_ON) << k; } } } }; BitSet.prototype.scale = function (index) { var l = index >>> WORD_LOG; for (var i = this.data.length; l >= i; l--) { this.data.push(BIT_OFF); } }; BitSet.prototype.set = function (index, value) { const pos = index >>> 3; for (let i = this.data.length, j = pos; j >= i; j--) { this.data.push(BIT_OFF); } if (value === undefined || value) { this.data[pos] |= (1 << (index % BUFFER_BITS)); } else { this.data[pos] &= ~(1 << (index % BUFFER_BITS)); } }; BitSet.prototype.get = function (index) { var n = index >>> WORD_LOG; if (n >= this.data.length) { return BIT_OFF; } return (this.data[n] >>> index) & BIT_ON; }; BitSet.prototype.toBuffer = function () { return Buffer.from(this.data); };