@@ -545,6 +545,72 @@ Handle<Value> Buffer::Ucs2Write(const Arguments &args) {
545545}
546546
547547
548+ inline unsigned hex2bin (char c) {
549+ if (c >= ' 0' && c <= ' 9' ) return c - ' 0' ;
550+ if (c >= ' A' && c <= ' F' ) return 10 + (c - ' A' );
551+ if (c >= ' a' && c <= ' f' ) return 10 + (c - ' a' );
552+ return static_cast <unsigned >(-1 );
553+ }
554+
555+
556+ Handle<Value> Buffer::HexWrite (const Arguments& args) {
557+ HandleScope scope;
558+ Buffer* parent = ObjectWrap::Unwrap<Buffer>(args.This ());
559+
560+ if (args[0 ]->IsString () == false ) {
561+ return ThrowTypeError (" Argument must be a string" );
562+ }
563+
564+ Local<String> s = args[0 ].As <String>();
565+
566+ if (s->Length () % 2 != 0 ) {
567+ return ThrowTypeError (" Invalid hex string" );
568+ }
569+
570+ uint32_t start = args[1 ]->Uint32Value ();
571+ uint32_t size = args[2 ]->Uint32Value ();
572+ uint32_t end = start + size;
573+
574+ if (start >= parent->length_ ) {
575+ Local<Integer> val = Integer::New (0 , node_isolate);
576+ constructor_template->GetFunction ()->Set (chars_written_sym, val);
577+ return scope.Close (val);
578+ }
579+
580+ if (end < start || end > parent->length_ ) { // Overflow + bounds check.
581+ end = parent->length_ ;
582+ size = parent->length_ - start;
583+ }
584+
585+ if (size == 0 ) {
586+ Local<Integer> val = Integer::New (0 , node_isolate);
587+ constructor_template->GetFunction ()->Set (chars_written_sym, val);
588+ return scope.Close (val);
589+ }
590+
591+ char * dst = parent->data_ + start;
592+ String::AsciiValue string (s);
593+ const char * src = *string;
594+ uint32_t max = string.length () / 2 ;
595+
596+ if (max > size) {
597+ max = size;
598+ }
599+
600+ for (uint32_t i = 0 ; i < max; ++i) {
601+ unsigned a = hex2bin (src[i * 2 + 0 ]);
602+ unsigned b = hex2bin (src[i * 2 + 1 ]);
603+ if (!~a || !~b) return ThrowTypeError (" Invalid hex string" );
604+ dst[i] = a * 16 + b;
605+ }
606+
607+ constructor_template->GetFunction ()->Set (chars_written_sym,
608+ Integer::New (max * 2 , node_isolate));
609+
610+ return scope.Close (Integer::New (max, node_isolate));
611+ }
612+
613+
548614// var charsWritten = buffer.asciiWrite(string, offset);
549615Handle<Value> Buffer::AsciiWrite (const Arguments &args) {
550616 HandleScope scope;
@@ -950,6 +1016,7 @@ void Buffer::Initialize(Handle<Object> target) {
9501016 NODE_SET_PROTOTYPE_METHOD (constructor_template, " binaryWrite" , Buffer::BinaryWrite);
9511017 NODE_SET_PROTOTYPE_METHOD (constructor_template, " base64Write" , Buffer::Base64Write);
9521018 NODE_SET_PROTOTYPE_METHOD (constructor_template, " ucs2Write" , Buffer::Ucs2Write);
1019+ NODE_SET_PROTOTYPE_METHOD (constructor_template, " hexWrite" , Buffer::HexWrite);
9531020 NODE_SET_PROTOTYPE_METHOD (constructor_template, " readFloatLE" , Buffer::ReadFloatLE);
9541021 NODE_SET_PROTOTYPE_METHOD (constructor_template, " readFloatBE" , Buffer::ReadFloatBE);
9551022 NODE_SET_PROTOTYPE_METHOD (constructor_template, " readDoubleLE" , Buffer::ReadDoubleLE);
0 commit comments