diff --git a/benchmark/buffers/buffer-write-string.js b/benchmark/buffers/buffer-write-string.js index e02a38fc857b37..4544e17b0cd72c 100644 --- a/benchmark/buffers/buffer-write-string.js +++ b/benchmark/buffers/buffer-write-string.js @@ -3,7 +3,7 @@ const common = require('../common.js'); const bench = common.createBenchmark(main, { len: [1,8,16,32], - n: [1e6], + n: [1], }); function main({ len, n }) { @@ -12,7 +12,7 @@ function main({ len, n }) { bench.start(); for (let i = 0; i < n; ++i) { - buf.asciiWrite(string); + buf.write(string, 0, len, 'ascii'); } bench.end(n); } diff --git a/lib/buffer.js b/lib/buffer.js index 59a125960c276f..37051c94073a49 100644 --- a/lib/buffer.js +++ b/lib/buffer.js @@ -55,6 +55,7 @@ const { } = primordials; const { + stringWrite, byteLengthUtf8, compare: _compare, compareOffset, @@ -657,7 +658,7 @@ const encodingOps = { encoding: 'ascii', encodingVal: encodingsMap.ascii, byteLength: (string) => string.length, - write: (buf, string, offset, len) => buf.asciiWrite(string, offset, len), + write: (buf, string, offset, len) => stringWrite(buf, string, offset, len), slice: (buf, start, end) => buf.asciiSlice(start, end), indexOf: (buf, val, byteOffset, dir) => indexOfBuffer(buf, diff --git a/src/node_buffer.cc b/src/node_buffer.cc index 6c30804f3b0b31..cf4c3e7ab39e83 100644 --- a/src/node_buffer.cc +++ b/src/node_buffer.cc @@ -19,6 +19,7 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE // USE OR OTHER DEALINGS IN THE SOFTWARE. +#include #include "node_buffer.h" #include "node.h" #include "node_blob.h" @@ -761,6 +762,41 @@ static v8::CFunction fast_byte_length_utf8( v8::CFunction::Make(FastByteLengthUtf8)); +template +void SlowWriteString(const FunctionCallbackInfo& args) { + Environment* env = Environment::GetCurrent(args); + + THROW_AND_RETURN_UNLESS_BUFFER(env, args[0]); + SPREAD_BUFFER_ARG(args[0], ts_obj); + + THROW_AND_RETURN_IF_NOT_STRING(env, args[1], "argument"); + + Local str = args[1]->ToString(env->context()).ToLocalChecked(); + + std::cerr << "SlowWriteString " << str->IsOneByte() << std::endl; + + size_t offset = 0; + size_t max_length = 0; + + THROW_AND_RETURN_IF_OOB(ParseArrayIndex(env, args[2], 0, &offset)); + if (offset > ts_obj_length) { + return node::THROW_ERR_BUFFER_OUT_OF_BOUNDS( + env, "\"offset\" is outside of buffer bounds"); + } + + THROW_AND_RETURN_IF_OOB(ParseArrayIndex(env, args[3], ts_obj_length - offset, + &max_length)); + + max_length = std::min(ts_obj_length - offset, max_length); + + if (max_length == 0) + return args.GetReturnValue().Set(0); + + uint32_t written = StringBytes::Write( + env->isolate(), ts_obj_data + offset, max_length, str, encoding); + args.GetReturnValue().Set(written); +} + uint32_t FastWriteString(Local receiver, const v8::FastApiTypedArray& dst, const v8::FastOneByteString& src, @@ -769,6 +805,10 @@ uint32_t FastWriteString(Local receiver, uint8_t* dst_data; CHECK(dst.getStorageIfAligned(&dst_data)); + // XXX: Throw "\"offset\" is outside of buffer bound + + std::cerr << "FastWriteString" << std::endl; + memcpy(dst_data, src.data, max_length); return max_length; @@ -1331,11 +1371,7 @@ void Initialize(Local target, SetMethodNoSideEffect(context, target, "ucs2Slice", StringSlice); SetMethodNoSideEffect(context, target, "utf8Slice", StringSlice); - SetFastMethodNoSideEffect(context, - target, - "asciiWrite", - StringWrite, - &fast_write_string); + SetMethod(context, target, "asciiWrite", StringWrite); SetMethod(context, target, "base64Write", StringWrite); SetMethod(context, target, "base64urlWrite", StringWrite); SetMethod(context, target, "latin1Write", StringWrite); @@ -1343,6 +1379,12 @@ void Initialize(Local target, SetMethod(context, target, "ucs2Write", StringWrite); SetMethod(context, target, "utf8Write", StringWrite); + SetFastMethodNoSideEffect(context, + target, + "stringWrite", + SlowWriteString, + &fast_write_string); + SetMethod(context, target, "getZeroFillToggle", GetZeroFillToggle); }