summaryrefslogtreecommitdiff
path: root/src/string_bytes.cc
diff options
context:
space:
mode:
authorBen Noordhuis <info@bnoordhuis.nl>2014-12-10 17:33:56 +0100
committerBen Noordhuis <info@bnoordhuis.nl>2014-12-14 16:01:47 +0100
commit56fde66c46653e5c0fbc6e8960d8a013af35f42b (patch)
treec73a2e4a7ddfea89b553c8af6746abe2c3623b0c /src/string_bytes.cc
parenta60056df3cad2867d337fc1d7adeebe66f89031a (diff)
downloadandroid-node-v8-56fde66c46653e5c0fbc6e8960d8a013af35f42b.tar.gz
android-node-v8-56fde66c46653e5c0fbc6e8960d8a013af35f42b.tar.bz2
android-node-v8-56fde66c46653e5c0fbc6e8960d8a013af35f42b.zip
src: redo unaligned access workaround
Introduce two-byte overloads of node::Encode() and StringBytes::Encode() that ensure that the input is suitably aligned. Revisits commit 535fec8 from yesterday.
Diffstat (limited to 'src/string_bytes.cc')
-rw-r--r--src/string_bytes.cc62
1 files changed, 36 insertions, 26 deletions
diff --git a/src/string_bytes.cc b/src/string_bytes.cc
index f9892405f3..e646087b9d 100644
--- a/src/string_bytes.cc
+++ b/src/string_bytes.cc
@@ -690,6 +690,7 @@ Local<Value> StringBytes::Encode(Isolate* isolate,
enum encoding encoding) {
EscapableHandleScope scope(isolate);
+ CHECK_NE(encoding, UCS2);
CHECK_LE(buflen, Buffer::kMaxLength);
if (!buflen && encoding != BUFFER)
return scope.Escape(String::Empty(isolate));
@@ -747,32 +748,6 @@ Local<Value> StringBytes::Encode(Isolate* isolate,
break;
}
- case UCS2: {
- // Node's "ucs2" encoding expects LE character data inside a
- // Buffer, so we need to reorder on BE platforms. See
- // http://nodejs.org/api/buffer.html regarding Node's "ucs2"
- // encoding specification. Note that we have to make a copy
- // to avoid pointer aliasing and unaligned access, something
- // that we can't guarantee by just reinterpret_casting |buf|.
- size_t srclen = buflen / 2;
- uint16_t* src = new uint16_t[srclen];
- for (size_t i = 0, k = 0; i < srclen; i += 1, k += 2) {
- const uint8_t lo = static_cast<uint8_t>(buf[k + 0]);
- const uint8_t hi = static_cast<uint8_t>(buf[k + 1]);
- src[i] = lo | hi << 8;
- }
- if (buflen < EXTERN_APEX) {
- val = String::NewFromTwoByte(isolate,
- src,
- String::kNormalString,
- srclen);
- } else {
- val = ExternTwoByteString::NewFromCopy(isolate, src, srclen);
- }
- delete[] src;
- break;
- }
-
case HEX: {
size_t dlen = buflen * 2;
char* dst = new char[dlen];
@@ -796,4 +771,39 @@ Local<Value> StringBytes::Encode(Isolate* isolate,
return scope.Escape(val);
}
+
+Local<Value> StringBytes::Encode(Isolate* isolate,
+ const uint16_t* buf,
+ size_t buflen) {
+ const uint16_t* src = buf;
+
+ // Node's "ucs2" encoding expects LE character data inside a
+ // Buffer, so we need to reorder on BE platforms. See
+ // http://nodejs.org/api/buffer.html regarding Node's "ucs2"
+ // encoding specification.
+ if (IsBigEndian()) {
+ // Inefficient, see StringSlice<UCS2>() in src/node_buffer.cc;
+ // this is potentially the second copy of the actual input.
+ uint16_t* copy = new uint16_t[buflen];
+ for (size_t i = 0; i < buflen; i += 1)
+ copy[i] = buf[i] << 8 | buf[i] >> 8;
+ src = copy;
+ }
+
+ Local<String> val;
+ if (buflen < EXTERN_APEX) {
+ val = String::NewFromTwoByte(isolate,
+ src,
+ String::kNormalString,
+ buflen);
+ } else {
+ val = ExternTwoByteString::NewFromCopy(isolate, src, buflen);
+ }
+
+ if (src != buf)
+ delete[] src;
+
+ return val;
+}
+
} // namespace node