Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/protocol/ExecuteTask.js
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,7 @@ function createInvalidFunctionCodeError() {
function isVector(type) {
switch (type) {
case TypeCode.REAL_VECTOR:
case TypeCode.HALF_VECTOR:
return true;
default:
return false;
Expand Down
6 changes: 6 additions & 0 deletions lib/protocol/Reader.js
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,12 @@ Reader.prototype.readRealVector = function readRealVector() {
});
}

Reader.prototype.readHalfVector = function readHalfVector() {
return this.readVector(2, function (buffer, offset) {
return bignum.readDec16LE(buffer, offset);
});
}

Reader.LobDescriptor = LobDescriptor;

function LobDescriptor(type, options, charLength, byteLength, locatorId, chunk, defaultType) {
Expand Down
1 change: 1 addition & 0 deletions lib/protocol/Statement.js
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ function isOutputParameter(metadata) {
function isVector(type) {
switch (type) {
case TypeCode.REAL_VECTOR:
case TypeCode.HALF_VECTOR:
return true;
default:
return false;
Expand Down
13 changes: 12 additions & 1 deletion lib/protocol/Writer.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ Writer.prototype.add = function add(type, value, fraction, length) {
} else if (type === TypeCode.DECIMAL || type === TypeCode.FIXED8
|| type === TypeCode.FIXED12 || type === TypeCode.FIXED16) {
this[type](value, fraction);
} else if (type === TypeCode.REAL_VECTOR) {
} else if (type === TypeCode.REAL_VECTOR || type === TypeCode.HALF_VECTOR) {
this[type](value, length);
} else {
this[type](value);
Expand Down Expand Up @@ -457,6 +457,7 @@ Writer.prototype.pushNull = function pushNull(type) {
break;
case TypeCode.ST_GEOMETRY:
case TypeCode.REAL_VECTOR:
case TypeCode.HALF_VECTOR:
nullTypeCode = TypeCode.BINARY | 0x80;
break;
default:
Expand Down Expand Up @@ -1002,6 +1003,16 @@ Writer.prototype[TypeCode.REAL_VECTOR] = function writeRealVector(value, length)
this.writeVector(value, length, 4, writeRealElem, 'REAL_VECTOR');
}

Writer.prototype[TypeCode.HALF_VECTOR] = function writeHalfVector(value, length) {
function writeHalfElem (value, buffer, offset) {
if (!util.isNumber(value)) {
throw createInputError('HALF_VECTOR');
}
bignum.writeDec16LE(buffer, value, offset);
}
this.writeVector(value, length, 2, writeHalfElem, 'HALF_VECTOR');
}

function setChar(str, i, c) {
if(i >= str.length) return str;
return str.substring(0, i) + c + str.substring(i + 1);
Expand Down
3 changes: 2 additions & 1 deletion lib/protocol/common/DataFormatVersion.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ module.exports = {
LEVEL7: 7,
LEVEL8: 8,
LEVEL9: 9,
LEVEL10: 10,
// Maximum data format version supported by this driver
MAX_VERSION: 9,
MAX_VERSION: 10,
};
2 changes: 2 additions & 0 deletions lib/protocol/common/NormalizedTypeCode.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,5 @@ NormalizedTypeCode[TypeCode.ST_POINT] = TypeCode.ST_GEOMETRY;
NormalizedTypeCode[TypeCode.BOOLEAN] = TypeCode.BOOLEAN;
// RealVector
NormalizedTypeCode[TypeCode.REAL_VECTOR] = TypeCode.REAL_VECTOR;
// HalfVector
NormalizedTypeCode[TypeCode.HALF_VECTOR] = TypeCode.HALF_VECTOR;
2 changes: 2 additions & 0 deletions lib/protocol/common/ReadFunction.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ var READ_FIXED8 = 'readFixed8';
var READ_FIXED12 = 'readFixed12';
var READ_FIXED16 = 'readFixed16';
var READ_REAL_VECTOR = 'readRealVector';
var READ_HALF_VECTOR = 'readHalfVector';

ReadFunction[TypeCode.TINYINT] = READ_TINYINT;
ReadFunction[TypeCode.SMALLINT] = READ_SMALLINT;
Expand Down Expand Up @@ -83,3 +84,4 @@ ReadFunction[TypeCode.FIXED8] = READ_FIXED8;
ReadFunction[TypeCode.FIXED12] = READ_FIXED12;
ReadFunction[TypeCode.FIXED16] = READ_FIXED16;
ReadFunction[TypeCode.REAL_VECTOR] = READ_REAL_VECTOR;
ReadFunction[TypeCode.HALF_VECTOR] = READ_HALF_VECTOR;
3 changes: 2 additions & 1 deletion lib/protocol/common/TypeCode.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,5 +89,6 @@ module.exports = {
FIXED16: 76,
FIXED8: 81,
FIXED12: 82,
REAL_VECTOR: 96
REAL_VECTOR: 96,
HALF_VECTOR: 97
};
109 changes: 109 additions & 0 deletions lib/util/bignum.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,15 @@ var BIN_10_35_7 = 19;
var UInt64Max = '18446744073709551615';
var UInt64MaxLen = 20;

/* overflow threshold for dec16 */
// dec16 max value + 1/2 ulp
var Dec16Overflow = 65520;
/* underflow threshold for dec16 */
// smallest non-zero dec16 value, half and smaller rounds to 0
var Dec16Underflow = 5.9604645e-8 * 0.5;
var Dec64ExpBias = 1023;
var Dec16ExpBias = 15;

function _readInt64(buffer, offset, unsigned) {

var x, y, s, y0, y1, x0, x1, x2;
Expand Down Expand Up @@ -831,6 +840,104 @@ function readFIXED(buffer, bytes, offset, frac) {
}
}

function writeDec16(buffer, value, offset) {
offset = offset || 0;
buffer.fill(0x00, offset, offset + 2);

var buffer64 = Buffer.alloc(8);
buffer64.writeDoubleLE(value);

// Write sign bit
if (value < 0) {
buffer[offset + 1] |= 0x80;
}

if (isNaN(value)) {
// Write max exponent + 1
buffer[offset + 1] |= 0x7c;
// Indicate NaN
buffer[offset + 1] |= 0x02;
// Attempt to preserve higher order 10 significand bits
buffer[offset + 1] |= (buffer64[6] & 0x0c) >> 2;
buffer[offset] |= (buffer64[6] & 0x03) << 6 | (buffer[5] & 0xfc) >> 2;
return ;
}

var abs = Math.abs(value);
if (abs >= Dec16Overflow) {
buffer[offset + 1] |= 0x7c; // Positive or negative infinity
return ;
}

if (abs <= Dec16Underflow) {
// Round to 0
return ;
}

// exp should be limited to -25 to 15 given the overflow and underflow bounds
var exp = ((buffer64[7] & 0x7f) << 4 | (buffer64[6] & 0xf0) >> 4) - Dec64ExpBias;

// For subnormals, for computations in rounding, retain the
// difference expdelta = E_min - exp and the hidden msb in the
// 64 bit representation.
var expdelta = 0;
var msb = 0;
if (exp < -14) {
// Subnormal
expdelta = -14 - exp;
exp = -15;
// Set the hidden msb in the bit after the mantissa
msb = 0x0010_0000;
}

var top_bits = buffer64[4] + (buffer64[5] << 8) + ((buffer64[6] & 0x0f) << 16) | msb;
var bottom_bits = buffer64[0] + (buffer64[1] << 8) + (buffer64[2] << 16) + (buffer64[3] << 24 >>> 0);

// Extract 10 significant bits starting at 42 + expdelta, top half starts at 32
var signif_bits = top_bits >> (10 + expdelta);

// Round to nearest even, determining to round up is a function
// of the least significant bit (lsb), next bit (round position),
// and sticky bit (if there are non-zero bits to the right of the
// round). Increments occur in 3 cases:
// LSB Round Sticky
// 0 1 1
// 1 1 0
// 1 1 1
var lsb = top_bits & (1 << 10 + expdelta);
var round = top_bits & (1 << 9 + expdelta);
var sticky = (bottom_bits != 0) | (top_bits & ((1 << 9 + expdelta) - 1));

if (round != 0 && ((lsb | sticky) != 0)) {
signif_bits++;
}

// Add exponent to significand in case of rounding increasing the
// exponent
signif_bits += (exp + 15) << 10;

buffer[offset + 1] |= (signif_bits >> 8) & 0x7f;
buffer[offset] |= signif_bits & 0xff;
}

function readDec16(buffer, offset) {
var s = buffer[offset + 1] & 0x80;
var e = (buffer[offset + 1] & 0x7c) >> 2;
var m = buffer[offset] + ((buffer[offset + 1] & 0x03) << 8);

if (e === 0) { // subnormal
e = 1 - Dec16ExpBias;
} else if (e === 0x1f) {
return m ? NaN : ((s ? -1 : 1) * Infinity);
} else {
m |= 1 << 10; // add hidden msb
e = e - Dec16ExpBias;
}

// Mantissa size is 10
return (s ? -1 : 1) * m * Math.pow(2, e - 10);
}

exports.readInt64LE = readInt64;
exports.readUInt64LE = readUInt64;
exports.writeInt64LE = writeInt64;
Expand All @@ -842,3 +949,5 @@ exports.writeDec128 = writeDec128;
exports.readDecFloat = readDecFloat;
exports.readDecFixed = readDecFixed;
exports.readFIXED = readFIXED;
exports.writeDec16LE = writeDec16;
exports.readDec16LE = readDec16;
Loading