Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 7e18f2e

Browse filesBrowse 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
Copy full SHA for 7e18f2e

File tree

Expand file treeCollapse file tree

4 files changed

+34
-7
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

4 files changed

+34
-7
lines changed
Open diff view settings
Collapse file

‎src/node_buffer.cc‎

Copy file name to clipboardExpand all lines: src/node_buffer.cc
+6-3Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -477,10 +477,11 @@ void StringSlice<UCS2>(const FunctionCallbackInfo<Value>& args) {
477477
// need to reorder on BE platforms. See http://nodejs.org/api/buffer.html
478478
// regarding Node's "ucs2" encoding specification.
479479
const bool aligned = (reinterpret_cast<uintptr_t>(data) % sizeof(*buf) == 0);
480-
if (IsLittleEndian() && aligned) {
481-
buf = reinterpret_cast<const uint16_t*>(data);
482-
} else {
480+
if (IsLittleEndian() && !aligned) {
483481
// Make a copy to avoid unaligned accesses in v8::String::NewFromTwoByte().
482+
// This applies ONLY to little endian platforms, as misalignment will be
483+
// handled by a byte-swapping operation in StringBytes::Encode on
484+
// big endian platforms.
484485
uint16_t* copy = new uint16_t[length];
485486
for (size_t i = 0, k = 0; i < length; i += 1, k += 2) {
486487
// Assumes that the input is little endian.
@@ -490,6 +491,8 @@ void StringSlice<UCS2>(const FunctionCallbackInfo<Value>& args) {
490491
}
491492
buf = copy;
492493
release = true;
494+
} else {
495+
buf = reinterpret_cast<const uint16_t*>(data);
493496
}
494497

495498
args.GetReturnValue().Set(StringBytes::Encode(env->isolate(), buf, length));
Collapse file

‎src/string_bytes.cc‎

Copy file name to clipboardExpand all lines: src/string_bytes.cc
+12-4Lines 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,
Collapse file

‎src/util-inl.h‎

Copy file name to clipboardExpand all lines: src/util-inl.h
+14Lines 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_
Collapse file

‎src/util.h‎

Copy file name to clipboardExpand all lines: src/util.h
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,8 @@ inline void ClearWrap(v8::Local<v8::Object> object);
176176
template <typename TypeName>
177177
inline TypeName* Unwrap(v8::Local<v8::Object> object);
178178

179+
inline void SwapBytes(uint16_t* dst, const uint16_t* src, size_t buflen);
180+
179181
class Utf8Value {
180182
public:
181183
explicit Utf8Value(v8::Isolate* isolate, v8::Local<v8::Value> value);

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.