@@ -293,6 +293,46 @@ bool StringBytes::GetExternalParts(Isolate* isolate,
293
293
}
294
294
295
295
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
+
296
336
size_t StringBytes::Write (Isolate* isolate,
297
337
char * buf,
298
338
size_t buflen,
@@ -334,26 +374,40 @@ size_t StringBytes::Write(Isolate* isolate,
334
374
break ;
335
375
336
376
case UCS2: {
337
- uint16_t * const dst = reinterpret_cast <uint16_t *>(buf);
338
377
size_t nchars;
378
+
339
379
if (is_extern && !str->IsOneByte ()) {
340
380
memcpy (buf, data, nbytes);
341
- nchars = nbytes / sizeof (*dst );
381
+ nchars = nbytes / sizeof (uint16_t );
342
382
} 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);
346
384
}
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);
352
400
for (size_t i = 0 ; i < nchars; i++)
353
401
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;
354
410
}
355
- if (chars_written != nullptr )
356
- *chars_written = nchars;
357
411
break ;
358
412
}
359
413
0 commit comments