Implement buffer.write for base64
There might be an off-by-one on the returned value.
This commit is contained in:
parent
528015e0d8
commit
2c1ca4078d
@ -77,6 +77,9 @@ Buffer.prototype.write = function (string) {
|
||||
case 'binary':
|
||||
return this.binaryWrite(string, offset);
|
||||
|
||||
case 'base64':
|
||||
return this.base64Write(string, offset);
|
||||
|
||||
default:
|
||||
throw new Error('Unknown encoding');
|
||||
}
|
||||
|
@ -275,6 +275,16 @@ Handle<Value> Buffer::Utf8Slice(const Arguments &args) {
|
||||
static char* base64_table = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"abcdefghijklmnopqrstuvwxyz"
|
||||
"0123456789+/";
|
||||
static int unbase64_table[] =
|
||||
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
|
||||
,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
|
||||
,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,62,-1,-1,-1,63
|
||||
,52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-1,-1,-1
|
||||
,-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14
|
||||
,15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1
|
||||
,-1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40
|
||||
,41,42,43,44,45,46,47,48,49,50,51,-1,-1,-1,-1,-1
|
||||
};
|
||||
|
||||
|
||||
Handle<Value> Buffer::Base64Slice(const Arguments &args) {
|
||||
@ -485,6 +495,91 @@ Handle<Value> Buffer::AsciiWrite(const Arguments &args) {
|
||||
}
|
||||
|
||||
|
||||
// var bytesWritten = buffer.base64Write(string, offset);
|
||||
Handle<Value> Buffer::Base64Write(const Arguments &args) {
|
||||
HandleScope scope;
|
||||
|
||||
assert(unbase64_table['/'] == 63);
|
||||
assert(unbase64_table['+'] == 62);
|
||||
assert(unbase64_table['T'] == 19);
|
||||
assert(unbase64_table['Z'] == 25);
|
||||
assert(unbase64_table['t'] == 45);
|
||||
assert(unbase64_table['z'] == 51);
|
||||
|
||||
Buffer *buffer = ObjectWrap::Unwrap<Buffer>(args.This());
|
||||
|
||||
if (!args[0]->IsString()) {
|
||||
return ThrowException(Exception::TypeError(String::New(
|
||||
"Argument must be a string")));
|
||||
}
|
||||
|
||||
String::AsciiValue s(args[0]->ToString());
|
||||
size_t offset = args[1]->Int32Value();
|
||||
|
||||
if (offset >= buffer->length_) {
|
||||
return ThrowException(Exception::TypeError(String::New(
|
||||
"Offset is out of bounds")));
|
||||
}
|
||||
|
||||
char *input = *s;
|
||||
int input_len = s.length();
|
||||
|
||||
char *start = buffer->data() + offset;
|
||||
char *p = start;
|
||||
const char *pe = buffer->data() + buffer->length_;
|
||||
|
||||
int i = 0;
|
||||
char a,b,c,d;
|
||||
|
||||
bool b_oob, c_oob;
|
||||
|
||||
while (i < input_len && p < pe) {
|
||||
if (input[i] == '=' || i >= input_len) break;
|
||||
a = unbase64_table[input[i]];
|
||||
i++;
|
||||
|
||||
if (input[i] == '=' || i >= input_len) {
|
||||
b = 0;
|
||||
b_oob = true;
|
||||
} else {
|
||||
b = unbase64_table[input[i]];
|
||||
b_oob = false;
|
||||
}
|
||||
i++;
|
||||
|
||||
if (b_oob || input[i] == '=' || i >= input_len) {
|
||||
c = 0;
|
||||
c_oob = true;
|
||||
} else {
|
||||
c = unbase64_table[input[i]];
|
||||
c_oob = false;
|
||||
}
|
||||
i++;
|
||||
|
||||
if (c_oob || input[i] == '=' || i >= input_len) {
|
||||
d = 0;
|
||||
} else {
|
||||
d = unbase64_table[input[i]];
|
||||
}
|
||||
i++;
|
||||
|
||||
|
||||
*p = (a << 2) | ((b & 0x30) >> 4);
|
||||
if (++p >= pe) break;
|
||||
|
||||
if (b_oob) break;
|
||||
*p = ((b & 0x0F) << 4) | ((c & 0x3c) >> 2);
|
||||
if (++p >= pe) break;
|
||||
|
||||
if (c_oob) break;
|
||||
*p = ((c & 0x03) << 6) | (d & 0x3f);
|
||||
if (++p >= pe) break;
|
||||
}
|
||||
|
||||
return scope.Close(Integer::New(p - start));
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> Buffer::BinaryWrite(const Arguments &args) {
|
||||
HandleScope scope;
|
||||
|
||||
@ -619,6 +714,7 @@ void Buffer::Initialize(Handle<Object> target) {
|
||||
NODE_SET_PROTOTYPE_METHOD(constructor_template, "utf8Write", Buffer::Utf8Write);
|
||||
NODE_SET_PROTOTYPE_METHOD(constructor_template, "asciiWrite", Buffer::AsciiWrite);
|
||||
NODE_SET_PROTOTYPE_METHOD(constructor_template, "binaryWrite", Buffer::BinaryWrite);
|
||||
NODE_SET_PROTOTYPE_METHOD(constructor_template, "base64Write", Buffer::Base64Write);
|
||||
NODE_SET_PROTOTYPE_METHOD(constructor_template, "unpack", Buffer::Unpack);
|
||||
NODE_SET_PROTOTYPE_METHOD(constructor_template, "copy", Buffer::Copy);
|
||||
|
||||
|
@ -57,6 +57,7 @@ class Buffer : public ObjectWrap {
|
||||
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> Base64Write(const v8::Arguments &args);
|
||||
static v8::Handle<v8::Value> AsciiWrite(const v8::Arguments &args);
|
||||
static v8::Handle<v8::Value> Utf8Write(const v8::Arguments &args);
|
||||
static v8::Handle<v8::Value> ByteLength(const v8::Arguments &args);
|
||||
|
@ -241,5 +241,10 @@ expected = "TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBi
|
||||
assert.equal(expected, (new Buffer(quote)).toString('base64'));
|
||||
|
||||
|
||||
b = new Buffer(1024);
|
||||
bytesWritten = b.write(expected, 0, 'base64');
|
||||
assert.equal(quote, b.toString('ascii', 0, quote.length));
|
||||
assert.equal(quote.length+1, bytesWritten); // writes a \0 too
|
||||
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user