mirror of
https://github.com/nodejs/node.git
synced 2024-11-29 23:16:30 +01:00
407 lines
9.8 KiB
JavaScript
407 lines
9.8 KiB
JavaScript
// Copyright Joyent, Inc. and other Node contributors.
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
// copy of this software and associated documentation files (the
|
|
// "Software"), to deal in the Software without restriction, including
|
|
// without limitation the rights to use, copy, modify, merge, publish,
|
|
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
|
// persons to whom the Software is furnished to do so, subject to the
|
|
// following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included
|
|
// in all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
|
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
var SlowBuffer = process.binding('buffer').SlowBuffer;
|
|
|
|
|
|
function toHex(n) {
|
|
if (n < 16) return '0' + n.toString(16);
|
|
return n.toString(16);
|
|
}
|
|
|
|
|
|
SlowBuffer.prototype.inspect = function() {
|
|
var out = [],
|
|
len = this.length;
|
|
for (var i = 0; i < len; i++) {
|
|
out[i] = toHex(this[i]);
|
|
}
|
|
return '<SlowBuffer ' + out.join(' ') + '>';
|
|
};
|
|
|
|
|
|
SlowBuffer.prototype.toString = function(encoding, start, end) {
|
|
encoding = String(encoding || 'utf8').toLowerCase();
|
|
start = +start || 0;
|
|
if (typeof end == 'undefined') end = this.length;
|
|
|
|
// Fastpath empty strings
|
|
if (+end == start) {
|
|
return '';
|
|
}
|
|
|
|
switch (encoding) {
|
|
case 'utf8':
|
|
case 'utf-8':
|
|
return this.utf8Slice(start, end);
|
|
|
|
case 'ascii':
|
|
return this.asciiSlice(start, end);
|
|
|
|
case 'binary':
|
|
return this.binarySlice(start, end);
|
|
|
|
case 'base64':
|
|
return this.base64Slice(start, end);
|
|
|
|
case 'ucs2':
|
|
case 'ucs-2':
|
|
return this.ucs2Slice(start, end);
|
|
|
|
default:
|
|
throw new Error('Unknown encoding');
|
|
}
|
|
};
|
|
|
|
|
|
SlowBuffer.prototype.write = function(string, offset, encoding) {
|
|
// Support both (string, offset, encoding)
|
|
// and the legacy (string, encoding, offset)
|
|
if (!isFinite(offset)) {
|
|
var swap = encoding;
|
|
encoding = offset;
|
|
offset = swap;
|
|
}
|
|
|
|
offset = +offset || 0;
|
|
encoding = String(encoding || 'utf8').toLowerCase();
|
|
|
|
switch (encoding) {
|
|
case 'utf8':
|
|
case 'utf-8':
|
|
return this.utf8Write(string, offset);
|
|
|
|
case 'ascii':
|
|
return this.asciiWrite(string, offset);
|
|
|
|
case 'binary':
|
|
return this.binaryWrite(string, offset);
|
|
|
|
case 'base64':
|
|
return this.base64Write(string, offset);
|
|
|
|
case 'ucs2':
|
|
case 'ucs-2':
|
|
return this.ucs2Write(string, offset);
|
|
|
|
default:
|
|
throw new Error('Unknown encoding');
|
|
}
|
|
};
|
|
|
|
|
|
// slice(start, end)
|
|
SlowBuffer.prototype.slice = function(start, end) {
|
|
if (end === undefined) end = this.length;
|
|
|
|
if (end > this.length) {
|
|
throw new Error('oob');
|
|
}
|
|
if (start > end) {
|
|
throw new Error('oob');
|
|
}
|
|
|
|
return new Buffer(this, end - start, +start);
|
|
};
|
|
|
|
|
|
// Buffer
|
|
|
|
function Buffer(subject, encoding, offset) {
|
|
if (!(this instanceof Buffer)) {
|
|
return new Buffer(subject, encoding, offset);
|
|
}
|
|
|
|
var type;
|
|
|
|
// Are we slicing?
|
|
if (typeof offset === 'number') {
|
|
this.length = encoding;
|
|
this.parent = subject;
|
|
this.offset = offset;
|
|
} else {
|
|
// Find the length
|
|
switch (type = typeof subject) {
|
|
case 'number':
|
|
this.length = subject;
|
|
break;
|
|
|
|
case 'string':
|
|
this.length = Buffer.byteLength(subject, encoding);
|
|
break;
|
|
|
|
case 'object': // Assume object is an array
|
|
this.length = subject.length;
|
|
break;
|
|
|
|
default:
|
|
throw new Error('First argument needs to be a number, ' +
|
|
'array or string.');
|
|
}
|
|
|
|
if (this.length > Buffer.poolSize) {
|
|
// Big buffer, just alloc one.
|
|
this.parent = new SlowBuffer(this.length);
|
|
this.offset = 0;
|
|
|
|
} else {
|
|
// Small buffer.
|
|
if (!pool || pool.length - pool.used < this.length) allocPool();
|
|
this.parent = pool;
|
|
this.offset = pool.used;
|
|
pool.used += this.length;
|
|
}
|
|
|
|
// Treat array-ish objects as a byte array.
|
|
if (isArrayIsh(subject)) {
|
|
for (var i = 0; i < this.length; i++) {
|
|
this.parent[i + this.offset] = subject[i];
|
|
}
|
|
} else if (type == 'string') {
|
|
// We are a string
|
|
this.length = this.write(subject, 0, encoding);
|
|
}
|
|
}
|
|
|
|
SlowBuffer.makeFastBuffer(this.parent, this, this.offset, this.length);
|
|
}
|
|
|
|
function isArrayIsh(subject) {
|
|
return Array.isArray(subject) || Buffer.isBuffer(subject) ||
|
|
subject && typeof subject === 'object' &&
|
|
typeof subject.length === 'number';
|
|
}
|
|
|
|
exports.SlowBuffer = SlowBuffer;
|
|
exports.Buffer = Buffer;
|
|
|
|
Buffer.poolSize = 8 * 1024;
|
|
var pool;
|
|
|
|
function allocPool() {
|
|
pool = new SlowBuffer(Buffer.poolSize);
|
|
pool.used = 0;
|
|
}
|
|
|
|
|
|
// Static methods
|
|
Buffer.isBuffer = function isBuffer(b) {
|
|
return b instanceof Buffer || b instanceof SlowBuffer;
|
|
};
|
|
|
|
|
|
// Inspect
|
|
Buffer.prototype.inspect = function inspect() {
|
|
var out = [],
|
|
len = this.length;
|
|
for (var i = 0; i < len; i++) {
|
|
out[i] = toHex(this.parent[i + this.offset]);
|
|
}
|
|
return '<Buffer ' + out.join(' ') + '>';
|
|
};
|
|
|
|
|
|
Buffer.prototype.get = function get(i) {
|
|
if (i < 0 || i >= this.length) throw new Error('oob');
|
|
return this.parent[this.offset + i];
|
|
};
|
|
|
|
|
|
Buffer.prototype.set = function set(i, v) {
|
|
if (i < 0 || i >= this.length) throw new Error('oob');
|
|
return this.parent[this.offset + i] = v;
|
|
};
|
|
|
|
|
|
// write(string, offset = 0, encoding = 'utf8')
|
|
Buffer.prototype.write = function(string, offset, encoding) {
|
|
if (!isFinite(offset)) {
|
|
var swap = encoding;
|
|
encoding = offset;
|
|
offset = swap;
|
|
}
|
|
|
|
offset = +offset || 0;
|
|
encoding = String(encoding || 'utf8').toLowerCase();
|
|
|
|
// Make sure we are not going to overflow
|
|
var maxLength = this.length - offset;
|
|
|
|
var ret;
|
|
switch (encoding) {
|
|
case 'utf8':
|
|
case 'utf-8':
|
|
ret = this.parent.utf8Write(string, this.offset + offset, maxLength);
|
|
break;
|
|
|
|
case 'ascii':
|
|
ret = this.parent.asciiWrite(string, this.offset + offset, maxLength);
|
|
break;
|
|
|
|
case 'binary':
|
|
ret = this.parent.binaryWrite(string, this.offset + offset, maxLength);
|
|
break;
|
|
|
|
case 'base64':
|
|
// Warning: maxLength not taken into account in base64Write
|
|
ret = this.parent.base64Write(string, this.offset + offset, maxLength);
|
|
break;
|
|
|
|
case 'ucs2':
|
|
case 'ucs-2':
|
|
ret = this.parent.ucs2Write(string, this.offset + offset, maxLength);
|
|
break;
|
|
|
|
default:
|
|
throw new Error('Unknown encoding');
|
|
}
|
|
|
|
Buffer._charsWritten = SlowBuffer._charsWritten;
|
|
|
|
return ret;
|
|
};
|
|
|
|
|
|
// toString(encoding, start=0, end=buffer.length)
|
|
Buffer.prototype.toString = function(encoding, start, end) {
|
|
encoding = String(encoding || 'utf8').toLowerCase();
|
|
|
|
if (typeof start == 'undefined' || start < 0) {
|
|
start = 0;
|
|
} else if (start > this.length) {
|
|
start = this.length;
|
|
}
|
|
|
|
if (typeof end == 'undefined' || end > this.length) {
|
|
end = this.length;
|
|
} else if (end < 0) {
|
|
end = 0;
|
|
}
|
|
|
|
start = start + this.offset;
|
|
end = end + this.offset;
|
|
|
|
switch (encoding) {
|
|
case 'utf8':
|
|
case 'utf-8':
|
|
return this.parent.utf8Slice(start, end);
|
|
|
|
case 'ascii':
|
|
return this.parent.asciiSlice(start, end);
|
|
|
|
case 'binary':
|
|
return this.parent.binarySlice(start, end);
|
|
|
|
case 'base64':
|
|
return this.parent.base64Slice(start, end);
|
|
|
|
case 'ucs2':
|
|
case 'ucs-2':
|
|
return this.parent.ucs2Slice(start, end);
|
|
|
|
default:
|
|
throw new Error('Unknown encoding');
|
|
}
|
|
};
|
|
|
|
|
|
// byteLength
|
|
Buffer.byteLength = SlowBuffer.byteLength;
|
|
|
|
|
|
// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)
|
|
Buffer.prototype.copy = function(target, target_start, start, end) {
|
|
var source = this;
|
|
start || (start = 0);
|
|
end || (end = this.length);
|
|
target_start || (target_start = 0);
|
|
|
|
if (end < start) throw new Error('sourceEnd < sourceStart');
|
|
|
|
// Copy 0 bytes; we're done
|
|
if (end === start) return 0;
|
|
if (target.length == 0 || source.length == 0) return 0;
|
|
|
|
if (target_start < 0 || target_start >= target.length) {
|
|
throw new Error('targetStart out of bounds');
|
|
}
|
|
|
|
if (start < 0 || start >= source.length) {
|
|
throw new Error('sourceStart out of bounds');
|
|
}
|
|
|
|
if (end < 0 || end > source.length) {
|
|
throw new Error('sourceEnd out of bounds');
|
|
}
|
|
|
|
// Are we oob?
|
|
if (end > this.length) {
|
|
end = this.length;
|
|
}
|
|
|
|
if (target.length - target_start < end - start) {
|
|
end = target.length - target_start + start;
|
|
}
|
|
|
|
return this.parent.copy(target.parent,
|
|
target_start + target.offset,
|
|
start + this.offset,
|
|
end + this.offset);
|
|
};
|
|
|
|
|
|
// slice(start, end)
|
|
Buffer.prototype.slice = function(start, end) {
|
|
if (end === undefined) end = this.length;
|
|
if (end > this.length) throw new Error('oob');
|
|
if (start > end) throw new Error('oob');
|
|
|
|
return new Buffer(this.parent, end - start, +start + this.offset);
|
|
};
|
|
|
|
|
|
// Legacy methods for backwards compatibility.
|
|
|
|
Buffer.prototype.utf8Slice = function(start, end) {
|
|
return this.toString('utf8', start, end);
|
|
};
|
|
|
|
Buffer.prototype.binarySlice = function(start, end) {
|
|
return this.toString('binary', start, end);
|
|
};
|
|
|
|
Buffer.prototype.asciiSlice = function(start, end) {
|
|
return this.toString('ascii', start, end);
|
|
};
|
|
|
|
Buffer.prototype.utf8Write = function(string, offset) {
|
|
return this.write(string, offset, 'utf8');
|
|
};
|
|
|
|
Buffer.prototype.binaryWrite = function(string, offset) {
|
|
return this.write(string, offset, 'binary');
|
|
};
|
|
|
|
Buffer.prototype.asciiWrite = function(string, offset) {
|
|
return this.write(string, offset, 'ascii');
|
|
};
|
|
|