diff options
author | Ben Noordhuis <info@bnoordhuis.nl> | 2014-12-10 17:33:56 +0100 |
---|---|---|
committer | Ben Noordhuis <info@bnoordhuis.nl> | 2014-12-14 16:01:47 +0100 |
commit | 56fde66c46653e5c0fbc6e8960d8a013af35f42b (patch) | |
tree | c73a2e4a7ddfea89b553c8af6746abe2c3623b0c /src/string_bytes.cc | |
parent | a60056df3cad2867d337fc1d7adeebe66f89031a (diff) | |
download | android-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.cc | 62 |
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 |