src: add BE support to StringBytes::Encode() · nodejs/node@7e18f2e · GitHub
Skip to content

Commit 7e18f2e

Browse files
exinfinitumrvagg
authored andcommitted
src: add BE support to StringBytes::Encode()
Versions of Node.js after v0.12 have relocated byte-swapping away from the StringBytes::Encode function, thereby causing a nan test (which accesses this function directly) to fail on big-endian machines. This change re-introduces byte swapping in StringBytes::Encode, done via a call to a function in util-inl. Another change in NodeBuffer::StringSlice was necessary to avoid double byte swapping in big-endian function calls to StringSlice. PR-URL: #3410 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Trevor Norris <trev.norris@gmail.com>
1 parent 1fe4d30 commit 7e18f2e

4 files changed

Lines changed: 34 additions & 7 deletions

File tree

src/node_buffer.cc

Lines changed: 6 additions & 3 deletions

src/string_bytes.cc

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
#include <limits.h>
88
#include <string.h> // memcpy
9+
#include <vector>
910

1011
// When creating strings >= this length v8's gc spins up and consumes
1112
// most of the execution time. For these cases it's more performant to
@@ -406,9 +407,7 @@ size_t StringBytes::Write(Isolate* isolate,
406407
reinterpret_cast<uintptr_t>(buf) % sizeof(uint16_t);
407408
if (is_aligned) {
408409
uint16_t* const dst = reinterpret_cast<uint16_t*>(buf);
409-
for (size_t i = 0; i < nchars; i++)
410-
dst[i] = dst[i] << 8 | dst[i] >> 8;
411-
break;
410+
SwapBytes(dst, dst, nchars);
412411
}
413412

414413
ASSERT_EQ(sizeof(uint16_t), 2);
@@ -857,7 +856,16 @@ Local<Value> StringBytes::Encode(Isolate* isolate,
857856
const uint16_t* buf,
858857
size_t buflen) {
859858
Local<String> val;
860-
859+
std::vector<uint16_t> dst;
860+
if (IsBigEndian()) {
861+
// Node's "ucs2" encoding expects LE character data inside a
862+
// Buffer, so we need to reorder on BE platforms. See
863+
// http://nodejs.org/api/buffer.html regarding Node's "ucs2"
864+
// encoding specification
865+
dst.resize(buflen);
866+
SwapBytes(&dst[0], buf, buflen);
867+
buf = &dst[0];
868+
}
861869
if (buflen < EXTERN_APEX) {
862870
val = String::NewFromTwoByte(isolate,
863871
buf,

src/util-inl.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,20 @@ TypeName* Unwrap(v8::Local<v8::Object> object) {
198198
return static_cast<TypeName*>(pointer);
199199
}
200200

201+
void SwapBytes(uint16_t* dst, const uint16_t* src, size_t buflen) {
202+
for (size_t i = 0; i < buflen; i++) {
203+
// __builtin_bswap16 generates more efficient code with
204+
// g++ 4.8 on PowerPC and other big-endian archs
205+
#ifdef __GNUC__
206+
dst[i] = __builtin_bswap16(src[i]);
207+
#else
208+
dst[i] = (src[i] << 8) | (src[i] >> 8);
209+
#endif
210+
}
211+
}
212+
213+
214+
201215
} // namespace node
202216

203217
#endif // SRC_UTIL_INL_H_

src/util.h

Lines changed: 2 additions & 0 deletions

0 commit comments

Comments
 (0)