Permalink
Browse files

Add reading/writing of C integers to buffers

  • Loading branch information...
1 parent 8a03cf7 commit 9812e31e8ba43be9c50d07f83cbf459427a5d877 @rmustacc rmustacc committed with ry May 1, 2011
Showing with 1,043 additions and 3 deletions.
  1. +195 −0 doc/api/buffers.markdown
  2. +445 −3 lib/buffer.js
  3. +100 −0 test/simple/test-readint.js
  4. +94 −0 test/simple/test-readuint.js
  5. +91 −0 test/simple/test-writeint.js
  6. +118 −0 test/simple/test-writeuint.js
View
195 doc/api/buffers.markdown
@@ -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`.
View
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);
+ }
+};
View
100 test/simple/test-readint.js
@@ -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();
View
94 test/simple/test-readuint.js
@@ -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();
View
91 test/simple/test-writeint.js
@@ -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();
View
118 test/simple/test-writeuint.js
@@ -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();

0 comments on commit 9812e31

Please sign in to comment.