diff options
-rw-r--r-- | lib/buffer.js | 17 | ||||
-rw-r--r-- | src/node.cc | 5 | ||||
-rw-r--r-- | src/node.h | 2 | ||||
-rw-r--r-- | src/node_buffer.cc | 46 | ||||
-rw-r--r-- | src/node_buffer.h | 2 | ||||
-rw-r--r-- | test/simple/test-buffer.js | 10 |
6 files changed, 80 insertions, 2 deletions
diff --git a/lib/buffer.js b/lib/buffer.js index 273394734..64caa7e97 100644 --- a/lib/buffer.js +++ b/lib/buffer.js @@ -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'); } diff --git a/src/node.cc b/src/node.cc index 2e1e6b39b..a52d3e3f5 100644 --- a/src/node.cc +++ b/src/node.cc @@ -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(); } diff --git a/src/node.h b/src/node.h index 580a9c12e..e2c58d344 100644 --- a/src/node.h +++ b/src/node.h @@ -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); diff --git a/src/node_buffer.cc b/src/node_buffer.cc index 2c1966212..8b48f2a2e 100644 --- a/src/node_buffer.cc +++ b/src/node_buffer.cc @@ -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(), diff --git a/src/node_buffer.h b/src/node_buffer.h index d87038b3e..9a0e1d240 100644 --- a/src/node_buffer.h +++ b/src/node_buffer.h @@ -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); diff --git a/test/simple/test-buffer.js b/test/simple/test-buffer.js index e8756a7db..176e5a463 100644 --- a/test/simple/test-buffer.js +++ b/test/simple/test-buffer.js @@ -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); |