buffer: add compare and equals methods
compare() works like String.localeCompare such that: Buffer.compare(a, b) === a.compare(b); equals() does a native check to see if two buffers are equal. Signed-off-by: Trevor Norris <trev.norris@gmail.com>
This commit is contained in:
parent
681fe599d7
commit
226f98a356
42
benchmark/buffers/buffer-compare.js
Normal file
42
benchmark/buffers/buffer-compare.js
Normal file
@ -0,0 +1,42 @@
|
||||
// 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 common = require('../common.js');
|
||||
|
||||
var bench = common.createBenchmark(main, {
|
||||
size: [16, 512, 1024, 4096, 16386],
|
||||
millions: [1]
|
||||
});
|
||||
|
||||
function main(conf) {
|
||||
var iter = (conf.millions >>> 0) * 1e6;
|
||||
var size = (conf.size >>> 0);
|
||||
var b0 = new Buffer(size).fill('a');
|
||||
var b1 = new Buffer(size).fill('a');
|
||||
|
||||
b1[size - 1] = 'b'.charCodeAt(0);
|
||||
|
||||
bench.start();
|
||||
for (var i = 0; i < iter; i++) {
|
||||
Buffer.compare(b0, b1);
|
||||
}
|
||||
bench.end(iter / 1e6);
|
||||
}
|
@ -115,6 +115,18 @@ If totalLength is not provided, it is read from the buffers in the list.
|
||||
However, this adds an additional loop to the function, so it is faster
|
||||
to provide the length explicitly.
|
||||
|
||||
### Class Method: Buffer.compare(buf1, buf2)
|
||||
|
||||
* `buf1` {Buffer}
|
||||
* `buf2` {Buffer}
|
||||
|
||||
The same as [`buf1.compare(buf2)`](#buffer_buf_compare_otherbuffer). Useful
|
||||
for sorting an Array of Buffers:
|
||||
|
||||
var arr = [Buffer('1234'), Buffer('0123')];
|
||||
arr.sort(Buffer.compare);
|
||||
|
||||
|
||||
### buf.length
|
||||
|
||||
* Number
|
||||
@ -207,6 +219,21 @@ Example: copy an ASCII string into a buffer, one byte at a time:
|
||||
|
||||
// node.js
|
||||
|
||||
### buf.equals(otherBuffer)
|
||||
|
||||
* `otherBuffer` {Buffer}
|
||||
|
||||
Returns a boolean of whether `this` and `otherBuffer` have the same
|
||||
bytes.
|
||||
|
||||
### buf.compare(otherBuffer)
|
||||
|
||||
* `otherBuffer` {Buffer}
|
||||
|
||||
Returns a number indicating whether `this` comes before or after or is
|
||||
the same as the `otherBuffer` in sort order.
|
||||
|
||||
|
||||
### buf.copy(targetBuffer, [targetStart], [sourceStart], [sourceEnd])
|
||||
|
||||
* `targetBuffer` Buffer object - Buffer to copy into
|
||||
|
@ -130,6 +130,15 @@ Buffer.isBuffer = function isBuffer(b) {
|
||||
};
|
||||
|
||||
|
||||
Buffer.compare = function compare(a, b) {
|
||||
if (!(a instanceof Buffer) ||
|
||||
!(b instanceof Buffer))
|
||||
throw new TypeError('Arguments must be Buffers');
|
||||
|
||||
return internal.compare(b, a);
|
||||
};
|
||||
|
||||
|
||||
Buffer.isEncoding = function(encoding) {
|
||||
switch ((encoding + '').toLowerCase()) {
|
||||
case 'hex':
|
||||
@ -256,6 +265,14 @@ Buffer.prototype.toString = function(encoding, start, end) {
|
||||
};
|
||||
|
||||
|
||||
Buffer.prototype.equals = function equals(b) {
|
||||
if (!(b instanceof Buffer))
|
||||
throw new TypeError('Argument must be a Buffer');
|
||||
|
||||
return internal.compare(this, b) === 0;
|
||||
};
|
||||
|
||||
|
||||
// Inspect
|
||||
Buffer.prototype.inspect = function inspect() {
|
||||
var str = '';
|
||||
@ -269,6 +286,14 @@ Buffer.prototype.inspect = function inspect() {
|
||||
};
|
||||
|
||||
|
||||
Buffer.prototype.compare = function compare(b) {
|
||||
if (!(b instanceof Buffer))
|
||||
throw new TypeError('Argument must be a Buffer');
|
||||
|
||||
return internal.compare(this, b);
|
||||
};
|
||||
|
||||
|
||||
// XXX remove in v0.13
|
||||
Buffer.prototype.get = util.deprecate(function get(offset) {
|
||||
offset = ~~offset;
|
||||
|
@ -69,6 +69,7 @@ namespace node {
|
||||
V(change_string, "change") \
|
||||
V(close_string, "close") \
|
||||
V(code_string, "code") \
|
||||
V(compare_string, "compare") \
|
||||
V(ctime_string, "ctime") \
|
||||
V(cwd_string, "cwd") \
|
||||
V(debug_port_string, "debugPort") \
|
||||
|
@ -607,6 +607,27 @@ void ByteLength(const FunctionCallbackInfo<Value> &args) {
|
||||
}
|
||||
|
||||
|
||||
void Compare(const FunctionCallbackInfo<Value> &args) {
|
||||
Local<Object> obj_a = args[0].As<Object>();
|
||||
char* obj_a_data =
|
||||
static_cast<char*>(obj_a->GetIndexedPropertiesExternalArrayData());
|
||||
size_t obj_a_len = obj_a->GetIndexedPropertiesExternalArrayDataLength();
|
||||
|
||||
Local<Object> obj_b = args[1].As<Object>();
|
||||
char* obj_b_data =
|
||||
static_cast<char*>(obj_b->GetIndexedPropertiesExternalArrayData());
|
||||
size_t obj_b_len = obj_b->GetIndexedPropertiesExternalArrayDataLength();
|
||||
|
||||
size_t cmp_length = MIN(obj_a_len, obj_b_len);
|
||||
|
||||
int32_t val = memcmp(obj_a_data, obj_b_data, cmp_length);
|
||||
if (!val)
|
||||
val = obj_a_len - obj_b_len;
|
||||
|
||||
args.GetReturnValue().Set(val);
|
||||
}
|
||||
|
||||
|
||||
// pass Buffer object to load prototype methods
|
||||
void SetupBufferJS(const FunctionCallbackInfo<Value>& args) {
|
||||
Environment* env = Environment::GetCurrent(args.GetIsolate());
|
||||
@ -663,6 +684,9 @@ void SetupBufferJS(const FunctionCallbackInfo<Value>& args) {
|
||||
internal->Set(env->byte_length_string(),
|
||||
FunctionTemplate::New(
|
||||
env->isolate(), ByteLength)->GetFunction());
|
||||
internal->Set(env->compare_string(),
|
||||
FunctionTemplate::New(
|
||||
env->isolate(), Compare)->GetFunction());
|
||||
}
|
||||
|
||||
|
||||
|
@ -1037,3 +1037,48 @@ assert.equal(
|
||||
crypto.createHash('sha1').update(b1).digest('hex'),
|
||||
crypto.createHash('sha1').update(b2).digest('hex')
|
||||
);
|
||||
|
||||
// Test Compare
|
||||
var b = new Buffer(1).fill('a');
|
||||
var c = new Buffer(1).fill('c');
|
||||
var d = new Buffer(2).fill('aa');
|
||||
|
||||
assert.equal(b.compare(c), -2);
|
||||
assert.equal(c.compare(d), 2);
|
||||
assert.equal(d.compare(b), 1);
|
||||
assert.equal(b.compare(d), -1);
|
||||
|
||||
assert.equal(Buffer.compare(b, c), 2);
|
||||
assert.equal(Buffer.compare(c, d), -2);
|
||||
assert.equal(Buffer.compare(d, b), -1);
|
||||
assert.equal(Buffer.compare(b, d), 1);
|
||||
|
||||
assert.throws(function() {
|
||||
var b = new Buffer(1);
|
||||
Buffer.compare(b, 'abc');
|
||||
});
|
||||
|
||||
assert.throws(function() {
|
||||
var b = new Buffer(1);
|
||||
Buffer.compare('abc', b);
|
||||
});
|
||||
|
||||
assert.throws(function() {
|
||||
var b = new Buffer(1);
|
||||
b.compare('abc');
|
||||
});
|
||||
|
||||
// Test Equals
|
||||
var b = new Buffer(5).fill('abcdf');
|
||||
var c = new Buffer(5).fill('abcdf');
|
||||
var d = new Buffer(5).fill('abcde');
|
||||
var e = new Buffer(6).fill('abcdef');
|
||||
|
||||
assert.ok(b.equals(c));
|
||||
assert.ok(!c.equals(d));
|
||||
assert.ok(!d.equals(e));
|
||||
|
||||
assert.throws(function() {
|
||||
var b = new Buffer(1);
|
||||
b.equals('abc');
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user