diff --git a/lib/buffer.js b/lib/buffer.js index 7d52c32df2a..c4c0e7657ee 100644 --- a/lib/buffer.js +++ b/lib/buffer.js @@ -74,36 +74,6 @@ SlowBuffer.prototype.toString = function(encoding, start, end) { }; -SlowBuffer.prototype.hexWrite = function(string, offset, length) { - offset = +offset || 0; - var remaining = this.length - offset; - if (!length) { - length = remaining; - } else { - length = +length; - if (length > remaining) { - length = remaining; - } - } - - // must be an even number of digits - var strLen = string.length; - if (strLen % 2) { - throw new TypeError('Invalid hex string'); - } - if (length > strLen / 2) { - length = strLen / 2; - } - for (var i = 0; i < length; i++) { - var byte = parseInt(string.substr(i * 2, 2), 16); - if (isNaN(byte)) throw new TypeError('Invalid hex string'); - this[offset + i] = byte; - } - SlowBuffer._charsWritten = i * 2; - return i; -}; - - SlowBuffer.prototype.write = function(string, offset, length, encoding) { // Support both (string, offset, length, encoding) // and the legacy (string, encoding, offset, length) diff --git a/src/node_buffer.cc b/src/node_buffer.cc index f6709cbbd89..be4d815bc63 100644 --- a/src/node_buffer.cc +++ b/src/node_buffer.cc @@ -545,6 +545,72 @@ Handle Buffer::Ucs2Write(const Arguments &args) { } +inline unsigned hex2bin(char c) { + if (c >= '0' && c <= '9') return c - '0'; + if (c >= 'A' && c <= 'F') return 10 + (c - 'A'); + if (c >= 'a' && c <= 'f') return 10 + (c - 'a'); + return static_cast(-1); +} + + +Handle Buffer::HexWrite(const Arguments& args) { + HandleScope scope; + Buffer* parent = ObjectWrap::Unwrap(args.This()); + + if (args[0]->IsString() == false) { + return ThrowTypeError("Argument must be a string"); + } + + Local s = args[0].As(); + + if (s->Length() % 2 != 0) { + return ThrowTypeError("Invalid hex string"); + } + + uint32_t start = args[1]->Uint32Value(); + uint32_t size = args[2]->Uint32Value(); + uint32_t end = start + size; + + if (start >= parent->length_) { + Local val = Integer::New(0, node_isolate); + constructor_template->GetFunction()->Set(chars_written_sym, val); + return scope.Close(val); + } + + if (end < start || end > parent->length_) { // Overflow + bounds check. + end = parent->length_; + size = parent->length_ - start; + } + + if (size == 0) { + Local val = Integer::New(0, node_isolate); + constructor_template->GetFunction()->Set(chars_written_sym, val); + return scope.Close(val); + } + + char* dst = parent->data_ + start; + String::AsciiValue string(s); + const char* src = *string; + uint32_t max = string.length() / 2; + + if (max > size) { + max = size; + } + + for (uint32_t i = 0; i < max; ++i) { + unsigned a = hex2bin(src[i * 2 + 0]); + unsigned b = hex2bin(src[i * 2 + 1]); + if (!~a || !~b) return ThrowTypeError("Invalid hex string"); + dst[i] = a * 16 + b; + } + + constructor_template->GetFunction()->Set(chars_written_sym, + Integer::New(max * 2, node_isolate)); + + return scope.Close(Integer::New(max, node_isolate)); +} + + // var charsWritten = buffer.asciiWrite(string, offset); Handle Buffer::AsciiWrite(const Arguments &args) { HandleScope scope; @@ -950,6 +1016,7 @@ void Buffer::Initialize(Handle target) { NODE_SET_PROTOTYPE_METHOD(constructor_template, "binaryWrite", Buffer::BinaryWrite); NODE_SET_PROTOTYPE_METHOD(constructor_template, "base64Write", Buffer::Base64Write); NODE_SET_PROTOTYPE_METHOD(constructor_template, "ucs2Write", Buffer::Ucs2Write); + NODE_SET_PROTOTYPE_METHOD(constructor_template, "hexWrite", Buffer::HexWrite); NODE_SET_PROTOTYPE_METHOD(constructor_template, "readFloatLE", Buffer::ReadFloatLE); NODE_SET_PROTOTYPE_METHOD(constructor_template, "readFloatBE", Buffer::ReadFloatBE); NODE_SET_PROTOTYPE_METHOD(constructor_template, "readDoubleLE", Buffer::ReadDoubleLE); diff --git a/src/node_buffer.h b/src/node_buffer.h index 27991fcfc07..5743f9b2618 100644 --- a/src/node_buffer.h +++ b/src/node_buffer.h @@ -124,6 +124,7 @@ class NODE_EXTERN Buffer: public ObjectWrap { static v8::Handle AsciiWrite(const v8::Arguments &args); static v8::Handle Utf8Write(const v8::Arguments &args); static v8::Handle Ucs2Write(const v8::Arguments &args); + static v8::Handle HexWrite(const v8::Arguments &args); static v8::Handle ReadFloatLE(const v8::Arguments &args); static v8::Handle ReadFloatBE(const v8::Arguments &args); static v8::Handle ReadDoubleLE(const v8::Arguments &args);