string_bytes: ucs2 support big endian
authorAndrew Low <Andrew_Low@ca.ibm.com>
Tue, 8 Apr 2014 14:39:33 +0000 (10:39 -0400)
committerTimothy J Fontaine <tjfontaine@gmail.com>
Wed, 21 May 2014 20:16:00 +0000 (13:16 -0700)
64bit constants are keyed for x64 platforms only, add PowerPC based
platform constants.

Node's "ucs2" encoding wants LE character data stored in the Buffer, so
we need to reorder on BE platforms.  See
http://nodejs.org/api/buffer.html regarding Node's "ucs2" encoding
specification

Signed-off-by: Timothy J Fontaine <tjfontaine@gmail.com>
src/string_bytes.cc

index de41ec1..1a7b4e1 100644 (file)
@@ -336,6 +336,16 @@ size_t StringBytes::Write(Isolate* isolate,
         memcpy(buf, data, len * 2);
       else
         len = str->Write(reinterpret_cast<uint16_t*>(buf), 0, buflen, flags);
+      if (IsBigEndian()) {
+        // Node's "ucs2" encoding wants LE character data stored in
+        // the Buffer, so we need to reorder on BE platforms.  See
+        // http://nodejs.org/api/buffer.html regarding Node's "ucs2"
+        // encoding specification
+        uint16_t* buf16 = reinterpret_cast<uint16_t*>(buf);
+        for (size_t i = 0; i < len; i++) {
+          buf16[i] = (buf16[i] << 8) | (buf16[i] >> 8);
+        }
+      }
       if (chars_written != NULL)
         *chars_written = len;
       len = len * sizeof(uint16_t);
@@ -515,7 +525,8 @@ static bool contains_non_ascii(const char* src, size_t len) {
   }
 
 
-#if defined(__x86_64__) || defined(_WIN64)
+#if defined(__x86_64__) || defined(_WIN64) || defined(__PPC64__) ||           \
+    defined(_ARCH_PPC64)
   const uintptr_t mask = 0x8080808080808080ll;
 #else
   const uintptr_t mask = 0x80808080l;
@@ -570,7 +581,8 @@ static void force_ascii(const char* src, char* dst, size_t len) {
     }
   }
 
-#if defined(__x86_64__) || defined(_WIN64)
+#if defined(__x86_64__) || defined(_WIN64) || defined(__PPC64__) ||           \
+    defined(_ARCH_PPC64)
   const uintptr_t mask = ~0x8080808080808080ll;
 #else
   const uintptr_t mask = ~0x80808080l;
@@ -738,6 +750,18 @@ Local<Value> StringBytes::Encode(Isolate* isolate,
 
     case UCS2: {
       const uint16_t* out = reinterpret_cast<const uint16_t*>(buf);
+      uint16_t* dst = NULL;
+      if (IsBigEndian()) {
+        // 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
+        dst = new uint16_t[buflen / 2];
+        for (size_t i = 0; i < buflen / 2; i++) {
+          dst[i] = (out[i] << 8) | (out[i] >> 8);
+        }
+        out = dst;
+      }
       if (buflen < EXTERN_APEX)
         val = String::NewFromTwoByte(isolate,
                                      out,
@@ -745,6 +769,8 @@ Local<Value> StringBytes::Encode(Isolate* isolate,
                                      buflen / 2);
       else
         val = ExternTwoByteString::NewFromCopy(isolate, out, buflen / 2);
+      if (dst)
+        delete[] dst;
       break;
     }