UCS-2 support

Closes GH-644.
This commit is contained in:
Konstantin Käfer 2011-02-06 15:49:52 -05:00 committed by Ryan Dahl
parent bf8f4aa966
commit 9e101f2b01
6 changed files with 80 additions and 2 deletions

View File

@ -41,6 +41,10 @@ SlowBuffer.prototype.toString = function(encoding, start, end) {
case 'base64':
return this.base64Slice(start, end);
case 'ucs2':
case 'ucs-2':
return this.ucs2Slice(start, end);
default:
throw new Error('Unknown encoding');
}
@ -73,6 +77,10 @@ SlowBuffer.prototype.write = function(string, offset, encoding) {
case 'base64':
return this.base64Write(string, offset);
case 'ucs2':
case 'ucs-2':
return this.ucs2Write(start, end);
default:
throw new Error('Unknown encoding');
}
@ -228,6 +236,11 @@ Buffer.prototype.write = function(string, offset, encoding) {
ret = this.parent.base64Write(string, this.offset + offset, maxLength);
break;
case 'ucs2':
case 'ucs-2':
ret = this.parent.ucs2Write(string, this.offset + offset, maxLength);
break;
default:
throw new Error('Unknown encoding');
}
@ -271,6 +284,10 @@ Buffer.prototype.toString = function(encoding, start, end) {
case 'base64':
return this.parent.base64Slice(start, end);
case 'ucs2':
case 'ucs-2':
return this.parent.ucs2Slice(start, end);
default:
throw new Error('Unknown encoding');
}

View File

@ -1078,6 +1078,10 @@ enum encoding ParseEncoding(Handle<Value> encoding_v, enum encoding _default) {
return ASCII;
} else if (strcasecmp(*encoding, "base64") == 0) {
return BASE64;
} else if (strcasecmp(*encoding, "ucs2") == 0) {
return UCS2;
} else if (strcasecmp(*encoding, "ucs-2") == 0) {
return UCS2;
} else if (strcasecmp(*encoding, "binary") == 0) {
return BINARY;
} else if (strcasecmp(*encoding, "raw") == 0) {
@ -1129,6 +1133,7 @@ ssize_t DecodeBytes(v8::Handle<v8::Value> val, enum encoding encoding) {
Local<String> str = val->ToString();
if (encoding == UTF8) return str->Utf8Length();
else if (encoding == UCS2) return str->Length() * 2;
return str->Length();
}

View File

@ -44,7 +44,7 @@ do { \
__callback##_TEM); \
} while (0)
enum encoding {ASCII, UTF8, BASE64, BINARY};
enum encoding {ASCII, UTF8, BASE64, UCS2, BINARY};
enum encoding ParseEncoding(v8::Handle<v8::Value> encoding_v,
enum encoding _default = BINARY);
void FatalException(v8::TryCatch &try_catch);

View File

@ -84,6 +84,8 @@ static size_t ByteLength (Handle<String> string, enum encoding enc) {
} else if (enc == BASE64) {
String::Utf8Value v(string);
return base64_decoded_size(*v, v.length());
} else if (enc == UCS2) {
return string->Length() * 2;
} else {
return string->Length();
}
@ -245,6 +247,15 @@ Handle<Value> Buffer::Utf8Slice(const Arguments &args) {
return scope.Close(string);
}
Handle<Value> Buffer::Ucs2Slice(const Arguments &args) {
HandleScope scope;
Buffer *parent = ObjectWrap::Unwrap<Buffer>(args.This());
SLICE_ARGS(args[0], args[1])
uint16_t *data = (uint16_t*)(parent->data_ + start);
Local<String> string = String::New(data, (end - start) / 2);
return scope.Close(string);
}
static const char *base64_table = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/";
@ -441,6 +452,39 @@ Handle<Value> Buffer::Utf8Write(const Arguments &args) {
}
// var charsWritten = buffer.ucs2Write(string, offset, [maxLength]);
Handle<Value> Buffer::Ucs2Write(const Arguments &args) {
HandleScope scope;
Buffer *buffer = ObjectWrap::Unwrap<Buffer>(args.This());
if (!args[0]->IsString()) {
return ThrowException(Exception::TypeError(String::New(
"Argument must be a string")));
}
Local<String> s = args[0]->ToString();
size_t offset = args[1]->Uint32Value();
if (s->Length() > 0 && offset >= buffer->length_) {
return ThrowException(Exception::TypeError(String::New(
"Offset is out of bounds")));
}
size_t max_length = args[2]->IsUndefined() ? buffer->length_ - offset
: args[2]->Uint32Value();
max_length = MIN(buffer->length_ - offset, max_length);
uint16_t* p = (uint16_t*)(buffer->data_ + offset);
int written = s->Write(p,
0,
max_length,
String::HINT_MANY_WRITES_EXPECTED);
return scope.Close(Integer::New(written * 2));
}
// var charsWritten = buffer.asciiWrite(string, offset);
Handle<Value> Buffer::AsciiWrite(const Arguments &args) {
HandleScope scope;
@ -652,6 +696,7 @@ void Buffer::Initialize(Handle<Object> target) {
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, "ucs2Slice", Buffer::Ucs2Slice);
// TODO NODE_SET_PROTOTYPE_METHOD(t, "utf16Slice", Utf16Slice);
// copy
NODE_SET_PROTOTYPE_METHOD(constructor_template, "utf8Slice", Buffer::Utf8Slice);
@ -660,6 +705,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, "base64Write", Buffer::Base64Write);
NODE_SET_PROTOTYPE_METHOD(constructor_template, "ucs2Write", Buffer::Ucs2Write);
NODE_SET_PROTOTYPE_METHOD(constructor_template, "copy", Buffer::Copy);
NODE_SET_METHOD(constructor_template->GetFunction(),

View File

@ -88,10 +88,12 @@ class Buffer : public ObjectWrap {
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> Ucs2Slice(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> Ucs2Write(const v8::Arguments &args);
static v8::Handle<v8::Value> ByteLength(const v8::Arguments &args);
static v8::Handle<v8::Value> MakeFastBuffer(const v8::Arguments &args);
static v8::Handle<v8::Value> Copy(const v8::Arguments &args);

View File

@ -225,6 +225,14 @@ var f = new Buffer('über', 'ascii');
console.error('f.length: %d (should be 4)', f.length);
assert.deepEqual(f, new Buffer([252, 98, 101, 114]));
var f = new Buffer('über', 'ucs2');
console.error('f.length: %d (should be 8)', f.length);
assert.deepEqual(f, new Buffer([252, 0, 98, 0, 101, 0, 114, 0]));
var f = new Buffer('привет', 'ucs2');
console.error('f.length: %d (should be 12)', f.length);
assert.deepEqual(f, new Buffer([63, 4, 64, 4, 56, 4, 50, 4, 53, 4, 66, 4]));
assert.equal(f.toString('ucs2'), 'привет');
//
// Test toString('base64')
@ -386,9 +394,9 @@ assert.equal('bcde', b.slice(1).toString());
// byte length
assert.equal(14, Buffer.byteLength('Il était tué'));
assert.equal(14, Buffer.byteLength('Il était tué', 'utf8'));
assert.equal(24, Buffer.byteLength('Il était tué', 'ucs2'));
assert.equal(12, Buffer.byteLength('Il était tué', 'ascii'));
assert.equal(12, Buffer.byteLength('Il était tué', 'binary'));
// slice(0,0).length === 0
assert.equal(0, Buffer('hello').slice(0, 0).length);