buffer: implement new fill behavior
authorTrevor Norris <trev.norris@gmail.com>
Fri, 24 May 2013 17:58:30 +0000 (10:58 -0700)
committerTrevor Norris <trev.norris@gmail.com>
Tue, 18 Jun 2013 22:41:03 +0000 (15:41 -0700)
Old fill would take the char code of the first character and wrap around
the int to fit in the 127 range. Now fill will duplicate whatever string
is given through the entirety of the buffer.

Note: There is one bug around ending on a partial fill of any character
outside the ASCII range.

src/node_buffer.cc
test/simple/test-buffer.js

index 2e5115a..d7f63b2 100644 (file)
@@ -296,18 +296,42 @@ Handle<Value> Fill(const Arguments &args) {
   HandleScope scope(node_isolate);
 
   ARGS_THIS(args.This())
-  int value;
+  SLICE_START_END(args[1], args[2], obj_length)
 
-  if (args[0]->IsString()) {
-    String::AsciiValue at(args[0]);
-    value = (*at)[0];
-  } else {
-    value = static_cast<char>(args[0]->Int32Value());
+  if (args[0]->IsNumber()) {
+    int value = args[0]->Uint32Value() & 255;
+    memset(obj_data + start, value, length);
+    return args.This();
   }
 
-  SLICE_START_END(args[1], args[2], obj_length)
+  String::Utf8Value at(args[0]);
+  size_t at_length = at.length();
+
+  // optimize single ascii character case
+  if (at_length == 1) {
+    int value = static_cast<int>((*at)[0]);
+    memset(obj_data + start, value, length);
+    return args.This();
+  }
+
+  size_t in_there = at_length;
+  char* ptr = obj_data + start + at_length;
 
-  memset(obj_data + start, value, length);
+  memcpy(obj_data + start, *at, MIN(at_length, length));
+
+  if (at_length >= length)
+    return args.This();
+
+  while (in_there < length - in_there) {
+    memcpy(ptr, obj_data + start, in_there);
+    ptr += in_there;
+    in_there *= 2;
+  }
+
+  if (in_there < length) {
+    memcpy(ptr, obj_data + start, length - in_there);
+    in_there = length;
+  }
 
   return args.This();
 }
index 19fa4ea..6975c8e 100644 (file)
@@ -120,6 +120,10 @@ for (var i = 0; i < b.length; i++) {
   assert.strictEqual(cntr, b[i]);
 }
 
+// copy string longer than buffer length (failure will segfault)
+var bb = new Buffer(10);
+bb.fill('hello crazy world');
+
 
 var caught_error = null;
 
@@ -637,6 +641,12 @@ for (var i = 0; i < 16; i++) assert.equal(0, b[i]);
 for (; i < 32; i++) assert.equal(1, b[i]);
 for (; i < b.length; i++) assert.equal(0, b[i]);
 
+var buf = new Buffer(10);
+buf.fill('abc');
+assert.equal(buf.toString(), 'abcabcabca');
+buf.fill('է');
+assert.equal(buf.toString(), 'էէէէէ');
+
 ['ucs2', 'ucs-2', 'utf16le', 'utf-16le'].forEach(function(encoding) {
   var b = new Buffer(10);
   b.write('あいうえお', encoding);