summaryrefslogtreecommitdiff
path: root/lib/string_decoder.js
diff options
context:
space:
mode:
authorkoichik <koichik@improvement.jp>2012-05-05 12:22:01 +0900
committerkoichik <koichik@improvement.jp>2012-05-05 12:24:01 +0900
commitceb51ddaa187b188035dd0b01589f1d24d5e90c7 (patch)
tree12b57894b35e5c17ed545d1aff71326406ddfe55 /lib/string_decoder.js
parenteaf607e88b632a80d59dde04bd08dae5cb2c7bb8 (diff)
downloadandroid-node-v8-ceb51ddaa187b188035dd0b01589f1d24d5e90c7.tar.gz
android-node-v8-ceb51ddaa187b188035dd0b01589f1d24d5e90c7.tar.bz2
android-node-v8-ceb51ddaa187b188035dd0b01589f1d24d5e90c7.zip
string_decoder: add support for CESU-8
Fixes #3217.
Diffstat (limited to 'lib/string_decoder.js')
-rw-r--r--lib/string_decoder.js49
1 files changed, 35 insertions, 14 deletions
diff --git a/lib/string_decoder.js b/lib/string_decoder.js
index 991b255e83..6e730c2fbd 100644
--- a/lib/string_decoder.js
+++ b/lib/string_decoder.js
@@ -22,7 +22,7 @@
var StringDecoder = exports.StringDecoder = function(encoding) {
this.encoding = (encoding || 'utf8').toLowerCase().replace(/[-_]/, '');
if (this.encoding === 'utf8') {
- this.charBuffer = new Buffer(4);
+ this.charBuffer = new Buffer(6);
this.charReceived = 0;
this.charLength = 0;
}
@@ -36,16 +36,18 @@ StringDecoder.prototype.write = function(buffer) {
}
var charStr = '';
+ var offset = 0;
// if our last write ended with an incomplete multibyte character
- if (this.charLength) {
+ while (this.charLength) {
// determine how many remaining bytes this buffer has to offer for this char
var i = (buffer.length >= this.charLength - this.charReceived) ?
this.charLength - this.charReceived :
buffer.length;
// add the new bytes to the char buffer
- buffer.copy(this.charBuffer, this.charReceived, 0, i);
- this.charReceived += i;
+ buffer.copy(this.charBuffer, this.charReceived, offset, i);
+ this.charReceived += (i - offset);
+ offset = i;
if (this.charReceived < this.charLength) {
// still not enough chars in this buffer? wait for more ...
@@ -54,6 +56,16 @@ StringDecoder.prototype.write = function(buffer) {
// get the character that was split
charStr = this.charBuffer.slice(0, this.charLength).toString();
+
+ // lead surrogate (D800-DBFF) is also the incomplete character
+ if (this.charLength === 3) {
+ var charCode = charStr.charCodeAt(0);
+ if (charCode >= 0xD800 && charCode <= 0xDBFF) {
+ charStr = '';
+ this.charLength += 3; // size of trail surrogate (DC00-DFFF)
+ continue;
+ }
+ }
this.charReceived = this.charLength = 0;
// if there are no more bytes in this buffer, just emit our char
@@ -61,6 +73,7 @@ StringDecoder.prototype.write = function(buffer) {
// otherwise cut off the characters end from the beginning of this buffer
buffer = buffer.slice(i, buffer.length);
+ break;
}
@@ -93,18 +106,26 @@ StringDecoder.prototype.write = function(buffer) {
}
}
- if (!this.charLength) {
- // no incomplete char at the end of this buffer, emit the whole thing
- return charStr + buffer.toString();
+ var end = buffer.length;
+ if (this.charLength) {
+ // buffer the incomplete character bytes we got
+ buffer.copy(this.charBuffer, 0, buffer.length - i, buffer.length);
+ this.charReceived = i;
+ end -= i;
}
- // buffer the incomplete character bytes we got
- buffer.copy(this.charBuffer, 0, buffer.length - i, buffer.length);
- this.charReceived = i;
-
- if (buffer.length - i > 0) {
- // buffer had more bytes before the incomplete char, emit them
- return charStr + buffer.toString('utf8', 0, buffer.length - i);
+ charStr += buffer.toString('utf8', 0, end);
+
+ // lead surrogate (D800-DBFF) is also the incomplete character
+ end = charStr.length - 1;
+ var charCode = charStr.charCodeAt(end);
+ if (charCode >= 0xD800 && charCode <= 0xDBFF) {
+ // CESU-8 represents each of Surrogate Pair by 3-bytes
+ this.charLength += 3
+ this.charReceived += 3
+ this.charBuffer.copy(this.charBuffer, 3, 0, 3);
+ this.charBuffer.write(charStr.charAt(end));
+ return charStr.substring(0, end);
}
// or just emit the charStr