Add buffer.copy
authorRyan Dahl <ry@tinyclouds.org>
Mon, 5 Apr 2010 01:58:55 +0000 (18:58 -0700)
committerRyan Dahl <ry@tinyclouds.org>
Mon, 5 Apr 2010 01:59:40 +0000 (18:59 -0700)
src/node_buffer.cc
src/node_buffer.h
test/simple/test-buffer.js

index c16ead3..326a97a 100644 (file)
@@ -4,6 +4,8 @@
 #include <stdlib.h> // malloc, free
 #include <v8.h>
 
+#include <string.h> // memcpy
+
 #include <arpa/inet.h>  // htons, htonl
 
 #include <node.h>
@@ -225,6 +227,55 @@ Handle<Value> Buffer::Slice(const Arguments &args) {
 }
 
 
+// var bytesCopied = buffer.copy(target, targetStart, sourceStart, sourceEnd);
+Handle<Value> Buffer::Copy(const Arguments &args) {
+  HandleScope scope;
+
+  Buffer *source = ObjectWrap::Unwrap<Buffer>(args.This());
+
+  if (!Buffer::HasInstance(args[0])) {
+    return ThrowException(Exception::TypeError(String::New(
+            "First arg should be a Buffer")));
+  }
+
+  Buffer *target = ObjectWrap::Unwrap<Buffer>(args[0]->ToObject());
+
+  ssize_t target_start = args[1]->Int32Value();
+  ssize_t source_start = args[2]->Int32Value();
+  ssize_t source_end = args[3]->IsInt32() ? args[3]->Int32Value()
+                                          : source->length();
+
+  if (source_end < source_start) {
+    return ThrowException(Exception::Error(String::New(
+            "sourceEnd < sourceStart")));
+  }
+
+  if (target_start >= target->length()) {
+    return ThrowException(Exception::Error(String::New(
+            "targetStart out of bounds")));
+  }
+
+  if (source_start >= source->length()) {
+    return ThrowException(Exception::Error(String::New(
+            "sourceStart out of bounds")));
+  }
+
+  if (source_end > source->length()) {
+    return ThrowException(Exception::Error(String::New(
+            "sourceEnd out of bounds")));
+  }
+
+  ssize_t to_copy = MIN(source_end - source_start,
+                        target->length() - target_start);
+
+  memcpy((void*)(target->data() + target_start),
+         (const void*)(source->data() + source_start),
+         to_copy);
+
+  return scope.Close(Integer::New(to_copy));
+}
+
+
 // var charsWritten = buffer.utf8Write(string, offset);
 Handle<Value> Buffer::Utf8Write(const Arguments &args) {
   HandleScope scope;
@@ -414,6 +465,7 @@ void Buffer::Initialize(Handle<Object> target) {
   NODE_SET_PROTOTYPE_METHOD(constructor_template, "asciiWrite", Buffer::AsciiWrite);
   NODE_SET_PROTOTYPE_METHOD(constructor_template, "binaryWrite", Buffer::BinaryWrite);
   NODE_SET_PROTOTYPE_METHOD(constructor_template, "unpack", Buffer::Unpack);
+  NODE_SET_PROTOTYPE_METHOD(constructor_template, "copy", Buffer::Copy);
 
   NODE_SET_METHOD(constructor_template->GetFunction(),
                   "byteLength",
index 9f497c5..e746cde 100644 (file)
@@ -53,6 +53,7 @@ class Buffer : public ObjectWrap {
   static v8::Handle<v8::Value> Utf8Write(const v8::Arguments &args);
   static v8::Handle<v8::Value> ByteLength(const v8::Arguments &args);
   static v8::Handle<v8::Value> Unpack(const v8::Arguments &args);
+  static v8::Handle<v8::Value> Copy(const v8::Arguments &args);
 
   int AsciiWrite(char *string, int offset, int length);
   int Utf8Write(char *string, int offset, int length);
index d175c4d..18fe7e6 100644 (file)
@@ -17,6 +17,16 @@ for (var i = 0; i < 1024; i++) {
   assert.equal(i % 256, b[i]);
 }
 
+var c = new Buffer(512);
+
+var copied = b.copy(c, 0, 0, 512);
+assert.equal(512, copied);
+for (var i = 0; i < c.length; i++) {
+  print('.');
+  assert.equal(i % 256, c[i]);
+}
+
+
 var asciiString = "hello world";
 var offset = 100;
 for (var j = 0; j < 500; j++) {