0
0
mirror of https://github.com/nodejs/node.git synced 2024-12-01 16:10:02 +01:00
nodejs/lib/buffer.js

361 lines
8.1 KiB
JavaScript
Raw Normal View History

2010-09-08 08:52:40 +02:00
var SlowBuffer = process.binding('buffer').SlowBuffer;
2010-03-20 04:50:29 +01:00
2010-09-04 22:48:04 +02:00
2010-12-02 01:36:23 +01:00
function toHex(n) {
if (n < 16) return '0' + n.toString(16);
2010-03-25 17:50:49 +01:00
return n.toString(16);
}
2010-07-15 23:37:03 +02:00
2010-12-02 01:36:23 +01:00
SlowBuffer.prototype.inspect = function() {
var out = [],
len = this.length;
for (var i = 0; i < len; i++) {
out[i] = toHex(this[i]);
2010-03-25 17:50:49 +01:00
}
2010-12-02 01:36:23 +01:00
return '<SlowBuffer ' + out.join(' ') + '>';
2010-03-20 04:50:29 +01:00
};
2010-09-04 22:48:04 +02:00
2010-12-02 01:36:23 +01:00
SlowBuffer.prototype.toString = function(encoding, start, end) {
encoding = String(encoding || 'utf8').toLowerCase();
start = +start || 0;
2010-12-02 01:36:23 +01:00
if (typeof end == 'undefined') end = this.length;
// Fastpath empty strings
2010-09-05 20:10:59 +02:00
if (+end == start) {
return '';
}
switch (encoding) {
case 'utf8':
case 'utf-8':
2010-09-05 20:10:59 +02:00
return this.utf8Slice(start, end);
case 'ascii':
2010-09-05 20:10:59 +02:00
return this.asciiSlice(start, end);
case 'binary':
2010-09-05 20:10:59 +02:00
return this.binarySlice(start, end);
2010-07-23 22:52:44 +02:00
case 'base64':
2010-09-05 20:10:59 +02:00
return this.base64Slice(start, end);
2010-07-23 22:52:44 +02:00
default:
throw new Error('Unknown encoding');
}
2010-03-20 04:50:29 +01:00
};
2010-09-04 22:48:04 +02:00
2010-12-02 01:36:23 +01:00
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);
default:
throw new Error('Unknown encoding');
}
2010-08-20 08:29:06 +02:00
};
// slice(start, end)
2010-12-02 01:36:23 +01:00
SlowBuffer.prototype.slice = function(start, end) {
if (end > this.length) {
2010-12-02 01:36:23 +01:00
throw new Error('oob');
}
if (start > end) {
2010-12-02 01:36:23 +01:00
throw new Error('oob');
}
return new Buffer(this, end - start, +start);
};
2010-08-21 13:18:15 +02:00
// Buffer
2010-09-04 22:48:04 +02:00
2010-12-02 01:36:23 +01:00
function Buffer(subject, encoding, offset) {
2010-09-05 05:58:51 +02:00
if (!(this instanceof Buffer)) {
2010-09-05 22:30:30 +02:00
return new Buffer(subject, encoding, offset);
2010-09-05 05:58:51 +02:00
}
2010-09-08 07:00:16 +02:00
var type;
// Are we slicing?
2010-09-05 22:30:30 +02:00
if (typeof offset === 'number') {
this.length = encoding;
this.parent = subject;
this.offset = offset;
} else {
// Find the length
switch (type = typeof subject) {
case 'number':
2010-09-08 07:00:16 +02:00
this.length = subject;
break;
case 'string':
2010-09-08 07:00:16 +02:00
this.length = Buffer.byteLength(subject, encoding);
break;
case 'object': // Assume object is an array
2010-09-08 07:00:16 +02:00
this.length = subject.length;
break;
default:
2010-12-02 01:36:23 +01:00
throw new Error('First argument need to be an number,' +
'array or string.');
}
2010-09-08 07:00:16 +02:00
if (this.length > Buffer.poolSize) {
// Big buffer, just alloc one.
2010-09-08 07:36:41 +02:00
this.parent = new SlowBuffer(this.length);
this.offset = 0;
} else {
// Small buffer.
2010-09-08 07:00:16 +02:00
if (!pool || pool.length - pool.used < this.length) allocPool();
this.parent = pool;
this.offset = pool.used;
2010-09-08 07:00:16 +02:00
pool.used += this.length;
2010-09-08 07:36:41 +02:00
}
2010-09-08 07:36:41 +02:00
// Assume object is an array
if (Array.isArray(subject)) {
for (var i = 0; i < this.length; i++) {
this.parent[i + this.offset] = subject[i];
}
2010-09-08 07:36:41 +02:00
} else if (type == 'string') {
// We are a string
2010-10-18 20:15:20 +02:00
this.length = this.write(subject, 0, encoding);
}
}
2010-09-05 22:30:30 +02:00
SlowBuffer.makeFastBuffer(this.parent, this, this.offset, this.length);
}
2010-09-08 00:20:26 +02:00
exports.SlowBuffer = SlowBuffer;
2010-08-21 13:18:15 +02:00
exports.Buffer = Buffer;
2010-12-02 01:36:23 +01:00
Buffer.poolSize = 8 * 1024;
2010-09-06 21:50:13 +02:00
var pool;
2010-12-02 01:36:23 +01:00
function allocPool() {
2010-09-06 21:50:13 +02:00
pool = new SlowBuffer(Buffer.poolSize);
pool.used = 0;
}
2010-09-04 22:48:04 +02:00
// Static methods
2010-08-21 13:18:15 +02:00
Buffer.isBuffer = function isBuffer(b) {
return b instanceof Buffer || b instanceof SlowBuffer;
};
2010-09-04 22:48:04 +02:00
// Inspect
2010-08-21 13:18:15 +02:00
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]);
}
2010-12-02 01:36:23 +01:00
return '<Buffer ' + out.join(' ') + '>';
};
2010-09-04 22:48:04 +02:00
2010-12-02 01:36:23 +01:00
Buffer.prototype.get = function get(i) {
if (i < 0 || i >= this.length) throw new Error('oob');
return this.parent[this.offset + i];
};
2010-09-04 22:48:04 +02:00
2010-12-02 01:36:23 +01:00
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')
2010-12-02 01:36:23 +01:00
Buffer.prototype.write = function(string, offset, encoding) {
if (!isFinite(offset)) {
var swap = encoding;
encoding = offset;
offset = swap;
}
2010-09-05 22:30:30 +02:00
offset = +offset || 0;
encoding = String(encoding || 'utf8').toLowerCase();
// Make sure we are not going to overflow
2010-09-05 22:30:30 +02:00
var maxLength = this.length - offset;
2010-09-06 12:07:32 +02:00
var ret;
2010-09-05 22:30:30 +02:00
switch (encoding) {
case 'utf8':
case 'utf-8':
2010-09-06 12:07:32 +02:00
ret = this.parent.utf8Write(string, this.offset + offset, maxLength);
break;
2010-09-05 22:30:30 +02:00
case 'ascii':
2010-09-06 12:07:32 +02:00
ret = this.parent.asciiWrite(string, this.offset + offset, maxLength);
break;
2010-09-05 22:30:30 +02:00
case 'binary':
2010-09-06 12:07:32 +02:00
ret = this.parent.binaryWrite(string, this.offset + offset, maxLength);
break;
2010-09-05 22:30:30 +02:00
case 'base64':
2010-09-06 12:07:32 +02:00
// Warning: maxLength not taken into account in base64Write
ret = this.parent.base64Write(string, this.offset + offset, maxLength);
break;
2010-09-05 22:30:30 +02:00
default:
throw new Error('Unknown encoding');
}
2010-09-06 12:07:32 +02:00
Buffer._charsWritten = SlowBuffer._charsWritten;
return ret;
2010-09-04 22:48:04 +02:00
};
// toString(encoding, start=0, end=buffer.length)
2010-12-02 01:36:23 +01:00
Buffer.prototype.toString = function(encoding, start, end) {
2010-09-05 22:30:30 +02:00
encoding = String(encoding || 'utf8').toLowerCase();
2010-09-05 20:10:59 +02:00
if (typeof start == 'undefined' || start < 0) {
start = 0;
} else if (start > this.length) {
start = this.length;
}
2010-12-02 01:36:23 +01:00
if (typeof end == 'undefined' || end > this.length) {
end = this.length;
2010-09-05 20:10:59 +02:00
} else if (end < 0) {
end = 0;
}
2010-09-05 22:30:30 +02:00
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);
default:
throw new Error('Unknown encoding');
}
};
2010-09-04 22:48:04 +02:00
// byteLength
2010-08-21 13:18:15 +02:00
Buffer.byteLength = SlowBuffer.byteLength;
2010-09-04 22:48:04 +02:00
2010-11-30 04:59:01 +01:00
// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)
2010-12-02 01:36:23 +01:00
Buffer.prototype.copy = function(target, target_start, start, end) {
2010-09-05 20:10:59 +02:00
var source = this;
start || (start = 0);
2010-12-02 01:36:23 +01:00
end || (end = this.length);
2010-11-30 04:59:01 +01:00
target_start || (target_start = 0);
2010-12-02 01:36:23 +01:00
if (end < start) throw new Error('sourceEnd < sourceStart');
2010-09-05 20:10:59 +02:00
// 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) {
2010-12-02 01:36:23 +01:00
throw new Error('targetStart out of bounds');
2010-09-05 20:10:59 +02:00
}
if (start < 0 || start >= source.length) {
2010-12-02 01:36:23 +01:00
throw new Error('sourceStart out of bounds');
2010-09-05 20:10:59 +02:00
}
if (end < 0 || end > source.length) {
2010-12-02 01:36:23 +01:00
throw new Error('sourceEnd out of bounds');
2010-09-05 20:10:59 +02:00
}
// Are we oob?
if (end > this.length) {
end = this.length;
}
2010-09-05 20:10:59 +02:00
if (target.length - target_start < end - start) {
end = target.length - target_start + start;
}
2010-09-04 22:48:04 +02:00
return this.parent.copy(target.parent,
target_start + target.offset,
start + this.offset,
end + this.offset);
};
2010-09-04 22:48:04 +02:00
// slice(start, end)
2010-12-02 01:36:23 +01:00
Buffer.prototype.slice = function(start, end) {
2010-11-23 21:20:22 +01:00
if (end === undefined) end = this.length;
2010-12-02 01:36:23 +01:00
if (end > this.length) throw new Error('oob');
if (start > end) throw new Error('oob');
2010-09-05 22:30:30 +02:00
return new Buffer(this.parent, end - start, +start + this.offset);
};
2010-11-02 18:09:59 +01:00
// Legacy methods for backwards compatibility.
2010-12-02 01:36:23 +01:00
Buffer.prototype.utf8Slice = function(start, end) {
return this.toString('utf8', start, end);
2010-11-02 18:09:59 +01:00
};
2010-12-02 01:36:23 +01:00
Buffer.prototype.binarySlice = function(start, end) {
return this.toString('binary', start, end);
2010-11-02 18:09:59 +01:00
};
2010-12-02 01:36:23 +01:00
Buffer.prototype.asciiSlice = function(start, end) {
return this.toString('ascii', start, end);
2010-11-02 18:09:59 +01:00
};
2010-12-02 01:36:23 +01:00
Buffer.prototype.utf8Write = function(string, offset) {
return this.write(string, offset, 'utf8');
2010-11-02 18:09:59 +01:00
};
2010-12-02 01:36:23 +01:00
Buffer.prototype.binaryWrite = function(string, offset) {
return this.write(string, offset, 'binary');
2010-11-02 18:09:59 +01:00
};
2010-12-02 01:36:23 +01:00
Buffer.prototype.asciiWrite = function(string, offset) {
return this.write(string, offset, 'ascii');
2010-11-02 18:09:59 +01:00
};