Skip to content
This repository
Browse code

now supports buffers

  • Loading branch information...
commit 4b9c1dba3619bb9e5b314a635bd0c6b2cef53be2 1 parent 4015be2
James Halliday authored

Showing 3 changed files with 1,076 additions and 0 deletions. Show diff stats Hide diff stats

  1. +41 0 LICENSE
  2. +951 0 builtins/buffer.js
  3. +84 0 builtins/buffer_ieee754.js
41 LICENSE
... ... @@ -1,5 +1,7 @@
1 1 Some pieces from builtins/ taken from node core under this license:
2 2
  3 +----
  4 +
3 5 Copyright Joyent, Inc. and other Node contributors.
4 6
5 7 Permission is hereby granted, free of charge, to any person obtaining a
@@ -20,3 +22,42 @@ NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
20 22 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
21 23 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
22 24 USE OR OTHER DEALINGS IN THE SOFTWARE.
  25 +
  26 +----
  27 +
  28 +buffer_ieee754.js has this license in it:
  29 +
  30 +----
  31 +
  32 +Copyright (c) 2008, Fair Oaks Labs, Inc.
  33 +All rights reserved.
  34 +
  35 +Redistribution and use in source and binary forms, with or without
  36 +modification, are permitted provided that the following conditions are met:
  37 +
  38 + * Redistributions of source code must retain the above copyright notice,
  39 + this list of conditions and the following disclaimer.
  40 +
  41 + * Redistributions in binary form must reproduce the above copyright notice,
  42 + this list of conditions and the following disclaimer in the documentation
  43 + and/or other materials provided with the distribution.
  44 +
  45 + * Neither the name of Fair Oaks Labs, Inc. nor the names of its contributors
  46 + may be used to endorse or promote products derived from this software
  47 + without specific prior written permission.
  48 +
  49 +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  50 +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  51 +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  52 +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  53 +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  54 +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  55 +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  56 +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  57 +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  58 +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  59 +POSSIBILITY OF SUCH DAMAGE.
  60 +
  61 +Modifications to writeIEEE754 to support negative zeroes made by Brian White
  62 +
  63 +----
951 builtins/buffer.js
... ... @@ -0,0 +1,951 @@
  1 +var assert = require('assert');
  2 +
  3 +exports.INSPECT_MAX_BYTES = 50;
  4 +
  5 +
  6 +function toHex(n) {
  7 + if (n < 16) return '0' + n.toString(16);
  8 + return n.toString(16);
  9 +}
  10 +
  11 +// Buffer
  12 +
  13 +function Buffer(subject, encoding, offset) {
  14 + if (!(this instanceof Buffer)) {
  15 + return new Buffer(subject, encoding, offset);
  16 + }
  17 +
  18 + var type;
  19 +
  20 + // Are we slicing?
  21 + if (typeof offset === 'number') {
  22 + this.length = coerce(encoding);
  23 + this.parent = subject;
  24 + this.offset = offset;
  25 + } else {
  26 + // Find the length
  27 + switch (type = typeof subject) {
  28 + case 'number':
  29 + this.length = coerce(subject);
  30 + break;
  31 +
  32 + case 'string':
  33 + this.length = Buffer.byteLength(subject, encoding);
  34 + break;
  35 +
  36 + case 'object': // Assume object is an array
  37 + this.length = coerce(subject.length);
  38 + break;
  39 +
  40 + default:
  41 + throw new Error('First argument needs to be a number, ' +
  42 + 'array or string.');
  43 + }
  44 +
  45 + if (this.length > Buffer.poolSize) {
  46 + // Big buffer, just alloc one.
  47 + this.parent = new SlowBuffer(this.length);
  48 + this.offset = 0;
  49 +
  50 + } else {
  51 + // Small buffer.
  52 + if (!pool || pool.length - pool.used < this.length) allocPool();
  53 + this.parent = pool;
  54 + this.offset = pool.used;
  55 + pool.used += this.length;
  56 + }
  57 +
  58 + // Treat array-ish objects as a byte array.
  59 + if (isArrayIsh(subject)) {
  60 + for (var i = 0; i < this.length; i++) {
  61 + this.parent[i + this.offset] = subject[i];
  62 + }
  63 + } else if (type == 'string') {
  64 + // We are a string
  65 + this.length = this.write(subject, 0, encoding);
  66 + }
  67 + }
  68 +}
  69 +
  70 +function isArrayIsh(subject) {
  71 + return Array.isArray(subject) || Buffer.isBuffer(subject) ||
  72 + subject && typeof subject === 'object' &&
  73 + typeof subject.length === 'number';
  74 +}
  75 +
  76 +Buffer.Buffer = Buffer;
  77 +module.exports = Buffer;
  78 +
  79 +Buffer.poolSize = 8 * 1024;
  80 +var pool;
  81 +
  82 +function allocPool() {
  83 + pool = new SlowBuffer(Buffer.poolSize);
  84 + pool.used = 0;
  85 +}
  86 +
  87 +
  88 +// Static methods
  89 +Buffer.isBuffer = function isBuffer(b) {
  90 + return b instanceof Buffer || b instanceof SlowBuffer;
  91 +};
  92 +
  93 +
  94 +// Inspect
  95 +Buffer.prototype.inspect = function inspect() {
  96 + var out = [],
  97 + len = this.length;
  98 +
  99 + for (var i = 0; i < len; i++) {
  100 + out[i] = toHex(this.parent[i + this.offset]);
  101 + if (i == exports.INSPECT_MAX_BYTES) {
  102 + out[i + 1] = '...';
  103 + break;
  104 + }
  105 + }
  106 +
  107 + return '<Buffer ' + out.join(' ') + '>';
  108 +};
  109 +
  110 +
  111 +Buffer.prototype.get = function get(i) {
  112 + if (i < 0 || i >= this.length) throw new Error('oob');
  113 + return this.parent[this.offset + i];
  114 +};
  115 +
  116 +
  117 +Buffer.prototype.set = function set(i, v) {
  118 + if (i < 0 || i >= this.length) throw new Error('oob');
  119 + return this.parent[this.offset + i] = v;
  120 +};
  121 +
  122 +
  123 +// write(string, offset = 0, length = buffer.length-offset, encoding = 'utf8')
  124 +Buffer.prototype.write = function(string, offset, length, encoding) {
  125 + // Support both (string, offset, length, encoding)
  126 + // and the legacy (string, encoding, offset, length)
  127 + if (isFinite(offset)) {
  128 + if (!isFinite(length)) {
  129 + encoding = length;
  130 + length = undefined;
  131 + }
  132 + } else { // legacy
  133 + var swap = encoding;
  134 + encoding = offset;
  135 + offset = length;
  136 + length = swap;
  137 + }
  138 +
  139 + offset = +offset || 0;
  140 + var remaining = this.length - offset;
  141 + if (!length) {
  142 + length = remaining;
  143 + } else {
  144 + length = +length;
  145 + if (length > remaining) {
  146 + length = remaining;
  147 + }
  148 + }
  149 + encoding = String(encoding || 'utf8').toLowerCase();
  150 +
  151 + var ret;
  152 + switch (encoding) {
  153 + case 'hex':
  154 + ret = this.parent.hexWrite(string, this.offset + offset, length);
  155 + break;
  156 +
  157 + case 'utf8':
  158 + case 'utf-8':
  159 + ret = this.parent.utf8Write(string, this.offset + offset, length);
  160 + break;
  161 +
  162 + case 'ascii':
  163 + ret = this.parent.asciiWrite(string, this.offset + offset, length);
  164 + break;
  165 +
  166 + case 'binary':
  167 + ret = this.parent.binaryWrite(string, this.offset + offset, length);
  168 + break;
  169 +
  170 + case 'base64':
  171 + // Warning: maxLength not taken into account in base64Write
  172 + ret = this.parent.base64Write(string, this.offset + offset, length);
  173 + break;
  174 +
  175 + case 'ucs2':
  176 + case 'ucs-2':
  177 + ret = this.parent.ucs2Write(string, this.offset + offset, length);
  178 + break;
  179 +
  180 + default:
  181 + throw new Error('Unknown encoding');
  182 + }
  183 +
  184 + Buffer._charsWritten = SlowBuffer._charsWritten;
  185 +
  186 + return ret;
  187 +};
  188 +
  189 +
  190 +// toString(encoding, start=0, end=buffer.length)
  191 +Buffer.prototype.toString = function(encoding, start, end) {
  192 + encoding = String(encoding || 'utf8').toLowerCase();
  193 +
  194 + if (typeof start == 'undefined' || start < 0) {
  195 + start = 0;
  196 + } else if (start > this.length) {
  197 + start = this.length;
  198 + }
  199 +
  200 + if (typeof end == 'undefined' || end > this.length) {
  201 + end = this.length;
  202 + } else if (end < 0) {
  203 + end = 0;
  204 + }
  205 +
  206 + start = start + this.offset;
  207 + end = end + this.offset;
  208 +
  209 + switch (encoding) {
  210 + case 'hex':
  211 + return this.parent.hexSlice(start, end);
  212 +
  213 + case 'utf8':
  214 + case 'utf-8':
  215 + return this.parent.utf8Slice(start, end);
  216 +
  217 + case 'ascii':
  218 + return this.parent.asciiSlice(start, end);
  219 +
  220 + case 'binary':
  221 + return this.parent.binarySlice(start, end);
  222 +
  223 + case 'base64':
  224 + return this.parent.base64Slice(start, end);
  225 +
  226 + case 'ucs2':
  227 + case 'ucs-2':
  228 + return this.parent.ucs2Slice(start, end);
  229 +
  230 + default:
  231 + throw new Error('Unknown encoding');
  232 + }
  233 +};
  234 +
  235 +
  236 +// byteLength
  237 +Buffer.byteLength = SlowBuffer.byteLength;
  238 +
  239 +
  240 +// fill(value, start=0, end=buffer.length)
  241 +Buffer.prototype.fill = function fill(value, start, end) {
  242 + value || (value = 0);
  243 + start || (start = 0);
  244 + end || (end = this.length);
  245 +
  246 + if (typeof value === 'string') {
  247 + value = value.charCodeAt(0);
  248 + }
  249 + if (!(typeof value === 'number') || isNaN(value)) {
  250 + throw new Error('value is not a number');
  251 + }
  252 +
  253 + if (end < start) throw new Error('end < start');
  254 +
  255 + // Fill 0 bytes; we're done
  256 + if (end === start) return 0;
  257 + if (this.length == 0) return 0;
  258 +
  259 + if (start < 0 || start >= this.length) {
  260 + throw new Error('start out of bounds');
  261 + }
  262 +
  263 + if (end < 0 || end > this.length) {
  264 + throw new Error('end out of bounds');
  265 + }
  266 +
  267 + return this.parent.fill(value,
  268 + start + this.offset,
  269 + end + this.offset);
  270 +};
  271 +
  272 +
  273 +// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)
  274 +Buffer.prototype.copy = function(target, target_start, start, end) {
  275 + var source = this;
  276 + start || (start = 0);
  277 + end || (end = this.length);
  278 + target_start || (target_start = 0);
  279 +
  280 + if (end < start) throw new Error('sourceEnd < sourceStart');
  281 +
  282 + // Copy 0 bytes; we're done
  283 + if (end === start) return 0;
  284 + if (target.length == 0 || source.length == 0) return 0;
  285 +
  286 + if (target_start < 0 || target_start >= target.length) {
  287 + throw new Error('targetStart out of bounds');
  288 + }
  289 +
  290 + if (start < 0 || start >= source.length) {
  291 + throw new Error('sourceStart out of bounds');
  292 + }
  293 +
  294 + if (end < 0 || end > source.length) {
  295 + throw new Error('sourceEnd out of bounds');
  296 + }
  297 +
  298 + // Are we oob?
  299 + if (end > this.length) {
  300 + end = this.length;
  301 + }
  302 +
  303 + if (target.length - target_start < end - start) {
  304 + end = target.length - target_start + start;
  305 + }
  306 +
  307 + return this.parent.copy(target.parent,
  308 + target_start + target.offset,
  309 + start + this.offset,
  310 + end + this.offset);
  311 +};
  312 +
  313 +
  314 +// slice(start, end)
  315 +Buffer.prototype.slice = function(start, end) {
  316 + if (end === undefined) end = this.length;
  317 + if (end > this.length) throw new Error('oob');
  318 + if (start > end) throw new Error('oob');
  319 +
  320 + return new Buffer(this.parent, end - start, +start + this.offset);
  321 +};
  322 +
  323 +
  324 +// Legacy methods for backwards compatibility.
  325 +
  326 +Buffer.prototype.utf8Slice = function(start, end) {
  327 + return this.toString('utf8', start, end);
  328 +};
  329 +
  330 +Buffer.prototype.binarySlice = function(start, end) {
  331 + return this.toString('binary', start, end);
  332 +};
  333 +
  334 +Buffer.prototype.asciiSlice = function(start, end) {
  335 + return this.toString('ascii', start, end);
  336 +};
  337 +
  338 +Buffer.prototype.utf8Write = function(string, offset) {
  339 + return this.write(string, offset, 'utf8');
  340 +};
  341 +
  342 +Buffer.prototype.binaryWrite = function(string, offset) {
  343 + return this.write(string, offset, 'binary');
  344 +};
  345 +
  346 +Buffer.prototype.asciiWrite = function(string, offset) {
  347 + return this.write(string, offset, 'ascii');
  348 +};
  349 +
  350 +Buffer.prototype.readUInt8 = function(offset, noAssert) {
  351 + var buffer = this;
  352 +
  353 + if (!noAssert) {
  354 + assert.ok(offset !== undefined && offset !== null,
  355 + 'missing offset');
  356 +
  357 + assert.ok(offset < buffer.length,
  358 + 'Trying to read beyond buffer length');
  359 + }
  360 +
  361 + return buffer[offset];
  362 +};
  363 +
  364 +function readUInt16(buffer, offset, isBigEndian, noAssert) {
  365 + var val = 0;
  366 +
  367 +
  368 + if (!noAssert) {
  369 + assert.ok(typeof (isBigEndian) === 'boolean',
  370 + 'missing or invalid endian');
  371 +
  372 + assert.ok(offset !== undefined && offset !== null,
  373 + 'missing offset');
  374 +
  375 + assert.ok(offset + 1 < buffer.length,
  376 + 'Trying to read beyond buffer length');
  377 + }
  378 +
  379 + if (isBigEndian) {
  380 + val = buffer[offset] << 8;
  381 + val |= buffer[offset + 1];
  382 + } else {
  383 + val = buffer[offset];
  384 + val |= buffer[offset + 1] << 8;
  385 + }
  386 +
  387 + return val;
  388 +}
  389 +
  390 +Buffer.prototype.readUInt16LE = function(offset, noAssert) {
  391 + return readUInt16(this, offset, false, noAssert);
  392 +};
  393 +
  394 +Buffer.prototype.readUInt16BE = function(offset, noAssert) {
  395 + return readUInt16(this, offset, true, noAssert);
  396 +};
  397 +
  398 +function readUInt32(buffer, offset, isBigEndian, noAssert) {
  399 + var val = 0;
  400 +
  401 + if (!noAssert) {
  402 + assert.ok(typeof (isBigEndian) === 'boolean',
  403 + 'missing or invalid endian');
  404 +
  405 + assert.ok(offset !== undefined && offset !== null,
  406 + 'missing offset');
  407 +
  408 + assert.ok(offset + 3 < buffer.length,
  409 + 'Trying to read beyond buffer length');
  410 + }
  411 +
  412 + if (isBigEndian) {
  413 + val = buffer[offset + 1] << 16;
  414 + val |= buffer[offset + 2] << 8;
  415 + val |= buffer[offset + 3];
  416 + val = val + (buffer[offset] << 24 >>> 0);
  417 + } else {
  418 + val = buffer[offset + 2] << 16;
  419 + val |= buffer[offset + 1] << 8;
  420 + val |= buffer[offset];
  421 + val = val + (buffer[offset + 3] << 24 >>> 0);
  422 + }
  423 +
  424 + return val;
  425 +}
  426 +
  427 +Buffer.prototype.readUInt32LE = function(offset, noAssert) {
  428 + return readUInt32(this, offset, false, noAssert);
  429 +};
  430 +
  431 +Buffer.prototype.readUInt32BE = function(offset, noAssert) {
  432 + return readUInt32(this, offset, true, noAssert);
  433 +};
  434 +
  435 +
  436 +/*
  437 + * Signed integer types, yay team! A reminder on how two's complement actually
  438 + * works. The first bit is the signed bit, i.e. tells us whether or not the
  439 + * number should be positive or negative. If the two's complement value is
  440 + * positive, then we're done, as it's equivalent to the unsigned representation.
  441 + *
  442 + * Now if the number is positive, you're pretty much done, you can just leverage
  443 + * the unsigned translations and return those. Unfortunately, negative numbers
  444 + * aren't quite that straightforward.
  445 + *
  446 + * At first glance, one might be inclined to use the traditional formula to
  447 + * translate binary numbers between the positive and negative values in two's
  448 + * complement. (Though it doesn't quite work for the most negative value)
  449 + * Mainly:
  450 + * - invert all the bits
  451 + * - add one to the result
  452 + *
  453 + * Of course, this doesn't quite work in Javascript. Take for example the value
  454 + * of -128. This could be represented in 16 bits (big-endian) as 0xff80. But of
  455 + * course, Javascript will do the following:
  456 + *
  457 + * > ~0xff80
  458 + * -65409
  459 + *
  460 + * Whoh there, Javascript, that's not quite right. But wait, according to
  461 + * Javascript that's perfectly correct. When Javascript ends up seeing the
  462 + * constant 0xff80, it has no notion that it is actually a signed number. It
  463 + * assumes that we've input the unsigned value 0xff80. Thus, when it does the
  464 + * binary negation, it casts it into a signed value, (positive 0xff80). Then
  465 + * when you perform binary negation on that, it turns it into a negative number.
  466 + *
  467 + * Instead, we're going to have to use the following general formula, that works
  468 + * in a rather Javascript friendly way. I'm glad we don't support this kind of
  469 + * weird numbering scheme in the kernel.
  470 + *
  471 + * (BIT-MAX - (unsigned)val + 1) * -1
  472 + *
  473 + * The astute observer, may think that this doesn't make sense for 8-bit numbers
  474 + * (really it isn't necessary for them). However, when you get 16-bit numbers,
  475 + * you do. Let's go back to our prior example and see how this will look:
  476 + *
  477 + * (0xffff - 0xff80 + 1) * -1
  478 + * (0x007f + 1) * -1
  479 + * (0x0080) * -1
  480 + */
  481 +Buffer.prototype.readInt8 = function(offset, noAssert) {
  482 + var buffer = this;
  483 + var neg;
  484 +
  485 + if (!noAssert) {
  486 + assert.ok(offset !== undefined && offset !== null,
  487 + 'missing offset');
  488 +
  489 + assert.ok(offset < buffer.length,
  490 + 'Trying to read beyond buffer length');
  491 + }
  492 +
  493 + neg = buffer[offset] & 0x80;
  494 + if (!neg) {
  495 + return (buffer[offset]);
  496 + }
  497 +
  498 + return ((0xff - buffer[offset] + 1) * -1);
  499 +};
  500 +
  501 +function readInt16(buffer, offset, isBigEndian, noAssert) {
  502 + var neg, val;
  503 +
  504 + if (!noAssert) {
  505 + assert.ok(typeof (isBigEndian) === 'boolean',
  506 + 'missing or invalid endian');
  507 +
  508 + assert.ok(offset !== undefined && offset !== null,
  509 + 'missing offset');
  510 +
  511 + assert.ok(offset + 1 < buffer.length,
  512 + 'Trying to read beyond buffer length');
  513 + }
  514 +
  515 + val = readUInt16(buffer, offset, isBigEndian, noAssert);
  516 + neg = val & 0x8000;
  517 + if (!neg) {
  518 + return val;
  519 + }
  520 +
  521 + return (0xffff - val + 1) * -1;
  522 +}
  523 +
  524 +Buffer.prototype.readInt16LE = function(offset, noAssert) {
  525 + return readInt16(this, offset, false, noAssert);
  526 +};
  527 +
  528 +Buffer.prototype.readInt16BE = function(offset, noAssert) {
  529 + return readInt16(this, offset, true, noAssert);
  530 +};
  531 +
  532 +function readInt32(buffer, offset, isBigEndian, noAssert) {
  533 + var neg, val;
  534 +
  535 + if (!noAssert) {
  536 + assert.ok(typeof (isBigEndian) === 'boolean',
  537 + 'missing or invalid endian');
  538 +
  539 + assert.ok(offset !== undefined && offset !== null,
  540 + 'missing offset');
  541 +
  542 + assert.ok(offset + 3 < buffer.length,
  543 + 'Trying to read beyond buffer length');
  544 + }
  545 +
  546 + val = readUInt32(buffer, offset, isBigEndian, noAssert);
  547 + neg = val & 0x80000000;
  548 + if (!neg) {
  549 + return (val);
  550 + }
  551 +
  552 + return (0xffffffff - val + 1) * -1;
  553 +}
  554 +
  555 +Buffer.prototype.readInt32LE = function(offset, noAssert) {
  556 + return readInt32(this, offset, false, noAssert);
  557 +};
  558 +
  559 +Buffer.prototype.readInt32BE = function(offset, noAssert) {
  560 + return readInt32(this, offset, true, noAssert);
  561 +};
  562 +
  563 +function readFloat(buffer, offset, isBigEndian, noAssert) {
  564 + if (!noAssert) {
  565 + assert.ok(typeof (isBigEndian) === 'boolean',
  566 + 'missing or invalid endian');
  567 +
  568 + assert.ok(offset + 3 < buffer.length,
  569 + 'Trying to read beyond buffer length');
  570 + }
  571 +
  572 + return require('buffer_ieee754').readIEEE754(buffer, offset, isBigEndian,
  573 + 23, 4);
  574 +}
  575 +
  576 +Buffer.prototype.readFloatLE = function(offset, noAssert) {
  577 + return readFloat(this, offset, false, noAssert);
  578 +};
  579 +
  580 +Buffer.prototype.readFloatBE = function(offset, noAssert) {
  581 + return readFloat(this, offset, true, noAssert);
  582 +};
  583 +
  584 +function readDouble(buffer, offset, isBigEndian, noAssert) {
  585 + if (!noAssert) {
  586 + assert.ok(typeof (isBigEndian) === 'boolean',
  587 + 'missing or invalid endian');
  588 +
  589 + assert.ok(offset + 7 < buffer.length,
  590 + 'Trying to read beyond buffer length');
  591 + }
  592 +
  593 + return require('buffer_ieee754').readIEEE754(buffer, offset, isBigEndian,
  594 + 52, 8);
  595 +}
  596 +
  597 +Buffer.prototype.readDoubleLE = function(offset, noAssert) {
  598 + return readDouble(this, offset, false, noAssert);
  599 +};
  600 +
  601 +Buffer.prototype.readDoubleBE = function(offset, noAssert) {
  602 + return readDouble(this, offset, true, noAssert);
  603 +};
  604 +
  605 +
  606 +/*
  607 + * We have to make sure that the value is a valid integer. This means that it is
  608 + * non-negative. It has no fractional component and that it does not exceed the
  609 + * maximum allowed value.
  610 + *
  611 + * value The number to check for validity
  612 + *
  613 + * max The maximum value
  614 + */
  615 +function verifuint(value, max) {
  616 + assert.ok(typeof (value) == 'number',
  617 + 'cannot write a non-number as a number');
  618 +
  619 + assert.ok(value >= 0,
  620 + 'specified a negative value for writing an unsigned value');
  621 +
  622 + assert.ok(value <= max, 'value is larger than maximum value for type');
  623 +
  624 + assert.ok(Math.floor(value) === value, 'value has a fractional component');
  625 +}
  626 +
  627 +Buffer.prototype.writeUInt8 = function(value, offset, noAssert) {
  628 + var buffer = this;
  629 +
  630 + if (!noAssert) {
  631 + assert.ok(value !== undefined && value !== null,
  632 + 'missing value');
  633 +
  634 + assert.ok(offset !== undefined && offset !== null,
  635 + 'missing offset');
  636 +
  637 + assert.ok(offset < buffer.length,
  638 + 'trying to write beyond buffer length');
  639 +
  640 + verifuint(value, 0xff);
  641 + }
  642 +
  643 + buffer[offset] = value;
  644 +};
  645 +
  646 +function writeUInt16(buffer, value, offset, isBigEndian, noAssert) {
  647 + if (!noAssert) {
  648 + assert.ok(value !== undefined && value !== null,
  649 + 'missing value');
  650 +
  651 + assert.ok(typeof (isBigEndian) === 'boolean',
  652 + 'missing or invalid endian');
  653 +
  654 + assert.ok(offset !== undefined && offset !== null,
  655 + 'missing offset');
  656 +
  657 + assert.ok(offset + 1 < buffer.length,
  658 + 'trying to write beyond buffer length');
  659 +
  660 + verifuint(value, 0xffff);
  661 + }
  662 +
  663 + if (isBigEndian) {
  664 + buffer[offset] = (value & 0xff00) >>> 8;
  665 + buffer[offset + 1] = value & 0x00ff;
  666 + } else {
  667 + buffer[offset + 1] = (value & 0xff00) >>> 8;
  668 + buffer[offset] = value & 0x00ff;
  669 + }
  670 +}
  671 +
  672 +Buffer.prototype.writeUInt16LE = function(value, offset, noAssert) {
  673 + writeUInt16(this, value, offset, false, noAssert);
  674 +};
  675 +
  676 +Buffer.prototype.writeUInt16BE = function(value, offset, noAssert) {
  677 + writeUInt16(this, value, offset, true, noAssert);
  678 +};
  679 +
  680 +function writeUInt32(buffer, value, offset, isBigEndian, noAssert) {
  681 + if (!noAssert) {
  682 + assert.ok(value !== undefined && value !== null,
  683 + 'missing value');
  684 +
  685 + assert.ok(typeof (isBigEndian) === 'boolean',
  686 + 'missing or invalid endian');
  687 +
  688 + assert.ok(offset !== undefined && offset !== null,
  689 + 'missing offset');
  690 +
  691 + assert.ok(offset + 3 < buffer.length,
  692 + 'trying to write beyond buffer length');
  693 +
  694 + verifuint(value, 0xffffffff);
  695 + }
  696 +
  697 + if (isBigEndian) {
  698 + buffer[offset] = (value >>> 24) & 0xff;
  699 + buffer[offset + 1] = (value >>> 16) & 0xff;
  700 + buffer[offset + 2] = (value >>> 8) & 0xff;
  701 + buffer[offset + 3] = value & 0xff;
  702 + } else {
  703 + buffer[offset + 3] = (value >>> 24) & 0xff;
  704 + buffer[offset + 2] = (value >>> 16) & 0xff;
  705 + buffer[offset + 1] = (value >>> 8) & 0xff;
  706 + buffer[offset] = value & 0xff;
  707 + }
  708 +}
  709 +
  710 +Buffer.prototype.writeUInt32LE = function(value, offset, noAssert) {
  711 + writeUInt32(this, value, offset, false, noAssert);
  712 +};
  713 +
  714 +Buffer.prototype.writeUInt32BE = function(value, offset, noAssert) {
  715 + writeUInt32(this, value, offset, true, noAssert);
  716 +};
  717 +
  718 +
  719 +/*
  720 + * We now move onto our friends in the signed number category. Unlike unsigned
  721 + * numbers, we're going to have to worry a bit more about how we put values into
  722 + * arrays. Since we are only worrying about signed 32-bit values, we're in
  723 + * slightly better shape. Unfortunately, we really can't do our favorite binary
  724 + * & in this system. It really seems to do the wrong thing. For example:
  725 + *
  726 + * > -32 & 0xff
  727 + * 224
  728 + *
  729 + * What's happening above is really: 0xe0 & 0xff = 0xe0. However, the results of
  730 + * this aren't treated as a signed number. Ultimately a bad thing.
  731 + *
  732 + * What we're going to want to do is basically create the unsigned equivalent of
  733 + * our representation and pass that off to the wuint* functions. To do that
  734 + * we're going to do the following:
  735 + *
  736 + * - if the value is positive
  737 + * we can pass it directly off to the equivalent wuint
  738 + * - if the value is negative
  739 + * we do the following computation:
  740 + * mb + val + 1, where
  741 + * mb is the maximum unsigned value in that byte size
  742 + * val is the Javascript negative integer
  743 + *
  744 + *
  745 + * As a concrete value, take -128. In signed 16 bits this would be 0xff80. If
  746 + * you do out the computations:
  747 + *
  748 + * 0xffff - 128 + 1
  749 + * 0xffff - 127
  750 + * 0xff80
  751 + *
  752 + * You can then encode this value as the signed version. This is really rather
  753 + * hacky, but it should work and get the job done which is our goal here.
  754 + */
  755 +
  756 +/*
  757 + * A series of checks to make sure we actually have a signed 32-bit number
  758 + */
  759 +function verifsint(value, max, min) {
  760 + assert.ok(typeof (value) == 'number',
  761 + 'cannot write a non-number as a number');
  762 +
  763 + assert.ok(value <= max, 'value larger than maximum allowed value');
  764 +
  765 + assert.ok(value >= min, 'value smaller than minimum allowed value');
  766 +
  767 + assert.ok(Math.floor(value) === value, 'value has a fractional component');
  768 +}
  769 +
  770 +function verifIEEE754(value, max, min) {
  771 + assert.ok(typeof (value) == 'number',
  772 + 'cannot write a non-number as a number');
  773 +
  774 + assert.ok(value <= max, 'value larger than maximum allowed value');
  775 +
  776 + assert.ok(value >= min, 'value smaller than minimum allowed value');
  777 +}
  778 +
  779 +Buffer.prototype.writeInt8 = function(value, offset, noAssert) {
  780 + var buffer = this;
  781 +
  782 + if (!noAssert) {
  783 + assert.ok(value !== undefined && value !== null,
  784 + 'missing value');
  785 +
  786 + assert.ok(offset !== undefined && offset !== null,
  787 + 'missing offset');
  788 +
  789 + assert.ok(offset < buffer.length,
  790 + 'Trying to write beyond buffer length');
  791 +
  792 + verifsint(value, 0x7f, -0x80);
  793 + }
  794 +
  795 + if (value >= 0) {
  796 + buffer.writeUInt8(value, offset, noAssert);
  797 + } else {
  798 + buffer.writeUInt8(0xff + value + 1, offset, noAssert);
  799 + }
  800 +};
  801 +
  802 +function writeInt16(buffer, value, offset, isBigEndian, noAssert) {
  803 + if (!noAssert) {
  804 + assert.ok(value !== undefined && value !== null,
  805 + 'missing value');
  806 +
  807 + assert.ok(typeof (isBigEndian) === 'boolean',
  808 + 'missing or invalid endian');
  809 +
  810 + assert.ok(offset !== undefined && offset !== null,
  811 + 'missing offset');
  812 +
  813 + assert.ok(offset + 1 < buffer.length,
  814 + 'Trying to write beyond buffer length');
  815 +
  816 + verifsint(value, 0x7fff, -0x8000);
  817 + }
  818 +
  819 + if (value >= 0) {
  820 + writeUInt16(buffer, value, offset, isBigEndian, noAssert);
  821 + } else {
  822 + writeUInt16(buffer, 0xffff + value + 1, offset, isBigEndian, noAssert);
  823 + }
  824 +}
  825 +
  826 +Buffer.prototype.writeInt16LE = function(value, offset, noAssert) {
  827 + writeInt16(this, value, offset, false, noAssert);
  828 +};
  829 +
  830 +Buffer.prototype.writeInt16BE = function(value, offset, noAssert) {
  831 + writeInt16(this, value, offset, true, noAssert);
  832 +};
  833 +
  834 +function writeInt32(buffer, value, offset, isBigEndian, noAssert) {
  835 + if (!noAssert) {
  836 + assert.ok(value !== undefined && value !== null,
  837 + 'missing value');
  838 +
  839 + assert.ok(typeof (isBigEndian) === 'boolean',
  840 + 'missing or invalid endian');
  841 +
  842 + assert.ok(offset !== undefined && offset !== null,
  843 + 'missing offset');
  844 +
  845 + assert.ok(offset + 3 < buffer.length,
  846 + 'Trying to write beyond buffer length');
  847 +
  848 + verifsint(value, 0x7fffffff, -0x80000000);
  849 + }
  850 +
  851 + if (value >= 0) {
  852 + writeUInt32(buffer, value, offset, isBigEndian, noAssert);
  853 + } else {
  854 + writeUInt32(buffer, 0xffffffff + value + 1, offset, isBigEndian, noAssert);
  855 + }
  856 +}
  857 +
  858 +Buffer.prototype.writeInt32LE = function(value, offset, noAssert) {
  859 + writeInt32(this, value, offset, false, noAssert);
  860 +};
  861 +
  862 +Buffer.prototype.writeInt32BE = function(value, offset, noAssert) {
  863 + writeInt32(this, value, offset, true, noAssert);
  864 +};
  865 +
  866 +function writeFloat(buffer, value, offset, isBigEndian, noAssert) {
  867 + if (!noAssert) {
  868 + assert.ok(value !== undefined && value !== null,
  869 + 'missing value');
  870 +
  871 + assert.ok(typeof (isBigEndian) === 'boolean',
  872 + 'missing or invalid endian');
  873 +
  874 + assert.ok(offset !== undefined && offset !== null,
  875 + 'missing offset');
  876 +
  877 + assert.ok(offset + 3 < buffer.length,
  878 + 'Trying to write beyond buffer length');
  879 +
  880 + verifIEEE754(value, 3.4028234663852886e+38, -3.4028234663852886e+38);
  881 + }
  882 +
  883 + require('buffer_ieee754').writeIEEE754(buffer, value, offset, isBigEndian,
  884 + 23, 4);
  885 +}
  886 +
  887 +Buffer.prototype.writeFloatLE = function(value, offset, noAssert) {
  888 + writeFloat(this, value, offset, false, noAssert);
  889 +};
  890 +
  891 +Buffer.prototype.writeFloatBE = function(value, offset, noAssert) {
  892 + writeFloat(this, value, offset, true, noAssert);
  893 +};
  894 +
  895 +function writeDouble(buffer, value, offset, isBigEndian, noAssert) {
  896 + if (!noAssert) {
  897 + assert.ok(value !== undefined && value !== null,
  898 + 'missing value');
  899 +
  900 + assert.ok(typeof (isBigEndian) === 'boolean',
  901 + 'missing or invalid endian');
  902 +
  903 + assert.ok(offset !== undefined && offset !== null,
  904 + 'missing offset');
  905 +
  906 + assert.ok(offset + 7 < buffer.length,
  907 + 'Trying to write beyond buffer length');
  908 +
  909 + verifIEEE754(value, 1.7976931348623157E+308, -1.7976931348623157E+308);
  910 + }
  911 +
  912 + require('buffer_ieee754').writeIEEE754(buffer, value, offset, isBigEndian,
  913 + 52, 8);
  914 +}
  915 +
  916 +Buffer.prototype.writeDoubleLE = function(value, offset, noAssert) {
  917 + writeDouble(this, value, offset, false, noAssert);
  918 +};
  919 +
  920 +Buffer.prototype.writeDoubleBE = function(value, offset, noAssert) {
  921 + writeDouble(this, value, offset, true, noAssert);
  922 +};
  923 +
  924 +SlowBuffer.prototype.readUInt8 = Buffer.prototype.readUInt8;
  925 +SlowBuffer.prototype.readUInt16LE = Buffer.prototype.readUInt16LE;
  926 +SlowBuffer.prototype.readUInt16BE = Buffer.prototype.readUInt16BE;
  927 +SlowBuffer.prototype.readUInt32LE = Buffer.prototype.readUInt32LE;
  928 +SlowBuffer.prototype.readUInt32BE = Buffer.prototype.readUInt32BE;
  929 +SlowBuffer.prototype.readInt8 = Buffer.prototype.readInt8;
  930 +SlowBuffer.prototype.readInt16LE = Buffer.prototype.readInt16LE;
  931 +SlowBuffer.prototype.readInt16BE = Buffer.prototype.readInt16BE;
  932 +SlowBuffer.prototype.readInt32LE = Buffer.prototype.readInt32LE;
  933 +SlowBuffer.prototype.readInt32BE = Buffer.prototype.readInt32BE;
  934 +SlowBuffer.prototype.readFloatLE = Buffer.prototype.readFloatLE;
  935 +SlowBuffer.prototype.readFloatBE = Buffer.prototype.readFloatBE;
  936 +SlowBuffer.prototype.readDoubleLE = Buffer.prototype.readDoubleLE;
  937 +SlowBuffer.prototype.readDoubleBE = Buffer.prototype.readDoubleBE;
  938 +SlowBuffer.prototype.writeUInt8 = Buffer.prototype.writeUInt8;
  939 +SlowBuffer.prototype.writeUInt16LE = Buffer.prototype.writeUInt16LE;
  940 +SlowBuffer.prototype.writeUInt16BE = Buffer.prototype.writeUInt16BE;
  941 +SlowBuffer.prototype.writeUInt32LE = Buffer.prototype.writeUInt32LE;
  942 +SlowBuffer.prototype.writeUInt32BE = Buffer.prototype.writeUInt32BE;
  943 +SlowBuffer.prototype.writeInt8 = Buffer.prototype.writeInt8;
  944 +SlowBuffer.prototype.writeInt16LE = Buffer.prototype.writeInt16LE;
  945 +SlowBuffer.prototype.writeInt16BE = Buffer.prototype.writeInt16BE;
  946 +SlowBuffer.prototype.writeInt32LE = Buffer.prototype.writeInt32LE;
  947 +SlowBuffer.prototype.writeInt32BE = Buffer.prototype.writeInt32BE;
  948 +SlowBuffer.prototype.writeFloatLE = Buffer.prototype.writeFloatLE;
  949 +SlowBuffer.prototype.writeFloatBE = Buffer.prototype.writeFloatBE;
  950 +SlowBuffer.prototype.writeDoubleLE = Buffer.prototype.writeDoubleLE;
  951 +SlowBuffer.prototype.writeDoubleBE = Buffer.prototype.writeDoubleBE;
84 builtins/buffer_ieee754.js
... ... @@ -0,0 +1,84 @@
  1 +exports.readIEEE754 = function(buffer, offset, isBE, mLen, nBytes) {
  2 + var e, m,
  3 + eLen = nBytes * 8 - mLen - 1,
  4 + eMax = (1 << eLen) - 1,
  5 + eBias = eMax >> 1,
  6 + nBits = -7,
  7 + i = isBE ? 0 : (nBytes - 1),
  8 + d = isBE ? 1 : -1,
  9 + s = buffer[offset + i];
  10 +
  11 + i += d;
  12 +
  13 + e = s & ((1 << (-nBits)) - 1);
  14 + s >>= (-nBits);
  15 + nBits += eLen;
  16 + for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8);
  17 +
  18 + m = e & ((1 << (-nBits)) - 1);
  19 + e >>= (-nBits);
  20 + nBits += mLen;
  21 + for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8);
  22 +
  23 + if (e === 0) {
  24 + e = 1 - eBias;
  25 + } else if (e === eMax) {
  26 + return m ? NaN : ((s ? -1 : 1) * Infinity);
  27 + } else {
  28 + m = m + Math.pow(2, mLen);
  29 + e = e - eBias;
  30 + }
  31 + return (s ? -1 : 1) * m * Math.pow(2, e - mLen);
  32 +};
  33 +
  34 +exports.writeIEEE754 = function(buffer, value, offset, isBE, mLen, nBytes) {
  35 + var e, m, c,
  36 + eLen = nBytes * 8 - mLen - 1,
  37 + eMax = (1 << eLen) - 1,
  38 + eBias = eMax >> 1,
  39 + rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0),
  40 + i = isBE ? (nBytes - 1) : 0,
  41 + d = isBE ? -1 : 1,
  42 + s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0;
  43 +
  44 + value = Math.abs(value);
  45 +
  46 + if (isNaN(value) || value === Infinity) {
  47 + m = isNaN(value) ? 1 : 0;
  48 + e = eMax;
  49 + } else {
  50 + e = Math.floor(Math.log(value) / Math.LN2);
  51 + if (value * (c = Math.pow(2, -e)) < 1) {
  52 + e--;
  53 + c *= 2;
  54 + }
  55 + if (e + eBias >= 1) {
  56 + value += rt / c;
  57 + } else {
  58 + value += rt * Math.pow(2, 1 - eBias);
  59 + }
  60 + if (value * c >= 2) {
  61 + e++;
  62 + c /= 2;
  63 + }
  64 +
  65 + if (e + eBias >= eMax) {
  66 + m = 0;
  67 + e = eMax;
  68 + } else if (e + eBias >= 1) {
  69 + m = (value * c - 1) * Math.pow(2, mLen);
  70 + e = e + eBias;
  71 + } else {
  72 + m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen);
  73 + e = 0;
  74 + }
  75 + }
  76 +
  77 + for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8);
  78 +
  79 + e = (e << mLen) | m;
  80 + eLen += mLen;
  81 + for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8);
  82 +
  83 + buffer[offset + i - d] |= s * 128;
  84 +};

0 comments on commit 4b9c1db

Please sign in to comment.
Something went wrong with that request. Please try again.