Implement buffer.toString('base64')
authorRyan Dahl <ry@tinyclouds.org>
Fri, 23 Jul 2010 20:52:44 +0000 (13:52 -0700)
committerRyan Dahl <ry@tinyclouds.org>
Fri, 23 Jul 2010 20:52:44 +0000 (13:52 -0700)
lib/buffer.js
src/node_buffer.cc
src/node_buffer.h
test/simple/test-buffer.js

index ef46482..e58a34b 100644 (file)
@@ -42,6 +42,9 @@ Buffer.prototype.toString = function (encoding, start, stop) {
     case 'binary':
       return this.binarySlice(start, stop);
 
+    case 'base64':
+      return this.base64Slice(start, stop);
+
     default:
       throw new Error('Unknown encoding');
   }
index ce959d8..c896b04 100644 (file)
@@ -272,6 +272,82 @@ Handle<Value> Buffer::Utf8Slice(const Arguments &args) {
   return scope.Close(string);
 }
 
+static char* base64_table = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+                            "abcdefghijklmnopqrstuvwxyz"
+                            "0123456789+/";
+
+
+Handle<Value> Buffer::Base64Slice(const Arguments &args) {
+  HandleScope scope;
+  Buffer *parent = ObjectWrap::Unwrap<Buffer>(args.This());
+  SLICE_ARGS(args[0], args[1])
+
+  int n = end - start;
+  int out_len = (n + 2 - ((n + 2) % 3)) / 3 * 4;
+  char *out = new char[out_len];
+
+  char bitbuf[3];
+  int i = start; // data() index
+  int j = 0; // out index
+  char c;
+  bool b1_oob, b2_oob;
+
+  while (i < end) {
+    bitbuf[0] = parent->data()[i++];
+
+    if (i < end) {
+      bitbuf[1] = parent->data()[i];
+      b1_oob = false;
+    }  else {
+      bitbuf[1] = 0;
+      b1_oob = true;
+    }
+    i++;
+
+    if (i < end) {
+      bitbuf[2] = parent->data()[i];
+      b2_oob = false;
+    }  else {
+      bitbuf[2] = 0;
+      b2_oob = true;
+    }
+    i++;
+
+
+    c = bitbuf[0] >> 2;
+    assert(c < 64);
+    out[j++] = base64_table[c];
+    assert(j < out_len);
+
+    c = ((bitbuf[0] & 0x03) << 4) | (bitbuf[1] >> 4);
+    assert(c < 64);
+    out[j++] = base64_table[c];
+    assert(j < out_len);
+
+    if (b1_oob) {
+      out[j++] = '=';
+    } else {
+      c = ((bitbuf[1] & 0x0F) << 2) | (bitbuf[2] >> 6);
+      assert(c < 64);
+      out[j++] = base64_table[c];
+    }
+    assert(j < out_len);
+
+    if (b2_oob) {
+      out[j++] = '=';
+    } else {
+      c = bitbuf[2] & 0x3F;
+      assert(c < 64);
+      out[j++]  = base64_table[c];
+    }
+    assert(j <= out_len);
+  }
+
+  Local<String> string = String::New(out, out_len);
+  delete [] out;
+  return scope.Close(string);
+}
+
 
 Handle<Value> Buffer::Slice(const Arguments &args) {
   HandleScope scope;
@@ -534,6 +610,7 @@ void Buffer::Initialize(Handle<Object> target) {
   // copy free
   NODE_SET_PROTOTYPE_METHOD(constructor_template, "binarySlice", Buffer::BinarySlice);
   NODE_SET_PROTOTYPE_METHOD(constructor_template, "asciiSlice", Buffer::AsciiSlice);
+  NODE_SET_PROTOTYPE_METHOD(constructor_template, "base64Slice", Buffer::Base64Slice);
   NODE_SET_PROTOTYPE_METHOD(constructor_template, "slice", Buffer::Slice);
   // TODO NODE_SET_PROTOTYPE_METHOD(t, "utf16Slice", Utf16Slice);
   // copy
index dd9d0db..47dbe08 100644 (file)
@@ -54,6 +54,7 @@ class Buffer : public ObjectWrap {
   static v8::Handle<v8::Value> Slice(const v8::Arguments &args);
   static v8::Handle<v8::Value> BinarySlice(const v8::Arguments &args);
   static v8::Handle<v8::Value> AsciiSlice(const v8::Arguments &args);
+  static v8::Handle<v8::Value> Base64Slice(const v8::Arguments &args);
   static v8::Handle<v8::Value> Utf8Slice(const v8::Arguments &args);
   static v8::Handle<v8::Value> BinaryWrite(const v8::Arguments &args);
   static v8::Handle<v8::Value> AsciiWrite(const v8::Arguments &args);
index 5776997..63a025f 100644 (file)
@@ -229,3 +229,17 @@ assert.deepEqual(e, new Buffer([195, 188, 98, 101, 114]));
 
 var f = new Buffer('über', 'ascii');
 assert.deepEqual(f, new Buffer([252, 98, 101, 114]));
+
+
+//
+// Test toString('base64')
+//
+assert.equal('TWFu', (new Buffer('Man')).toString('base64'));
+// big example
+quote = "Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure.";
+expected = "TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4=";
+assert.equal(expected, (new Buffer(quote)).toString('base64'));
+
+
+
+