Skip to content

Commit

Permalink
buffer: move checkFloat from lib into src
Browse files Browse the repository at this point in the history
The type and range checks performed by this function can be done more
efficiently in native code.

PR-URL: #3763
Reviewed-By: Trevor Norris <[email protected]>
Reviewed-By: James M Snell <[email protected]>
  • Loading branch information
Matt Loring authored and rvagg committed Dec 5, 2015
1 parent f90227b commit fcf0e8e
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 29 deletions.
28 changes: 12 additions & 16 deletions lib/buffer.js
Original file line number Diff line number Diff line change
Expand Up @@ -1028,20 +1028,13 @@ Buffer.prototype.writeInt32BE = function(value, offset, noAssert) {
};


function checkFloat(buffer, value, offset, ext) {
if (!(buffer instanceof Buffer))
throw new TypeError('buffer must be a Buffer instance');
if (offset + ext > buffer.length)
throw new RangeError('index out of range');
}


Buffer.prototype.writeFloatLE = function writeFloatLE(val, offset, noAssert) {
val = +val;
offset = offset >>> 0;
if (!noAssert)
checkFloat(this, val, offset, 4);
binding.writeFloatLE(this, val, offset);
binding.writeFloatLE(this, val, offset);
else
binding.writeFloatLE(this, val, offset, true);
return offset + 4;
};

Expand All @@ -1050,8 +1043,9 @@ Buffer.prototype.writeFloatBE = function writeFloatBE(val, offset, noAssert) {
val = +val;
offset = offset >>> 0;
if (!noAssert)
checkFloat(this, val, offset, 4);
binding.writeFloatBE(this, val, offset);
binding.writeFloatBE(this, val, offset);
else
binding.writeFloatBE(this, val, offset, true);
return offset + 4;
};

Expand All @@ -1060,8 +1054,9 @@ Buffer.prototype.writeDoubleLE = function writeDoubleLE(val, offset, noAssert) {
val = +val;
offset = offset >>> 0;
if (!noAssert)
checkFloat(this, val, offset, 8);
binding.writeDoubleLE(this, val, offset);
binding.writeDoubleLE(this, val, offset);
else
binding.writeDoubleLE(this, val, offset, true);
return offset + 8;
};

Expand All @@ -1070,7 +1065,8 @@ Buffer.prototype.writeDoubleBE = function writeDoubleBE(val, offset, noAssert) {
val = +val;
offset = offset >>> 0;
if (!noAssert)
checkFloat(this, val, offset, 8);
binding.writeDoubleBE(this, val, offset);
binding.writeDoubleBE(this, val, offset);
else
binding.writeDoubleBE(this, val, offset, true);
return offset + 8;
};
43 changes: 30 additions & 13 deletions src/node_buffer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -730,15 +730,37 @@ void ReadDoubleBE(const FunctionCallbackInfo<Value>& args) {


template <typename T, enum Endianness endianness>
uint32_t WriteFloatGeneric(const FunctionCallbackInfo<Value>& args) {
SPREAD_ARG(args[0], ts_obj);
void WriteFloatGeneric(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);

bool should_assert = args.Length() < 4;

if (should_assert) {
THROW_AND_RETURN_UNLESS_BUFFER(env, args[0]);
}

Local<Uint8Array> ts_obj = args[0].As<Uint8Array>();
ArrayBuffer::Contents ts_obj_c = ts_obj->Buffer()->GetContents();
const size_t ts_obj_offset = ts_obj->ByteOffset();
const size_t ts_obj_length = ts_obj->ByteLength();
char* const ts_obj_data =
static_cast<char*>(ts_obj_c.Data()) + ts_obj_offset;
if (ts_obj_length > 0)
CHECK_NE(ts_obj_data, nullptr);

T val = args[1]->NumberValue(env->context()).FromMaybe(0);
size_t offset = args[2]->IntegerValue(env->context()).FromMaybe(0);

T val = args[1]->NumberValue();
uint32_t offset = args[2]->Uint32Value();
size_t memcpy_num = sizeof(T);
if (offset + sizeof(T) > ts_obj_length)
memcpy_num = ts_obj_length - offset;

if (should_assert) {
CHECK_NOT_OOB(offset + memcpy_num >= memcpy_num);
CHECK_NOT_OOB(offset + memcpy_num <= ts_obj_length);
}
CHECK_LE(offset + memcpy_num, ts_obj_length);

union NoAlias {
T val;
char bytes[sizeof(T)];
Expand All @@ -749,31 +771,26 @@ uint32_t WriteFloatGeneric(const FunctionCallbackInfo<Value>& args) {
if (endianness != GetEndianness())
Swizzle(na.bytes, sizeof(na.bytes));
memcpy(ptr, na.bytes, memcpy_num);
return offset + memcpy_num;
}


void WriteFloatLE(const FunctionCallbackInfo<Value>& args) {
THROW_AND_RETURN_UNLESS_BUFFER(Environment::GetCurrent(args), args[0]);
args.GetReturnValue().Set(WriteFloatGeneric<float, kLittleEndian>(args));
WriteFloatGeneric<float, kLittleEndian>(args);
}


void WriteFloatBE(const FunctionCallbackInfo<Value>& args) {
THROW_AND_RETURN_UNLESS_BUFFER(Environment::GetCurrent(args), args[0]);
args.GetReturnValue().Set(WriteFloatGeneric<float, kBigEndian>(args));
WriteFloatGeneric<float, kBigEndian>(args);
}


void WriteDoubleLE(const FunctionCallbackInfo<Value>& args) {
THROW_AND_RETURN_UNLESS_BUFFER(Environment::GetCurrent(args), args[0]);
args.GetReturnValue().Set(WriteFloatGeneric<double, kLittleEndian>(args));
WriteFloatGeneric<double, kLittleEndian>(args);
}


void WriteDoubleBE(const FunctionCallbackInfo<Value>& args) {
THROW_AND_RETURN_UNLESS_BUFFER(Environment::GetCurrent(args), args[0]);
args.GetReturnValue().Set(WriteFloatGeneric<double, kBigEndian>(args));
WriteFloatGeneric<double, kBigEndian>(args);
}


Expand Down

0 comments on commit fcf0e8e

Please sign in to comment.