@@ -293,6 +293,46 @@ bool StringBytes::GetExternalParts(Isolate* isolate,
293293}
294294
295295
296+ size_t StringBytes::WriteUCS2 (char * buf,
297+ size_t buflen,
298+ size_t nbytes,
299+ const char * data,
300+ Local<String> str,
301+ int flags,
302+ size_t * chars_written) {
303+ uint16_t * const dst = reinterpret_cast <uint16_t *>(buf);
304+
305+ size_t max_chars = (buflen / sizeof (*dst));
306+ size_t nchars;
307+ size_t alignment = reinterpret_cast <uintptr_t >(dst) % sizeof (*dst);
308+ if (alignment == 0 ) {
309+ nchars = str->Write (dst, 0 , max_chars, flags);
310+ *chars_written = nchars;
311+ return nchars * sizeof (*dst);
312+ }
313+
314+ uint16_t * aligned_dst =
315+ reinterpret_cast <uint16_t *>(buf + sizeof (*dst) - alignment);
316+ ASSERT_EQ (reinterpret_cast <uintptr_t >(aligned_dst) % sizeof (*dst), 0 );
317+
318+ // Write all but the last char
319+ nchars = str->Write (aligned_dst, 0 , max_chars - 1 , flags);
320+
321+ // Shift everything to unaligned-left
322+ memmove (dst, aligned_dst, nchars * sizeof (*dst));
323+
324+ // One more char to be written
325+ uint16_t last;
326+ if (nchars == max_chars - 1 && str->Write (&last, nchars, 1 , flags) != 0 ) {
327+ memcpy (buf + nchars * sizeof (*dst), &last, sizeof (last));
328+ nchars++;
329+ }
330+
331+ *chars_written = nchars;
332+ return nchars * sizeof (*dst);
333+ }
334+
335+
296336size_t StringBytes::Write (Isolate* isolate,
297337 char * buf,
298338 size_t buflen,
@@ -334,26 +374,40 @@ size_t StringBytes::Write(Isolate* isolate,
334374 break ;
335375
336376 case UCS2: {
337- uint16_t * const dst = reinterpret_cast <uint16_t *>(buf);
338377 size_t nchars;
378+
339379 if (is_extern && !str->IsOneByte ()) {
340380 memcpy (buf, data, nbytes);
341- nchars = nbytes / sizeof (*dst );
381+ nchars = nbytes / sizeof (uint16_t );
342382 } else {
343- nchars = buflen / sizeof (*dst);
344- nchars = str->Write (dst, 0 , nchars, flags);
345- nbytes = nchars * sizeof (*dst);
383+ nbytes = WriteUCS2 (buf, buflen, nbytes, data, str, flags, &nchars);
346384 }
347- if (IsBigEndian ()) {
348- // Node's "ucs2" encoding wants LE character data stored in
349- // the Buffer, so we need to reorder on BE platforms. See
350- // http://nodejs.org/api/buffer.html regarding Node's "ucs2"
351- // encoding specification
385+ if (chars_written != nullptr )
386+ *chars_written = nchars;
387+
388+ if (!IsBigEndian ())
389+ break ;
390+
391+ // Node's "ucs2" encoding wants LE character data stored in
392+ // the Buffer, so we need to reorder on BE platforms. See
393+ // http://nodejs.org/api/buffer.html regarding Node's "ucs2"
394+ // encoding specification
395+
396+ const bool is_aligned =
397+ reinterpret_cast <uintptr_t >(buf) % sizeof (uint16_t );
398+ if (is_aligned) {
399+ uint16_t * const dst = reinterpret_cast <uint16_t *>(buf);
352400 for (size_t i = 0 ; i < nchars; i++)
353401 dst[i] = dst[i] << 8 | dst[i] >> 8 ;
402+ break ;
403+ }
404+
405+ ASSERT_EQ (sizeof (uint16_t ), 2 );
406+ for (size_t i = 0 ; i < nchars; i++) {
407+ char tmp = buf[i * 2 ];
408+ buf[i * 2 ] = buf[i * 2 + 1 ];
409+ buf[i * 2 + 1 ] = tmp;
354410 }
355- if (chars_written != nullptr )
356- *chars_written = nchars;
357411 break ;
358412 }
359413
0 commit comments