File tree 4 files changed +34
-7
lines changed
4 files changed +34
-7
lines changed Original file line number Diff line number Diff line change @@ -477,10 +477,11 @@ void StringSlice<UCS2>(const FunctionCallbackInfo<Value>& args) {
477
477
// need to reorder on BE platforms. See http://nodejs.org/api/buffer.html
478
478
// regarding Node's "ucs2" encoding specification.
479
479
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) {
483
481
// 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.
484
485
uint16_t * copy = new uint16_t [length];
485
486
for (size_t i = 0 , k = 0 ; i < length; i += 1 , k += 2 ) {
486
487
// Assumes that the input is little endian.
@@ -490,6 +491,8 @@ void StringSlice<UCS2>(const FunctionCallbackInfo<Value>& args) {
490
491
}
491
492
buf = copy;
492
493
release = true ;
494
+ } else {
495
+ buf = reinterpret_cast <const uint16_t *>(data);
493
496
}
494
497
495
498
args.GetReturnValue ().Set (StringBytes::Encode (env->isolate (), buf, length));
Original file line number Diff line number Diff line change 6
6
7
7
#include < limits.h>
8
8
#include < string.h> // memcpy
9
+ #include < vector>
9
10
10
11
// When creating strings >= this length v8's gc spins up and consumes
11
12
// most of the execution time. For these cases it's more performant to
@@ -406,9 +407,7 @@ size_t StringBytes::Write(Isolate* isolate,
406
407
reinterpret_cast <uintptr_t >(buf) % sizeof (uint16_t );
407
408
if (is_aligned) {
408
409
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);
412
411
}
413
412
414
413
ASSERT_EQ (sizeof (uint16_t ), 2 );
@@ -857,7 +856,16 @@ Local<Value> StringBytes::Encode(Isolate* isolate,
857
856
const uint16_t * buf,
858
857
size_t buflen) {
859
858
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
+ }
861
869
if (buflen < EXTERN_APEX) {
862
870
val = String::NewFromTwoByte (isolate,
863
871
buf,
Original file line number Diff line number Diff line change @@ -198,6 +198,20 @@ TypeName* Unwrap(v8::Local<v8::Object> object) {
198
198
return static_cast <TypeName*>(pointer);
199
199
}
200
200
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
+
201
215
} // namespace node
202
216
203
217
#endif // SRC_UTIL_INL_H_
Original file line number Diff line number Diff line change @@ -176,6 +176,8 @@ inline void ClearWrap(v8::Local<v8::Object> object);
176
176
template <typename TypeName>
177
177
inline TypeName* Unwrap (v8::Local<v8::Object> object);
178
178
179
+ inline void SwapBytes (uint16_t * dst, const uint16_t * src, size_t buflen);
180
+
179
181
class Utf8Value {
180
182
public:
181
183
explicit Utf8Value (v8::Isolate* isolate, v8::Local<v8::Value> value);
You can’t perform that action at this time.
0 commit comments