Skip to content

Commit bec924f

Browse files
trevnorrisrvagg
authored andcommitted
buffer: allow ARGS_THIS to accept a name
Allowing the name to be passed to the ARGS_THIS macro will make it easier to share code with the Uint8Array implementation. PR-URL: #1825 Reviewed-By: Ben Noordhuis <[email protected]>
1 parent 8335ece commit bec924f

File tree

1 file changed

+81
-58
lines changed

1 file changed

+81
-58
lines changed

src/node_buffer.cc

+81-58
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,17 @@
2424
return env->ThrowTypeError("argument should be a Buffer"); \
2525
} while (0)
2626

27-
#define ARGS_THIS(argT) \
28-
Local<Object> obj = argT; \
29-
size_t obj_length = obj->GetIndexedPropertiesExternalArrayDataLength(); \
30-
char* obj_data = static_cast<char*>( \
31-
obj->GetIndexedPropertiesExternalArrayData()); \
32-
if (obj_length > 0) \
33-
CHECK_NE(obj_data, nullptr);
27+
#define ARGS_THIS_DEC(name) \
28+
size_t name##_length; \
29+
char* name##_data;
30+
31+
#define ARGS_THIS(argT, name) \
32+
Local<Object> name = argT; \
33+
name##_length = name->GetIndexedPropertiesExternalArrayDataLength(); \
34+
name##_data = static_cast<char*>( \
35+
name->GetIndexedPropertiesExternalArrayData()); \
36+
if (name##_length > 0) \
37+
CHECK_NE(name##_data, nullptr);
3438

3539
#define SLICE_START_END(start_arg, end_arg, end_max) \
3640
size_t start; \
@@ -228,34 +232,40 @@ Local<Object> Use(Environment* env, char* data, uint32_t length) {
228232
template <encoding encoding>
229233
void StringSlice(const FunctionCallbackInfo<Value>& args) {
230234
Environment* env = Environment::GetCurrent(args);
235+
Isolate* isolate = env->isolate();
231236

232237
THROW_AND_RETURN_UNLESS_BUFFER(env, args.This());
233-
ARGS_THIS(args.This())
234238

235-
if (obj_length == 0)
239+
ARGS_THIS_DEC(ts_obj);
240+
ARGS_THIS(args.This(), ts_obj);
241+
242+
if (ts_obj_length == 0)
236243
return args.GetReturnValue().SetEmptyString();
237244

238-
SLICE_START_END(args[0], args[1], obj_length)
245+
SLICE_START_END(args[0], args[1], ts_obj_length)
239246

240247
args.GetReturnValue().Set(
241-
StringBytes::Encode(env->isolate(), obj_data + start, length, encoding));
248+
StringBytes::Encode(isolate, ts_obj_data + start, length, encoding));
242249
}
243250

244251

245252
template <>
246253
void StringSlice<UCS2>(const FunctionCallbackInfo<Value>& args) {
247254
Environment* env = Environment::GetCurrent(args);
255+
ARGS_THIS_DEC(ts_obj);
248256

249257
THROW_AND_RETURN_UNLESS_BUFFER(env, args.This());
250-
ARGS_THIS(args.This())
258+
ARGS_THIS(args.This(), ts_obj);
259+
260+
261+
SLICE_START_END(args[0], args[1], ts_obj_length)
251262

252-
if (obj_length == 0)
263+
if (ts_obj_length == 0)
253264
return args.GetReturnValue().SetEmptyString();
254265

255-
SLICE_START_END(args[0], args[1], obj_length)
256266
length /= 2;
257267

258-
const char* data = obj_data + start;
268+
const char* data = ts_obj_data + start;
259269
const uint16_t* buf;
260270
bool release = false;
261271

@@ -322,10 +332,13 @@ void Copy(const FunctionCallbackInfo<Value> &args) {
322332
if (!HasInstance(args[0]))
323333
return env->ThrowTypeError("first arg should be a Buffer");
324334

325-
Local<Object> target = args[0].As<Object>();
326-
327335
THROW_AND_RETURN_UNLESS_BUFFER(env, args.This());
328-
ARGS_THIS(args.This())
336+
337+
Local<Object> target = args[0]->ToObject(env->isolate());
338+
ARGS_THIS_DEC(ts_obj);
339+
340+
ARGS_THIS(args.This(), ts_obj);
341+
329342
size_t target_length = target->GetIndexedPropertiesExternalArrayDataLength();
330343
char* target_data = static_cast<char*>(
331344
target->GetIndexedPropertiesExternalArrayData());
@@ -335,63 +348,64 @@ void Copy(const FunctionCallbackInfo<Value> &args) {
335348

336349
CHECK_NOT_OOB(ParseArrayIndex(args[1], 0, &target_start));
337350
CHECK_NOT_OOB(ParseArrayIndex(args[2], 0, &source_start));
338-
CHECK_NOT_OOB(ParseArrayIndex(args[3], obj_length, &source_end));
351+
CHECK_NOT_OOB(ParseArrayIndex(args[3], ts_obj_length, &source_end));
339352

340353
// Copy 0 bytes; we're done
341354
if (target_start >= target_length || source_start >= source_end)
342355
return args.GetReturnValue().Set(0);
343356

344-
if (source_start > obj_length)
357+
if (source_start > ts_obj_length)
345358
return env->ThrowRangeError("out of range index");
346359

347360
if (source_end - source_start > target_length - target_start)
348361
source_end = source_start + target_length - target_start;
349362

350363
uint32_t to_copy = MIN(MIN(source_end - source_start,
351364
target_length - target_start),
352-
obj_length - source_start);
365+
ts_obj_length - source_start);
353366

354-
memmove(target_data + target_start, obj_data + source_start, to_copy);
367+
memmove(target_data + target_start, ts_obj_data + source_start, to_copy);
355368
args.GetReturnValue().Set(to_copy);
356369
}
357370

358371

359372
void Fill(const FunctionCallbackInfo<Value>& args) {
360373
THROW_AND_RETURN_UNLESS_BUFFER(Environment::GetCurrent(args), args[0]);
361-
ARGS_THIS(args[0].As<Object>())
374+
ARGS_THIS_DEC(ts_obj);
375+
ARGS_THIS(args[0].As<Object>(), ts_obj);
362376

363377
size_t start = args[2]->Uint32Value();
364378
size_t end = args[3]->Uint32Value();
365379
size_t length = end - start;
366-
CHECK(length + start <= obj_length);
380+
CHECK(length + start <= ts_obj_length);
367381

368382
if (args[1]->IsNumber()) {
369383
int value = args[1]->Uint32Value() & 255;
370-
memset(obj_data + start, value, length);
384+
memset(ts_obj_data + start, value, length);
371385
return;
372386
}
373387

374388
node::Utf8Value str(args.GetIsolate(), args[1]);
375389
size_t str_length = str.length();
376390
size_t in_there = str_length;
377-
char* ptr = obj_data + start + str_length;
391+
char* ptr = ts_obj_data + start + str_length;
378392

379393
if (str_length == 0)
380394
return;
381395

382-
memcpy(obj_data + start, *str, MIN(str_length, length));
396+
memcpy(ts_obj_data + start, *str, MIN(str_length, length));
383397

384398
if (str_length >= length)
385399
return;
386400

387401
while (in_there < length - in_there) {
388-
memcpy(ptr, obj_data + start, in_there);
402+
memcpy(ptr, ts_obj_data + start, in_there);
389403
ptr += in_there;
390404
in_there *= 2;
391405
}
392406

393407
if (in_there < length) {
394-
memcpy(ptr, obj_data + start, length - in_there);
408+
memcpy(ptr, ts_obj_data + start, length - in_there);
395409
in_there = length;
396410
}
397411
}
@@ -400,9 +414,10 @@ void Fill(const FunctionCallbackInfo<Value>& args) {
400414
template <encoding encoding>
401415
void StringWrite(const FunctionCallbackInfo<Value>& args) {
402416
Environment* env = Environment::GetCurrent(args);
417+
ARGS_THIS_DEC(ts_obj);
403418

404419
THROW_AND_RETURN_UNLESS_BUFFER(env, args.This());
405-
ARGS_THIS(args.This())
420+
ARGS_THIS(args.This(), ts_obj);
406421

407422
if (!args[0]->IsString())
408423
return env->ThrowTypeError("Argument must be a string");
@@ -416,18 +431,18 @@ void StringWrite(const FunctionCallbackInfo<Value>& args) {
416431
size_t max_length;
417432

418433
CHECK_NOT_OOB(ParseArrayIndex(args[1], 0, &offset));
419-
CHECK_NOT_OOB(ParseArrayIndex(args[2], obj_length - offset, &max_length));
434+
CHECK_NOT_OOB(ParseArrayIndex(args[2], ts_obj_length - offset, &max_length));
420435

421-
max_length = MIN(obj_length - offset, max_length);
436+
max_length = MIN(ts_obj_length - offset, max_length);
422437

423438
if (max_length == 0)
424439
return args.GetReturnValue().Set(0);
425440

426-
if (offset >= obj_length)
441+
if (offset >= ts_obj_length)
427442
return env->ThrowRangeError("Offset is out of bounds");
428443

429444
uint32_t written = StringBytes::Write(env->isolate(),
430-
obj_data + offset,
445+
ts_obj_data + offset,
431446
max_length,
432447
str,
433448
encoding,
@@ -479,18 +494,19 @@ static inline void Swizzle(char* start, unsigned int len) {
479494
template <typename T, enum Endianness endianness>
480495
void ReadFloatGeneric(const FunctionCallbackInfo<Value>& args) {
481496
THROW_AND_RETURN_UNLESS_BUFFER(Environment::GetCurrent(args), args[0]);
482-
ARGS_THIS(args[0].As<Object>());
497+
ARGS_THIS_DEC(ts_obj);
498+
ARGS_THIS(args[0].As<Object>(), ts_obj);
483499

484500
uint32_t offset = args[1]->Uint32Value();
485-
CHECK_LE(offset + sizeof(T), obj_length);
501+
CHECK_LE(offset + sizeof(T), ts_obj_length);
486502

487503
union NoAlias {
488504
T val;
489505
char bytes[sizeof(T)];
490506
};
491507

492508
union NoAlias na;
493-
const char* ptr = static_cast<const char*>(obj_data) + offset;
509+
const char* ptr = static_cast<const char*>(ts_obj_data) + offset;
494510
memcpy(na.bytes, ptr, sizeof(na.bytes));
495511
if (endianness != GetEndianness())
496512
Swizzle(na.bytes, sizeof(na.bytes));
@@ -521,19 +537,20 @@ void ReadDoubleBE(const FunctionCallbackInfo<Value>& args) {
521537

522538
template <typename T, enum Endianness endianness>
523539
uint32_t WriteFloatGeneric(const FunctionCallbackInfo<Value>& args) {
524-
ARGS_THIS(args[0].As<Object>())
540+
ARGS_THIS_DEC(ts_obj);
541+
ARGS_THIS(args[0].As<Object>(), ts_obj);
525542

526543
T val = args[1]->NumberValue();
527544
uint32_t offset = args[2]->Uint32Value();
528-
CHECK_LE(offset + sizeof(T), obj_length);
545+
CHECK_LE(offset + sizeof(T), ts_obj_length);
529546

530547
union NoAlias {
531548
T val;
532549
char bytes[sizeof(T)];
533550
};
534551

535552
union NoAlias na = { val };
536-
char* ptr = static_cast<char*>(obj_data) + offset;
553+
char* ptr = static_cast<char*>(ts_obj_data) + offset;
537554
if (endianness != GetEndianness())
538555
Swizzle(na.bytes, sizeof(na.bytes));
539556
memcpy(ptr, na.bytes, sizeof(na.bytes));
@@ -631,28 +648,30 @@ void IndexOfString(const FunctionCallbackInfo<Value>& args) {
631648
ASSERT(args[2]->IsNumber());
632649

633650
THROW_AND_RETURN_UNLESS_BUFFER(Environment::GetCurrent(args), args[0]);
634-
ARGS_THIS(args[0].As<Object>());
651+
ARGS_THIS_DEC(ts_obj);
652+
ARGS_THIS(args[0].As<Object>(), ts_obj);
653+
635654
node::Utf8Value str(args.GetIsolate(), args[1]);
636655
int32_t offset_i32 = args[2]->Int32Value();
637656
uint32_t offset;
638657

639658
if (offset_i32 < 0) {
640-
if (offset_i32 + static_cast<int32_t>(obj_length) < 0)
659+
if (offset_i32 + static_cast<int32_t>(ts_obj_length) < 0)
641660
offset = 0;
642661
else
643-
offset = static_cast<uint32_t>(obj_length + offset_i32);
662+
offset = static_cast<uint32_t>(ts_obj_length + offset_i32);
644663
} else {
645664
offset = static_cast<uint32_t>(offset_i32);
646665
}
647666

648667
if (str.length() == 0 ||
649-
obj_length == 0 ||
668+
ts_obj_length == 0 ||
650669
(offset != 0 && str.length() + offset <= str.length()) ||
651-
str.length() + offset > obj_length)
670+
str.length() + offset > ts_obj_length)
652671
return args.GetReturnValue().Set(-1);
653672

654673
int32_t r =
655-
IndexOf(obj_data + offset, obj_length - offset, *str, str.length());
674+
IndexOf(ts_obj_data + offset, ts_obj_length - offset, *str, str.length());
656675
args.GetReturnValue().Set(r == -1 ? -1 : static_cast<int32_t>(r + offset));
657676
}
658677

@@ -662,7 +681,9 @@ void IndexOfBuffer(const FunctionCallbackInfo<Value>& args) {
662681
ASSERT(args[2]->IsNumber());
663682

664683
THROW_AND_RETURN_UNLESS_BUFFER(Environment::GetCurrent(args), args[0]);
665-
ARGS_THIS(args[0].As<Object>());
684+
ARGS_THIS_DEC(ts_obj);
685+
ARGS_THIS(args[0].As<Object>(), ts_obj);
686+
666687
Local<Object> buf = args[1].As<Object>();
667688
int32_t offset_i32 = args[2]->Int32Value();
668689
size_t buf_length = buf->GetIndexedPropertiesExternalArrayDataLength();
@@ -674,22 +695,22 @@ void IndexOfBuffer(const FunctionCallbackInfo<Value>& args) {
674695
CHECK_NE(buf_data, nullptr);
675696

676697
if (offset_i32 < 0) {
677-
if (offset_i32 + static_cast<int32_t>(obj_length) < 0)
698+
if (offset_i32 + static_cast<int32_t>(ts_obj_length) < 0)
678699
offset = 0;
679700
else
680-
offset = static_cast<uint32_t>(obj_length + offset_i32);
701+
offset = static_cast<uint32_t>(ts_obj_length + offset_i32);
681702
} else {
682703
offset = static_cast<uint32_t>(offset_i32);
683704
}
684705

685706
if (buf_length == 0 ||
686-
obj_length == 0 ||
707+
ts_obj_length == 0 ||
687708
(offset != 0 && buf_length + offset <= buf_length) ||
688-
buf_length + offset > obj_length)
709+
buf_length + offset > ts_obj_length)
689710
return args.GetReturnValue().Set(-1);
690711

691712
int32_t r =
692-
IndexOf(obj_data + offset, obj_length - offset, buf_data, buf_length);
713+
IndexOf(ts_obj_data + offset, ts_obj_length - offset, buf_data, buf_length);
693714
args.GetReturnValue().Set(r == -1 ? -1 : static_cast<int32_t>(r + offset));
694715
}
695716

@@ -699,27 +720,29 @@ void IndexOfNumber(const FunctionCallbackInfo<Value>& args) {
699720
ASSERT(args[2]->IsNumber());
700721

701722
THROW_AND_RETURN_UNLESS_BUFFER(Environment::GetCurrent(args), args[0]);
702-
ARGS_THIS(args[0].As<Object>());
723+
ARGS_THIS_DEC(ts_obj);
724+
ARGS_THIS(args[0].As<Object>(), ts_obj);
725+
703726
uint32_t needle = args[1]->Uint32Value();
704727
int32_t offset_i32 = args[2]->Int32Value();
705728
uint32_t offset;
706729

707730
if (offset_i32 < 0) {
708-
if (offset_i32 + static_cast<int32_t>(obj_length) < 0)
731+
if (offset_i32 + static_cast<int32_t>(ts_obj_length) < 0)
709732
offset = 0;
710733
else
711-
offset = static_cast<uint32_t>(obj_length + offset_i32);
734+
offset = static_cast<uint32_t>(ts_obj_length + offset_i32);
712735
} else {
713736
offset = static_cast<uint32_t>(offset_i32);
714737
}
715738

716-
if (obj_length == 0 || offset + 1 > obj_length)
739+
if (ts_obj_length == 0 || offset + 1 > ts_obj_length)
717740
return args.GetReturnValue().Set(-1);
718741

719-
void* ptr = memchr(obj_data + offset, needle, obj_length - offset);
742+
void* ptr = memchr(ts_obj_data + offset, needle, ts_obj_length - offset);
720743
char* ptr_char = static_cast<char*>(ptr);
721744
args.GetReturnValue().Set(
722-
ptr ? static_cast<int32_t>(ptr_char - obj_data) : -1);
745+
ptr ? static_cast<int32_t>(ptr_char - ts_obj_data) : -1);
723746
}
724747

725748

0 commit comments

Comments
 (0)