int* chars_written) {
HandleScope scope(isolate);
const char* data = nullptr;
- size_t len = 0;
- bool is_extern = GetExternalParts(isolate, val, &data, &len);
- size_t extlen = len;
+ size_t nbytes = 0;
+ const bool is_extern = GetExternalParts(isolate, val, &data, &nbytes);
+ const size_t external_nbytes = nbytes;
CHECK(val->IsString() == true);
Local<String> str = val.As<String>();
- len = len < buflen ? len : buflen;
+
+ if (nbytes > buflen)
+ nbytes = buflen;
int flags = String::HINT_MANY_WRITES_EXPECTED |
String::NO_NULL_TERMINATION |
case ASCII:
case BINARY:
case BUFFER:
- if (is_extern)
- memcpy(buf, data, len);
- else
- len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf),
- 0,
- buflen,
- flags);
+ if (is_extern && str->IsOneByte()) {
+ memcpy(buf, data, nbytes);
+ } else {
+ uint8_t* const dst = reinterpret_cast<uint8_t*>(buf);
+ nbytes = str->WriteOneByte(dst, 0, buflen, flags);
+ }
if (chars_written != nullptr)
- *chars_written = len;
+ *chars_written = nbytes;
break;
case UTF8:
- if (is_extern)
- // TODO(tjfontaine) should this validate invalid surrogate pairs as
- // well?
- memcpy(buf, data, len);
- else
- len = str->WriteUtf8(buf, buflen, chars_written, flags);
+ nbytes = str->WriteUtf8(buf, buflen, chars_written, flags);
break;
- case UCS2:
- if (is_extern)
- memcpy(buf, data, len);
- else
- len = str->Write(reinterpret_cast<uint16_t*>(buf), 0, buflen, flags);
+ case UCS2: {
+ uint16_t* const dst = reinterpret_cast<uint16_t*>(buf);
+ size_t nchars;
+ if (is_extern && !str->IsOneByte()) {
+ memcpy(buf, data, nbytes);
+ nchars = nbytes / sizeof(*dst);
+ } else {
+ nchars = buflen / sizeof(*dst);
+ nchars = str->Write(dst, 0, nchars, flags);
+ nbytes = nchars * sizeof(*dst);
+ }
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);
- }
+ for (size_t i = 0; i < nchars; i++)
+ dst[i] = dst[i] << 8 | dst[i] >> 8;
}
if (chars_written != nullptr)
- *chars_written = len;
- len = len * sizeof(uint16_t);
+ *chars_written = nchars;
break;
+ }
case BASE64:
if (is_extern) {
- len = base64_decode(buf, buflen, data, extlen);
+ nbytes = base64_decode(buf, buflen, data, external_nbytes);
} else {
String::Value value(str);
- len = base64_decode(buf, buflen, *value, value.length());
+ nbytes = base64_decode(buf, buflen, *value, value.length());
}
if (chars_written != nullptr) {
- *chars_written = len;
+ *chars_written = nbytes;
}
break;
case HEX:
if (is_extern) {
- len = hex_decode(buf, buflen, data, extlen);
+ nbytes = hex_decode(buf, buflen, data, external_nbytes);
} else {
String::Value value(str);
- len = hex_decode(buf, buflen, *value, value.length());
+ nbytes = hex_decode(buf, buflen, *value, value.length());
}
if (chars_written != nullptr) {
- *chars_written = len * 2;
+ *chars_written = nbytes;
}
break;
break;
}
- return len;
+ return nbytes;
}