Add reading/writing of C integers to buffers
This commit is contained in:
parent
8a03cf7a7b
commit
9812e31e8b
@ -168,3 +168,198 @@ from the original Buffer.
|
||||
|
||||
// abc
|
||||
// !bc
|
||||
|
||||
### buffer.readUInt8(offset, endian)
|
||||
|
||||
Reads an unsigned 8 bit integer from the buffer at the specified offset. Endian
|
||||
must be either 'big' or 'little' and specifies what endian ordering to read the
|
||||
bytes from the buffer in.
|
||||
|
||||
Example:
|
||||
|
||||
var buf = new Buffer(4);
|
||||
|
||||
buf[0] = 0x3;
|
||||
buf[1] = 0x4;
|
||||
buf[2] = 0x23;
|
||||
buf[3] = 0x42;
|
||||
|
||||
for (ii = 0; ii < buf.length; ii++) {
|
||||
console.log(buf.readUInt8(ii, 'big');
|
||||
console.log(buf.readUInt8(ii, 'little');
|
||||
}
|
||||
|
||||
// 0x3
|
||||
// 0x3
|
||||
// 0x4
|
||||
// 0x4
|
||||
// 0x23
|
||||
// 0x23
|
||||
// 0x42
|
||||
// 0x42
|
||||
|
||||
### buffer.readUInt16(offset, endian)
|
||||
|
||||
Reads an unsigned 16 bit integer from the buffer at the specified offset. Endian
|
||||
must be either 'big' or 'little' and specifies what endian ordering to read the
|
||||
bytes from the buffer in.
|
||||
|
||||
Example:
|
||||
|
||||
var buf = new Buffer(4);
|
||||
|
||||
buf[0] = 0x3;
|
||||
buf[1] = 0x4;
|
||||
buf[2] = 0x23;
|
||||
buf[3] = 0x42;
|
||||
|
||||
console.log(buf.readUInt16(0, 'big');
|
||||
console.log(buf.readUInt16(0, 'little');
|
||||
console.log(buf.readUInt16(1, 'big');
|
||||
console.log(buf.readUInt16(1, 'little');
|
||||
console.log(buf.readUInt16(2, 'big');
|
||||
console.log(buf.readUInt16(2, 'little');
|
||||
|
||||
// 0x0304
|
||||
// 0x0403
|
||||
// 0x0423
|
||||
// 0x2304
|
||||
// 0x2342
|
||||
// 0x4223
|
||||
|
||||
### buffer.readUInt32(offset, endian)
|
||||
|
||||
Reads an unsigned 32 bit integer from the buffer at the specified offset. Endian
|
||||
must be either 'big' or 'little' and specifies what endian ordering to read the
|
||||
bytes from the buffer in.
|
||||
|
||||
Example:
|
||||
|
||||
var buf = new Buffer(4);
|
||||
|
||||
buf[0] = 0x3;
|
||||
buf[1] = 0x4;
|
||||
buf[2] = 0x23;
|
||||
buf[3] = 0x42;
|
||||
|
||||
console.log(buf.readUInt32(0, 'big');
|
||||
console.log(buf.readUInt32(0, 'little');
|
||||
|
||||
// 0x03042342
|
||||
// 0x42230403
|
||||
|
||||
### buffer.readInt8(offset, endian)
|
||||
|
||||
Reads a signed 8 bit integer from the buffer at the specified offset. Endian
|
||||
must be either 'big' or 'little' and specifies what endian ordering to read the
|
||||
bytes from the buffer in.
|
||||
|
||||
Works as `buffer.readUInt8`, except buffer contents are treated as twos
|
||||
complement signed values.
|
||||
|
||||
### buffer.readInt16(offset, endian)
|
||||
|
||||
Reads a signed 16 bit integer from the buffer at the specified offset. Endian
|
||||
must be either 'big' or 'little' and specifies what endian ordering to read the
|
||||
bytes from the buffer in.
|
||||
|
||||
Works as `buffer.readUInt16`, except buffer contents are treated as twos
|
||||
complement signed values.
|
||||
|
||||
### buffer.readInt32(offset, endian)
|
||||
|
||||
Reads a signed 32 bit integer from the buffer at the specified offset. Endian
|
||||
must be either 'big' or 'little' and specifies what endian ordering to read the
|
||||
bytes from the buffer in.
|
||||
|
||||
Works as `buffer.readUInt32`, except buffer contents are treated as twos
|
||||
complement signed values.
|
||||
|
||||
### buffer.writeUInt8(value, offset, endian)
|
||||
|
||||
Writes `value` to the buffer at the specified offset with specified endian
|
||||
format. Note, `value` must be a valid 8 bit unsigned integer.
|
||||
|
||||
Example:
|
||||
|
||||
var buf = new Buffer(4);
|
||||
buf.writeUInt8(0x3, 0, 'big');
|
||||
buf.writeUInt8(0x4, 1, 'big');
|
||||
buf.writeUInt8(0x23, 2, 'big');
|
||||
buf.writeUInt8(0x42, 3, 'big');
|
||||
|
||||
console.log(buf);
|
||||
|
||||
buf.writeUInt8(0x3, 0, 'little');
|
||||
buf.writeUInt8(0x4, 1, 'little');
|
||||
buf.writeUInt8(0x23, 2, 'little');
|
||||
buf.writeUInt8(0x42, 3, 'little');
|
||||
|
||||
console.log(buf);
|
||||
|
||||
// <Buffer 03 04 23 42>
|
||||
// <Buffer 03 04 23 42>
|
||||
|
||||
### buffer.writeUInt16(value, offset, endian)
|
||||
|
||||
Writes `value` to the buffer at the specified offset with specified endian
|
||||
format. Note, `value` must be a valid 16 bit unsigned integer.
|
||||
|
||||
Example:
|
||||
|
||||
var buf = new Buffer(4);
|
||||
buf.writeUInt16(0xdead, 0, 'big');
|
||||
buf.writeUInt16(0xbeef, 2, 'big');
|
||||
|
||||
console.log(buf);
|
||||
|
||||
buf.writeUInt16(0xdead, 0, 'little');
|
||||
buf.writeUInt16(0xbeef, 2, 'little');
|
||||
|
||||
console.log(buf);
|
||||
|
||||
// <Buffer de ad be ef>
|
||||
// <Buffer ad de ef be>
|
||||
|
||||
### buffer.writeUInt32(value, offset, endian)
|
||||
|
||||
Writes `value` to the buffer at the specified offset with specified endian
|
||||
format. Note, `value` must be a valid 32 bit unsigned integer.
|
||||
|
||||
Example:
|
||||
|
||||
var buf = new Buffer(4);
|
||||
buf.writeUInt32(0xfeedface, 0, 'big');
|
||||
|
||||
console.log(buf);
|
||||
|
||||
buf.writeUInt32(0xfeedface, 0, 'little');
|
||||
|
||||
console.log(buf);
|
||||
|
||||
// <Buffer fe ed fa ce>
|
||||
// <Buffer ce fa ed fe>
|
||||
|
||||
### buffer.writeInt8(value, offset, endian)
|
||||
|
||||
Writes `value` to the buffer at the specified offset with specified endian
|
||||
format. Note, `value` must be a valid 16 bit signed integer.
|
||||
|
||||
Works as `buffer.writeUInt8`, except value is written out as a two's complement
|
||||
signed integer into `buffer`.
|
||||
|
||||
### buffer.writeInt16(value, offset, endian)
|
||||
|
||||
Writes `value` to the buffer at the specified offset with specified endian
|
||||
format. Note, `value` must be a valid 16 bit unsigned integer.
|
||||
|
||||
Works as `buffer.writeUInt16`, except value is written out as a two's complement
|
||||
signed integer into `buffer`.
|
||||
|
||||
### buffer.writeInt32(value, offset, endian)
|
||||
|
||||
Writes `value` to the buffer at the specified offset with specified endian
|
||||
format. Note, `value` must be a valid 16 bit signed integer.
|
||||
|
||||
Works as `buffer.writeUInt832, except value is written out as a two's complement
|
||||
signed integer into `buffer`.
|
||||
|
448
lib/buffer.js
448
lib/buffer.js
@ -20,6 +20,7 @@
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
var SlowBuffer = process.binding('buffer').SlowBuffer;
|
||||
var assert = require('assert');
|
||||
|
||||
|
||||
function toHex(n) {
|
||||
@ -45,7 +46,7 @@ SlowBuffer.prototype.hexSlice = function(start, end) {
|
||||
if (!end || end < 0 || end > len) end = len;
|
||||
|
||||
var out = '';
|
||||
for (var i = start; i < end; i ++) {
|
||||
for (var i = start; i < end; i++) {
|
||||
out += toHex(this[i]);
|
||||
}
|
||||
return out;
|
||||
@ -98,13 +99,13 @@ SlowBuffer.prototype.hexWrite = function(string, offset) {
|
||||
if (len % 2) {
|
||||
throw new Error('Invalid hex string');
|
||||
}
|
||||
for (var i = 0; i < len / 2; i ++) {
|
||||
for (var i = 0; i < len / 2; i++) {
|
||||
var byte = parseInt(string.substr(i * 2, 2), 16);
|
||||
if (isNaN(byte)) throw new Error('Invalid hex string');
|
||||
this[offset + i] = byte;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
SlowBuffer.prototype.write = function(string, offset, encoding) {
|
||||
@ -449,3 +450,444 @@ Buffer.prototype.asciiWrite = function(string, offset) {
|
||||
return this.write(string, offset, 'ascii');
|
||||
};
|
||||
|
||||
Buffer.prototype.readUInt8 = function(offset, endian) {
|
||||
var buffer = this;
|
||||
|
||||
assert.ok(endian !== undefined && endian !== null,
|
||||
'missing endian');
|
||||
|
||||
assert.ok(endian == 'big' || endian == 'little',
|
||||
'bad endian value');
|
||||
|
||||
assert.ok(offset !== undefined && offset !== null,
|
||||
'missing offset');
|
||||
|
||||
assert.ok(offset < buffer.length,
|
||||
'Trying to read beyond buffer length');
|
||||
|
||||
return buffer[offset];
|
||||
};
|
||||
|
||||
|
||||
Buffer.prototype.readUInt16 = function(offset, endian) {
|
||||
var val = 0;
|
||||
var buffer = this;
|
||||
|
||||
assert.ok(endian !== undefined && endian !== null,
|
||||
'missing endian');
|
||||
|
||||
assert.ok(endian == 'big' || endian == 'little',
|
||||
'bad endian value');
|
||||
|
||||
assert.ok(offset !== undefined && offset !== null,
|
||||
'missing offset');
|
||||
|
||||
assert.ok(offset + 1 < buffer.length,
|
||||
'Trying to read beyond buffer length');
|
||||
|
||||
if (endian == 'big') {
|
||||
val = buffer[offset] << 8;
|
||||
val |= buffer[offset + 1];
|
||||
} else {
|
||||
val = buffer[offset];
|
||||
val |= buffer[offset + 1] << 8;
|
||||
}
|
||||
|
||||
return val;
|
||||
};
|
||||
|
||||
|
||||
Buffer.prototype.readUInt32 = function(offset, endian) {
|
||||
var val = 0;
|
||||
var buffer = this;
|
||||
|
||||
assert.ok(endian !== undefined && endian !== null,
|
||||
'missing endian');
|
||||
|
||||
assert.ok(endian == 'big' || endian == 'little',
|
||||
'bad endian value');
|
||||
|
||||
assert.ok(offset !== undefined && offset !== null,
|
||||
'missing offset');
|
||||
|
||||
assert.ok(offset + 3 < buffer.length,
|
||||
'Trying to read beyond buffer length');
|
||||
|
||||
if (endian == 'big') {
|
||||
val = buffer[offset + 1] << 16;
|
||||
val |= buffer[offset + 2] << 8;
|
||||
val |= buffer[offset + 3];
|
||||
val = val + (buffer[offset] << 24 >>> 0);
|
||||
} else {
|
||||
val = buffer[offset + 2] << 16;
|
||||
val |= buffer[offset + 1] << 8;
|
||||
val |= buffer[offset];
|
||||
val = val + (buffer[offset + 3] << 24 >>> 0);
|
||||
}
|
||||
|
||||
return val;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Signed integer types, yay team! A reminder on how two's complement actually
|
||||
* works. The first bit is the signed bit, i.e. tells us whether or not the
|
||||
* number should be positive or negative. If the two's complement value is
|
||||
* positive, then we're done, as it's equivalent to the unsigned representation.
|
||||
*
|
||||
* Now if the number is positive, you're pretty much done, you can just leverage
|
||||
* the unsigned translations and return those. Unfortunately, negative numbers
|
||||
* aren't quite that straightforward.
|
||||
*
|
||||
* At first glance, one might be inclined to use the traditional formula to
|
||||
* translate binary numbers between the positive and negative values in two's
|
||||
* complement. (Though it doesn't quite work for the most negative value)
|
||||
* Mainly:
|
||||
* - invert all the bits
|
||||
* - add one to the result
|
||||
*
|
||||
* Of course, this doesn't quite work in Javascript. Take for example the value
|
||||
* of -128. This could be represented in 16 bits (big-endian) as 0xff80. But of
|
||||
* course, Javascript will do the following:
|
||||
*
|
||||
* > ~0xff80
|
||||
* -65409
|
||||
*
|
||||
* Whoh there, Javascript, that's not quite right. But wait, according to
|
||||
* Javascript that's perfectly correct. When Javascript ends up seeing the
|
||||
* constant 0xff80, it has no notion that it is actually a signed number. It
|
||||
* assumes that we've input the unsigned value 0xff80. Thus, when it does the
|
||||
* binary negation, it casts it into a signed value, (positive 0xff80). Then
|
||||
* when you perform binary negation on that, it turns it into a negative number.
|
||||
*
|
||||
* Instead, we're going to have to use the following general formula, that works
|
||||
* in a rather Javascript friendly way. I'm glad we don't support this kind of
|
||||
* weird numbering scheme in the kernel.
|
||||
*
|
||||
* (BIT-MAX - (unsigned)val + 1) * -1
|
||||
*
|
||||
* The astute observer, may think that this doesn't make sense for 8-bit numbers
|
||||
* (really it isn't necessary for them). However, when you get 16-bit numbers,
|
||||
* you do. Let's go back to our prior example and see how this will look:
|
||||
*
|
||||
* (0xffff - 0xff80 + 1) * -1
|
||||
* (0x007f + 1) * -1
|
||||
* (0x0080) * -1
|
||||
*/
|
||||
Buffer.prototype.readInt8 = function(offset, endian) {
|
||||
var buffer = this;
|
||||
var neg;
|
||||
|
||||
assert.ok(endian !== undefined && endian !== null,
|
||||
'missing endian');
|
||||
|
||||
assert.ok(endian == 'big' || endian == 'little',
|
||||
'bad endian value');
|
||||
|
||||
assert.ok(offset !== undefined && offset !== null,
|
||||
'missing offset');
|
||||
|
||||
assert.ok(offset < buffer.length,
|
||||
'Trying to read beyond buffer length');
|
||||
|
||||
neg = buffer[offset] & 0x80;
|
||||
if (!neg) {
|
||||
return (buffer[offset]);
|
||||
}
|
||||
|
||||
return ((0xff - buffer[offset] + 1) * -1);
|
||||
};
|
||||
|
||||
|
||||
Buffer.prototype.readInt16 = function(offset, endian) {
|
||||
var buffer = this;
|
||||
var neg;
|
||||
|
||||
assert.ok(endian !== undefined && endian !== null,
|
||||
'missing endian');
|
||||
|
||||
assert.ok(endian == 'big' || endian == 'little',
|
||||
'bad endian value');
|
||||
|
||||
assert.ok(offset !== undefined && offset !== null,
|
||||
'missing offset');
|
||||
|
||||
assert.ok(offset + 1 < buffer.length,
|
||||
'Trying to read beyond buffer length');
|
||||
|
||||
val = buffer.readUInt16(offset, endian);
|
||||
neg = val & 0x8000;
|
||||
if (!neg) {
|
||||
return val;
|
||||
}
|
||||
|
||||
return (0xffff - val + 1) * -1;
|
||||
};
|
||||
|
||||
|
||||
Buffer.prototype.readInt32 = function(offset, endian) {
|
||||
var buffer = this;
|
||||
var neg;
|
||||
|
||||
assert.ok(endian !== undefined && endian !== null,
|
||||
'missing endian');
|
||||
|
||||
assert.ok(endian == 'big' || endian == 'little',
|
||||
'bad endian value');
|
||||
|
||||
assert.ok(offset !== undefined && offset !== null,
|
||||
'missing offset');
|
||||
|
||||
assert.ok(offset + 3 < buffer.length,
|
||||
'Trying to read beyond buffer length');
|
||||
|
||||
val = buffer.readUInt32(offset, endian);
|
||||
neg = val & 0x80000000;
|
||||
if (!neg) {
|
||||
return (val);
|
||||
}
|
||||
|
||||
return (0xffffffff - val + 1) * -1;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* We have to make sure that the value is a valid integer. This means that it is
|
||||
* non-negative. It has no fractional component and that it does not exceed the
|
||||
* maximum allowed value.
|
||||
*
|
||||
* value The number to check for validity
|
||||
*
|
||||
* max The maximum value
|
||||
*/
|
||||
function verifuint(value, max) {
|
||||
assert.ok(typeof (value) == 'number',
|
||||
'cannot write a non-number as a number');
|
||||
|
||||
assert.ok(value >= 0,
|
||||
'specified a negative value for writing an unsigned value');
|
||||
|
||||
assert.ok(value <= max, 'value is larger than maximum value for type');
|
||||
|
||||
assert.ok(Math.floor(value) === value, 'value has a fractional component');
|
||||
}
|
||||
|
||||
|
||||
Buffer.prototype.writeUInt8 = function(value, offset, endian) {
|
||||
var buffer = this;
|
||||
|
||||
assert.ok(value !== undefined && value !== null,
|
||||
'missing value');
|
||||
|
||||
assert.ok(endian !== undefined && endian !== null,
|
||||
'missing endian');
|
||||
|
||||
assert.ok(endian == 'big' || endian == 'little',
|
||||
'bad endian value');
|
||||
|
||||
assert.ok(offset !== undefined && offset !== null,
|
||||
'missing offset');
|
||||
|
||||
assert.ok(offset < buffer.length,
|
||||
'trying to read beyond buffer length');
|
||||
|
||||
verifuint(value, 0xff);
|
||||
buffer[offset] = value;
|
||||
};
|
||||
|
||||
|
||||
Buffer.prototype.writeUInt16 = function(value, offset, endian) {
|
||||
var buffer = this;
|
||||
|
||||
assert.ok(value !== undefined && value !== null,
|
||||
'missing value');
|
||||
|
||||
assert.ok(endian !== undefined && endian !== null,
|
||||
'missing endian');
|
||||
|
||||
assert.ok(endian == 'big' || endian == 'little',
|
||||
'bad endian value');
|
||||
|
||||
assert.ok(offset !== undefined && offset !== null,
|
||||
'missing offset');
|
||||
|
||||
assert.ok(offset + 1 < buffer.length,
|
||||
'trying to read beyond buffer length');
|
||||
|
||||
verifuint(value, 0xffff);
|
||||
|
||||
if (endian == 'big') {
|
||||
buffer[offset] = (value & 0xff00) >>> 8;
|
||||
buffer[offset + 1] = value & 0x00ff;
|
||||
} else {
|
||||
buffer[offset + 1] = (value & 0xff00) >>> 8;
|
||||
buffer[offset] = value & 0x00ff;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Buffer.prototype.writeUInt32 = function(value, offset, endian) {
|
||||
var buffer = this;
|
||||
|
||||
assert.ok(value !== undefined && value !== null,
|
||||
'missing value');
|
||||
|
||||
assert.ok(endian !== undefined && endian !== null,
|
||||
'missing endian');
|
||||
|
||||
assert.ok(endian == 'big' || endian == 'little',
|
||||
'bad endian value');
|
||||
|
||||
assert.ok(offset !== undefined && offset !== null,
|
||||
'missing offset');
|
||||
|
||||
assert.ok(offset + 3 < buffer.length,
|
||||
'trying to read beyond buffer length');
|
||||
|
||||
verifuint(value, 0xffffffff);
|
||||
if (endian == 'big') {
|
||||
buffer[offset] = (value >>> 24) & 0xff;
|
||||
buffer[offset + 1] = (value >>> 16) & 0xff;
|
||||
buffer[offset + 2] = (value >>> 8) & 0xff;
|
||||
buffer[offset + 3] = value & 0xff;
|
||||
} else {
|
||||
buffer[offset + 3] = (value >>> 24) & 0xff;
|
||||
buffer[offset + 2] = (value >>> 16) & 0xff;
|
||||
buffer[offset + 1] = (value >>> 8) & 0xff;
|
||||
buffer[offset] = value & 0xff;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* We now move onto our friends in the signed number category. Unlike unsigned
|
||||
* numbers, we're going to have to worry a bit more about how we put values into
|
||||
* arrays. Since we are only worrying about signed 32-bit values, we're in
|
||||
* slightly better shape. Unfortunately, we really can't do our favorite binary
|
||||
* & in this system. It really seems to do the wrong thing. For example:
|
||||
*
|
||||
* > -32 & 0xff
|
||||
* 224
|
||||
*
|
||||
* What's happening above is really: 0xe0 & 0xff = 0xe0. However, the results of
|
||||
* this aren't treated as a signed number. Ultimately a bad thing.
|
||||
*
|
||||
* What we're going to want to do is basically create the unsigned equivalent of
|
||||
* our representation and pass that off to the wuint* functions. To do that
|
||||
* we're going to do the following:
|
||||
*
|
||||
* - if the value is positive
|
||||
* we can pass it directly off to the equivalent wuint
|
||||
* - if the value is negative
|
||||
* we do the following computation:
|
||||
* mb + val + 1, where
|
||||
* mb is the maximum unsigned value in that byte size
|
||||
* val is the Javascript negative integer
|
||||
*
|
||||
*
|
||||
* As a concrete value, take -128. In signed 16 bits this would be 0xff80. If
|
||||
* you do out the computations:
|
||||
*
|
||||
* 0xffff - 128 + 1
|
||||
* 0xffff - 127
|
||||
* 0xff80
|
||||
*
|
||||
* You can then encode this value as the signed version. This is really rather
|
||||
* hacky, but it should work and get the job done which is our goal here.
|
||||
*/
|
||||
|
||||
/*
|
||||
* A series of checks to make sure we actually have a signed 32-bit number
|
||||
*/
|
||||
function verifsint(value, max, min) {
|
||||
assert.ok(typeof (value) == 'number',
|
||||
'cannot write a non-number as a number');
|
||||
|
||||
assert.ok(value <= max, 'value larger than maximum allowed value');
|
||||
|
||||
assert.ok(value >= min, 'value smaller than minimum allowed value');
|
||||
|
||||
assert.ok(Math.floor(value) === value, 'value has a fractional component');
|
||||
}
|
||||
|
||||
Buffer.prototype.writeInt8 = function(value, offset, endian) {
|
||||
var buffer = this;
|
||||
|
||||
assert.ok(value !== undefined && value !== null,
|
||||
'missing value');
|
||||
|
||||
assert.ok(endian !== undefined && endian !== null,
|
||||
'missing endian');
|
||||
|
||||
assert.ok(endian == 'big' || endian == 'little',
|
||||
'bad endian value');
|
||||
|
||||
assert.ok(offset !== undefined && offset !== null,
|
||||
'missing offset');
|
||||
|
||||
assert.ok(offset < buffer.length,
|
||||
'Trying to read beyond buffer length');
|
||||
|
||||
verifsint(value, 0x7f, -0xf0);
|
||||
|
||||
if (value >= 0) {
|
||||
buffer.writeUInt8(value, offset, endian);
|
||||
} else {
|
||||
buffer.writeUInt8(0xff + value + 1, offset, endian);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Buffer.prototype.writeInt16 = function(value, offset, endian) {
|
||||
var buffer = this;
|
||||
|
||||
assert.ok(value !== undefined && value !== null,
|
||||
'missing value');
|
||||
|
||||
assert.ok(endian !== undefined && endian !== null,
|
||||
'missing endian');
|
||||
|
||||
assert.ok(endian == 'big' || endian == 'little',
|
||||
'bad endian value');
|
||||
|
||||
assert.ok(offset !== undefined && offset !== null,
|
||||
'missing offset');
|
||||
|
||||
assert.ok(offset + 1 < buffer.length,
|
||||
'Trying to read beyond buffer length');
|
||||
|
||||
verifsint(value, 0x7fff, -0xf000);
|
||||
|
||||
if (value >= 0) {
|
||||
buffer.writeUInt16(value, offset, endian);
|
||||
} else {
|
||||
buffer.writeUInt16(0xffff + value + 1, offset, endian);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Buffer.prototype.writeInt32 = function(value, offset, endian) {
|
||||
var buffer = this;
|
||||
|
||||
assert.ok(value !== undefined && value !== null,
|
||||
'missing value');
|
||||
|
||||
assert.ok(endian !== undefined && endian !== null,
|
||||
'missing endian');
|
||||
|
||||
assert.ok(endian == 'big' || endian == 'little',
|
||||
'bad endian value');
|
||||
|
||||
assert.ok(offset !== undefined && offset !== null,
|
||||
'missing offset');
|
||||
|
||||
assert.ok(offset + 3 < buffer.length,
|
||||
'Trying to read beyond buffer length');
|
||||
|
||||
verifsint(value, 0x7fffffff, -0xf0000000);
|
||||
if (value >= 0) {
|
||||
buffer.writeUInt32(value, offset, endian);
|
||||
} else {
|
||||
buffer.writeUInt32(0xffffffff + value + 1, offset, endian);
|
||||
}
|
||||
};
|
||||
|
100
test/simple/test-readint.js
Normal file
100
test/simple/test-readint.js
Normal file
@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Tests to verify we're reading in signed integers correctly
|
||||
*/
|
||||
var ASSERT = require('assert');
|
||||
|
||||
/*
|
||||
* Test 8 bit signed integers
|
||||
*/
|
||||
function test8() {
|
||||
var data = new Buffer(4);
|
||||
|
||||
data[0] = 0x23;
|
||||
ASSERT.equal(0x23, data.readInt8(0, 'big'));
|
||||
ASSERT.equal(0x23, data.readInt8(0, 'little'));
|
||||
|
||||
data[0] = 0xff;
|
||||
ASSERT.equal(-1, data.readInt8(0, 'big'));
|
||||
ASSERT.equal(-1, data.readInt8(0, 'little'));
|
||||
|
||||
data[0] = 0x87;
|
||||
data[1] = 0xab;
|
||||
data[2] = 0x7c;
|
||||
data[3] = 0xef;
|
||||
ASSERT.equal(-121, data.readInt8(0, 'big'));
|
||||
ASSERT.equal(-85, data.readInt8(1, 'big'));
|
||||
ASSERT.equal(124, data.readInt8(2, 'big'));
|
||||
ASSERT.equal(-17, data.readInt8(3, 'big'));
|
||||
ASSERT.equal(-121, data.readInt8(0, 'little'));
|
||||
ASSERT.equal(-85, data.readInt8(1, 'little'));
|
||||
ASSERT.equal(124, data.readInt8(2, 'little'));
|
||||
ASSERT.equal(-17, data.readInt8(3, 'little'));
|
||||
}
|
||||
|
||||
|
||||
function test16() {
|
||||
var buffer = new Buffer(6);
|
||||
buffer[0] = 0x16;
|
||||
buffer[1] = 0x79;
|
||||
ASSERT.equal(0x1679, buffer.readInt16(0, 'big'));
|
||||
ASSERT.equal(0x7916, buffer.readInt16(0, 'little'));
|
||||
|
||||
buffer[0] = 0xff;
|
||||
buffer[1] = 0x80;
|
||||
ASSERT.equal(-128, buffer.readInt16(0, 'big'));
|
||||
ASSERT.equal(-32513, buffer.readInt16(0, 'little'));
|
||||
|
||||
/* test offset with weenix */
|
||||
buffer[0] = 0x77;
|
||||
buffer[1] = 0x65;
|
||||
buffer[2] = 0x65;
|
||||
buffer[3] = 0x6e;
|
||||
buffer[4] = 0x69;
|
||||
buffer[5] = 0x78;
|
||||
ASSERT.equal(0x7765, buffer.readInt16(0, 'big'));
|
||||
ASSERT.equal(0x6565, buffer.readInt16(1, 'big'));
|
||||
ASSERT.equal(0x656e, buffer.readInt16(2, 'big'));
|
||||
ASSERT.equal(0x6e69, buffer.readInt16(3, 'big'));
|
||||
ASSERT.equal(0x6978, buffer.readInt16(4, 'big'));
|
||||
ASSERT.equal(0x6577, buffer.readInt16(0, 'little'));
|
||||
ASSERT.equal(0x6565, buffer.readInt16(1, 'little'));
|
||||
ASSERT.equal(0x6e65, buffer.readInt16(2, 'little'));
|
||||
ASSERT.equal(0x696e, buffer.readInt16(3, 'little'));
|
||||
ASSERT.equal(0x7869, buffer.readInt16(4, 'little'));
|
||||
}
|
||||
|
||||
|
||||
function test32() {
|
||||
var buffer = new Buffer(6);
|
||||
buffer[0] = 0x43;
|
||||
buffer[1] = 0x53;
|
||||
buffer[2] = 0x16;
|
||||
buffer[3] = 0x79;
|
||||
ASSERT.equal(0x43531679, buffer.readInt32(0, 'big'));
|
||||
ASSERT.equal(0x79165343, buffer.readInt32(0, 'little'));
|
||||
|
||||
buffer[0] = 0xff;
|
||||
buffer[1] = 0xfe;
|
||||
buffer[2] = 0xef;
|
||||
buffer[3] = 0xfa;
|
||||
ASSERT.equal(-69638, buffer.readInt32(0, 'big'));
|
||||
ASSERT.equal(-84934913, buffer.readInt32(0, 'little'));
|
||||
|
||||
buffer[0] = 0x42;
|
||||
buffer[1] = 0xc3;
|
||||
buffer[2] = 0x95;
|
||||
buffer[3] = 0xa9;
|
||||
buffer[4] = 0x36;
|
||||
buffer[5] = 0x17;
|
||||
ASSERT.equal(0x42c395a9, buffer.readInt32(0, 'big'));
|
||||
ASSERT.equal(-1013601994, buffer.readInt32(1, 'big'));
|
||||
ASSERT.equal(-1784072681, buffer.readInt32(2, 'big'));
|
||||
ASSERT.equal(-1449802942, buffer.readInt32(0, 'little'));
|
||||
ASSERT.equal(917083587, buffer.readInt32(1, 'little'));
|
||||
ASSERT.equal(389458325, buffer.readInt32(2, 'little'));
|
||||
}
|
||||
|
||||
|
||||
test8();
|
||||
test16();
|
||||
test32();
|
94
test/simple/test-readuint.js
Normal file
94
test/simple/test-readuint.js
Normal file
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* A battery of tests to help us read a series of uints
|
||||
*/
|
||||
|
||||
var ASSERT = require('assert');
|
||||
|
||||
/*
|
||||
* We need to check the following things:
|
||||
* - We are correctly resolving big endian (doesn't mean anything for 8 bit)
|
||||
* - Correctly resolving little endian (doesn't mean anything for 8 bit)
|
||||
* - Correctly using the offsets
|
||||
* - Correctly interpreting values that are beyond the signed range as unsigned
|
||||
*/
|
||||
function test8() {
|
||||
var data = new Buffer(4);
|
||||
data[0] = 23;
|
||||
data[1] = 23;
|
||||
data[2] = 23;
|
||||
data[3] = 23;
|
||||
ASSERT.equal(23, data.readUInt8(0, 'big'));
|
||||
ASSERT.equal(23, data.readUInt8(0, 'little'));
|
||||
ASSERT.equal(23, data.readUInt8(1, 'big'));
|
||||
ASSERT.equal(23, data.readUInt8(1, 'little'));
|
||||
ASSERT.equal(23, data.readUInt8(2, 'big'));
|
||||
ASSERT.equal(23, data.readUInt8(2, 'little'));
|
||||
ASSERT.equal(23, data.readUInt8(3, 'big'));
|
||||
ASSERT.equal(23, data.readUInt8(3, 'little'));
|
||||
data[0] = 255; /* If it became a signed int, would be -1 */
|
||||
ASSERT.equal(255, data.readUInt8(0, 'big'));
|
||||
ASSERT.equal(255, data.readUInt8(0, 'little'));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Test 16 bit unsigned integers. We need to verify the same set as 8 bit, only
|
||||
* now some of the issues actually matter:
|
||||
* - We are correctly resolving big endian
|
||||
* - Correctly resolving little endian
|
||||
* - Correctly using the offsets
|
||||
* - Correctly interpreting values that are beyond the signed range as unsigned
|
||||
*/
|
||||
function test16() {
|
||||
var data = new Buffer(4);
|
||||
|
||||
data[0] = 0;
|
||||
data[1] = 0x23;
|
||||
data[2] = 0x42;
|
||||
data[3] = 0x3f;
|
||||
|
||||
ASSERT.equal(0x23, data.readUInt16(0, 'big'));
|
||||
ASSERT.equal(0x2342, data.readUInt16(1, 'big'));
|
||||
ASSERT.equal(0x423f, data.readUInt16(2, 'big'));
|
||||
|
||||
ASSERT.equal(0x2300, data.readUInt16(0, 'little'));
|
||||
ASSERT.equal(0x4223, data.readUInt16(1, 'little'));
|
||||
ASSERT.equal(0x3f42, data.readUInt16(2, 'little'));
|
||||
|
||||
data[0] = 0xfe;
|
||||
data[1] = 0xfe;
|
||||
|
||||
ASSERT.equal(0xfefe, data.readUInt16(0, 'big'));
|
||||
ASSERT.equal(0xfefe, data.readUInt16(0, 'little'));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Test 32 bit unsigned integers. We need to verify the same set as 8 bit, only
|
||||
* now some of the issues actually matter:
|
||||
* - We are correctly resolving big endian
|
||||
* - Correctly using the offsets
|
||||
* - Correctly interpreting values that are beyond the signed range as unsigned
|
||||
*/
|
||||
function test32() {
|
||||
var data = new Buffer(8);
|
||||
data[0] = 0x32;
|
||||
data[1] = 0x65;
|
||||
data[2] = 0x42;
|
||||
data[3] = 0x56;
|
||||
data[4] = 0x23;
|
||||
data[5] = 0xff;
|
||||
|
||||
ASSERT.equal(0x32654256, data.readUInt32(0, 'big'));
|
||||
ASSERT.equal(0x65425623, data.readUInt32(1, 'big'));
|
||||
ASSERT.equal(0x425623ff, data.readUInt32(2, 'big'));
|
||||
|
||||
ASSERT.equal(0x56426532, data.readUInt32(0, 'little'));
|
||||
ASSERT.equal(0x23564265, data.readUInt32(1, 'little'));
|
||||
ASSERT.equal(0xff235642, data.readUInt32(2, 'little'));
|
||||
}
|
||||
|
||||
|
||||
test8();
|
||||
test16();
|
||||
test32();
|
91
test/simple/test-writeint.js
Normal file
91
test/simple/test-writeint.js
Normal file
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Tests to verify we're writing signed integers correctly
|
||||
*/
|
||||
var ASSERT = require('assert');
|
||||
|
||||
function test8() {
|
||||
var buffer = new Buffer(4);
|
||||
buffer.writeInt8(0x23, 0, 'big');
|
||||
buffer.writeInt8(0x23, 1, 'little');
|
||||
buffer.writeInt8(-5, 2, 'big');
|
||||
buffer.writeInt8(-5, 3, 'little');
|
||||
|
||||
ASSERT.equal(0x23, buffer[0]);
|
||||
ASSERT.equal(0x23, buffer[1]);
|
||||
ASSERT.equal(0xfb, buffer[2]);
|
||||
ASSERT.equal(0xfb, buffer[3]);
|
||||
|
||||
/* Make sure we handle truncation correctly */
|
||||
ASSERT.throws(function() {
|
||||
buffer.writeInt8(0xabc, 0, 'big');
|
||||
});
|
||||
ASSERT.throws(function() {
|
||||
buffer.writeInt8(0xabc, 0, 'little');
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function test16() {
|
||||
var buffer = new Buffer(6);
|
||||
buffer.writeInt16(0x0023, 0, 'big');
|
||||
buffer.writeInt16(0x0023, 2, 'little');
|
||||
ASSERT.equal(0x00, buffer[0]);
|
||||
ASSERT.equal(0x23, buffer[1]);
|
||||
ASSERT.equal(0x23, buffer[2]);
|
||||
ASSERT.equal(0x00, buffer[3]);
|
||||
buffer.writeInt16(-5, 0, 'big');
|
||||
buffer.writeInt16(-5, 2, 'little');
|
||||
ASSERT.equal(0xff, buffer[0]);
|
||||
ASSERT.equal(0xfb, buffer[1]);
|
||||
ASSERT.equal(0xfb, buffer[2]);
|
||||
ASSERT.equal(0xff, buffer[3]);
|
||||
|
||||
buffer.writeInt16(-1679, 1, 'big');
|
||||
buffer.writeInt16(-1679, 3, 'little');
|
||||
ASSERT.equal(0xf9, buffer[1]);
|
||||
ASSERT.equal(0x71, buffer[2]);
|
||||
ASSERT.equal(0x71, buffer[3]);
|
||||
ASSERT.equal(0xf9, buffer[4]);
|
||||
}
|
||||
|
||||
|
||||
function test32() {
|
||||
var buffer = new Buffer(8);
|
||||
buffer.writeInt32(0x23, 0, 'big');
|
||||
buffer.writeInt32(0x23, 4, 'little');
|
||||
ASSERT.equal(0x00, buffer[0]);
|
||||
ASSERT.equal(0x00, buffer[1]);
|
||||
ASSERT.equal(0x00, buffer[2]);
|
||||
ASSERT.equal(0x23, buffer[3]);
|
||||
ASSERT.equal(0x23, buffer[4]);
|
||||
ASSERT.equal(0x00, buffer[5]);
|
||||
ASSERT.equal(0x00, buffer[6]);
|
||||
ASSERT.equal(0x00, buffer[7]);
|
||||
|
||||
buffer.writeInt32(-5, 0, 'big');
|
||||
buffer.writeInt32(-5, 4, 'little');
|
||||
ASSERT.equal(0xff, buffer[0]);
|
||||
ASSERT.equal(0xff, buffer[1]);
|
||||
ASSERT.equal(0xff, buffer[2]);
|
||||
ASSERT.equal(0xfb, buffer[3]);
|
||||
ASSERT.equal(0xfb, buffer[4]);
|
||||
ASSERT.equal(0xff, buffer[5]);
|
||||
ASSERT.equal(0xff, buffer[6]);
|
||||
ASSERT.equal(0xff, buffer[7]);
|
||||
|
||||
buffer.writeInt32(-805306713, 0, 'big');
|
||||
buffer.writeInt32(-805306713, 4, 'little');
|
||||
ASSERT.equal(0xcf, buffer[0]);
|
||||
ASSERT.equal(0xff, buffer[1]);
|
||||
ASSERT.equal(0xfe, buffer[2]);
|
||||
ASSERT.equal(0xa7, buffer[3]);
|
||||
ASSERT.equal(0xa7, buffer[4]);
|
||||
ASSERT.equal(0xfe, buffer[5]);
|
||||
ASSERT.equal(0xff, buffer[6]);
|
||||
ASSERT.equal(0xcf, buffer[7]);
|
||||
}
|
||||
|
||||
|
||||
test8();
|
||||
test16();
|
||||
test32();
|
118
test/simple/test-writeuint.js
Normal file
118
test/simple/test-writeuint.js
Normal file
@ -0,0 +1,118 @@
|
||||
/*
|
||||
* A battery of tests to help us read a series of uints
|
||||
*/
|
||||
var ASSERT = require('assert');
|
||||
|
||||
/*
|
||||
* We need to check the following things:
|
||||
* - We are correctly resolving big endian (doesn't mean anything for 8 bit)
|
||||
* - Correctly resolving little endian (doesn't mean anything for 8 bit)
|
||||
* - Correctly using the offsets
|
||||
* - Correctly interpreting values that are beyond the signed range as unsigned
|
||||
*/
|
||||
function test8() {
|
||||
var data = new Buffer(4);
|
||||
data.writeUInt8(23, 0, 'big');
|
||||
data.writeUInt8(23, 1, 'big');
|
||||
data.writeUInt8(23, 2, 'big');
|
||||
data.writeUInt8(23, 3, 'big');
|
||||
ASSERT.equal(23, data[0]);
|
||||
ASSERT.equal(23, data[1]);
|
||||
ASSERT.equal(23, data[2]);
|
||||
ASSERT.equal(23, data[3]);
|
||||
data.writeUInt8(23, 0, 'little');
|
||||
data.writeUInt8(23, 1, 'little');
|
||||
data.writeUInt8(23, 2, 'little');
|
||||
data.writeUInt8(23, 3, 'little');
|
||||
ASSERT.equal(23, data[0]);
|
||||
ASSERT.equal(23, data[1]);
|
||||
ASSERT.equal(23, data[2]);
|
||||
ASSERT.equal(23, data[3]);
|
||||
data.writeUInt8(255, 0, 'big');
|
||||
ASSERT.equal(255, data[0]);
|
||||
data.writeUInt8(255, 0, 'little');
|
||||
ASSERT.equal(255, data[0]);
|
||||
}
|
||||
|
||||
|
||||
function test16() {
|
||||
var value = 0x2343;
|
||||
var data = new Buffer(4);
|
||||
data.writeUInt16(value, 0, 'big');
|
||||
ASSERT.equal(0x23, data[0]);
|
||||
ASSERT.equal(0x43, data[1]);
|
||||
data.writeUInt16(value, 1, 'big');
|
||||
ASSERT.equal(0x23, data[1]);
|
||||
ASSERT.equal(0x43, data[2]);
|
||||
data.writeUInt16(value, 2, 'big');
|
||||
ASSERT.equal(0x23, data[2]);
|
||||
ASSERT.equal(0x43, data[3]);
|
||||
|
||||
data.writeUInt16(value, 0, 'little');
|
||||
ASSERT.equal(0x23, data[1]);
|
||||
ASSERT.equal(0x43, data[0]);
|
||||
|
||||
data.writeUInt16(value, 1, 'little');
|
||||
ASSERT.equal(0x23, data[2]);
|
||||
ASSERT.equal(0x43, data[1]);
|
||||
|
||||
data.writeUInt16(value, 2, 'little');
|
||||
ASSERT.equal(0x23, data[3]);
|
||||
ASSERT.equal(0x43, data[2]);
|
||||
|
||||
value = 0xff80;
|
||||
data.writeUInt16(value, 0, 'little');
|
||||
ASSERT.equal(0xff, data[1]);
|
||||
ASSERT.equal(0x80, data[0]);
|
||||
|
||||
data.writeUInt16(value, 0, 'big');
|
||||
ASSERT.equal(0xff, data[0]);
|
||||
ASSERT.equal(0x80, data[1]);
|
||||
}
|
||||
|
||||
|
||||
function test32() {
|
||||
var data = new Buffer(6);
|
||||
var value = 0xe7f90a6d;
|
||||
|
||||
data.writeUInt32(value, 0, 'big');
|
||||
ASSERT.equal(0xe7, data[0]);
|
||||
ASSERT.equal(0xf9, data[1]);
|
||||
ASSERT.equal(0x0a, data[2]);
|
||||
ASSERT.equal(0x6d, data[3]);
|
||||
|
||||
data.writeUInt32(value, 1, 'big');
|
||||
ASSERT.equal(0xe7, data[1]);
|
||||
ASSERT.equal(0xf9, data[2]);
|
||||
ASSERT.equal(0x0a, data[3]);
|
||||
ASSERT.equal(0x6d, data[4]);
|
||||
|
||||
data.writeUInt32(value, 2, 'big');
|
||||
ASSERT.equal(0xe7, data[2]);
|
||||
ASSERT.equal(0xf9, data[3]);
|
||||
ASSERT.equal(0x0a, data[4]);
|
||||
ASSERT.equal(0x6d, data[5]);
|
||||
|
||||
data.writeUInt32(value, 0, 'little');
|
||||
ASSERT.equal(0xe7, data[3]);
|
||||
ASSERT.equal(0xf9, data[2]);
|
||||
ASSERT.equal(0x0a, data[1]);
|
||||
ASSERT.equal(0x6d, data[0]);
|
||||
|
||||
data.writeUInt32(value, 1, 'little');
|
||||
ASSERT.equal(0xe7, data[4]);
|
||||
ASSERT.equal(0xf9, data[3]);
|
||||
ASSERT.equal(0x0a, data[2]);
|
||||
ASSERT.equal(0x6d, data[1]);
|
||||
|
||||
data.writeUInt32(value, 2, 'little');
|
||||
ASSERT.equal(0xe7, data[5]);
|
||||
ASSERT.equal(0xf9, data[4]);
|
||||
ASSERT.equal(0x0a, data[3]);
|
||||
ASSERT.equal(0x6d, data[2]);
|
||||
}
|
||||
|
||||
|
||||
test8();
|
||||
test16();
|
||||
test32();
|
Loading…
x
Reference in New Issue
Block a user