GCC Code Coverage Report
Directory: ../src/ Exec Total Coverage
File: /home/node-core-coverage/node-core-coverage/workdir/node/out/../src/node_buffer.cc Lines: 568 606 93.7 %
Date: 2016-11-30 Branches: 501 794 63.1 %

Line Branch Exec Source
1
#include "node.h"
2
#include "node_buffer.h"
3
4
#include "env.h"
5
#include "env-inl.h"
6
#include "string_bytes.h"
7
#include "string_search.h"
8
#include "util.h"
9
#include "util-inl.h"
10
#include "v8-profiler.h"
11
#include "v8.h"
12
13
#include <string.h>
14
#include <limits.h>
15
16
#define BUFFER_ID 0xB0E4
17
18
#define MIN(a, b) ((a) < (b) ? (a) : (b))
19
20
#define THROW_AND_RETURN_IF_OOB(r)                                          \
21
  do {                                                                      \
22
    if (!(r)) return env->ThrowRangeError("out of range index");            \
23
  } while (0)
24
25
#define SLICE_START_END(start_arg, end_arg, end_max)                        \
26
  size_t start;                                                             \
27
  size_t end;                                                               \
28
  THROW_AND_RETURN_IF_OOB(ParseArrayIndex(start_arg, 0, &start));           \
29
  THROW_AND_RETURN_IF_OOB(ParseArrayIndex(end_arg, end_max, &end));         \
30
  if (end < start) end = start;                                             \
31
  THROW_AND_RETURN_IF_OOB(end <= end_max);                                  \
32
  size_t length = end - start;
33
34
namespace node {
35
36
// if true, all Buffer and SlowBuffer instances will automatically zero-fill
37
bool zero_fill_all_buffers = false;
38
39
namespace {
40
41
1886
inline void* BufferMalloc(size_t length) {
42
  return zero_fill_all_buffers ? node::UncheckedCalloc(length) :
43
3772
                                 node::UncheckedMalloc(length);
44
}
45
46
}  // namespace
47
48
namespace Buffer {
49
50
using v8::ArrayBuffer;
51
using v8::ArrayBufferCreationMode;
52
using v8::Context;
53
using v8::EscapableHandleScope;
54
using v8::FunctionCallbackInfo;
55
using v8::Integer;
56
using v8::Isolate;
57
using v8::Local;
58
using v8::Maybe;
59
using v8::MaybeLocal;
60
using v8::Object;
61
using v8::Persistent;
62
using v8::String;
63
using v8::Uint32Array;
64
using v8::Uint8Array;
65
using v8::Value;
66
using v8::WeakCallbackInfo;
67
68
class CallbackInfo {
69
 public:
70
  static inline void Free(char* data, void* hint);
71
  static inline CallbackInfo* New(Isolate* isolate,
72
                                  Local<ArrayBuffer> object,
73
                                  FreeCallback callback,
74
                                  char* data,
75
                                  void* hint = 0);
76
 private:
77
  static void WeakCallback(const WeakCallbackInfo<CallbackInfo>&);
78
  inline void WeakCallback(Isolate* isolate);
79
  inline CallbackInfo(Isolate* isolate,
80
                      Local<ArrayBuffer> object,
81
                      FreeCallback callback,
82
                      char* data,
83
                      void* hint);
84
  ~CallbackInfo();
85
  Persistent<ArrayBuffer> persistent_;
86
  FreeCallback const callback_;
87
  char* const data_;
88
  void* const hint_;
89
  DISALLOW_COPY_AND_ASSIGN(CallbackInfo);
90
};
91
92
93
void CallbackInfo::Free(char* data, void*) {
94
  ::free(data);
95
}
96
97
98
12
CallbackInfo* CallbackInfo::New(Isolate* isolate,
99
                                Local<ArrayBuffer> object,
100
                                FreeCallback callback,
101
                                char* data,
102
                                void* hint) {
103
12
  return new CallbackInfo(isolate, object, callback, data, hint);
104
}
105
106
107
12
CallbackInfo::CallbackInfo(Isolate* isolate,
108
                           Local<ArrayBuffer> object,
109
                           FreeCallback callback,
110
                           char* data,
111
                           void* hint)
112
    : persistent_(isolate, object),
113
      callback_(callback),
114
      data_(data),
115
24
      hint_(hint) {
116
12
  ArrayBuffer::Contents obj_c = object->GetContents();
117
12
  CHECK_EQ(data_, static_cast<char*>(obj_c.Data()));
118
12
  if (object->ByteLength() != 0)
119
10
    CHECK_NE(data_, nullptr);
120
121
24
  persistent_.SetWeak(this, WeakCallback, v8::WeakCallbackType::kParameter);
122
24
  persistent_.SetWrapperClassId(BUFFER_ID);
123
24
  persistent_.MarkIndependent();
124
24
  isolate->AdjustAmountOfExternalAllocatedMemory(sizeof(*this));
125
12
}
126
127
128
24
CallbackInfo::~CallbackInfo() {
129
24
  persistent_.Reset();
130
}
131
132
133
12
void CallbackInfo::WeakCallback(
134
    const WeakCallbackInfo<CallbackInfo>& data) {
135
12
  CallbackInfo* self = data.GetParameter();
136
24
  self->WeakCallback(data.GetIsolate());
137
24
  delete self;
138
12
}
139
140
141
void CallbackInfo::WeakCallback(Isolate* isolate) {
142
12
  callback_(data_, hint_);
143
12
  int64_t change_in_bytes = -static_cast<int64_t>(sizeof(*this));
144
12
  isolate->AdjustAmountOfExternalAllocatedMemory(change_in_bytes);
145
}
146
147
148
// Parse index for external array data.
149
916514
inline MUST_USE_RESULT bool ParseArrayIndex(Local<Value> arg,
150
                                            size_t def,
151
                                            size_t* ret) {
152
1833028
  if (arg->IsUndefined()) {
153
529937
    *ret = def;
154
529937
    return true;
155
  }
156
157
386577
  int64_t tmp_i = arg->IntegerValue();
158
159
386577
  if (tmp_i < 0)
160
    return false;
161
162
  // Check that the result fits in a size_t.
163
386575
  const uint64_t kSizeMax = static_cast<uint64_t>(static_cast<size_t>(-1));
164
  // coverity[pointless_expression]
165
  if (static_cast<uint64_t>(tmp_i) > kSizeMax)
166
    return false;
167
168
386575
  *ret = static_cast<size_t>(tmp_i);
169
386575
  return true;
170
}
171
172
173
// Buffer methods
174
175
600416
bool HasInstance(Local<Value> val) {
176
873131
  return val->IsUint8Array();
177
}
178
179
180
50
bool HasInstance(Local<Object> obj) {
181
323830
  return obj->IsUint8Array();
182
}
183
184
185
26681
char* Data(Local<Value> val) {
186
26681
  CHECK(val->IsUint8Array());
187
26681
  Local<Uint8Array> ui = val.As<Uint8Array>();
188
53362
  ArrayBuffer::Contents ab_c = ui->Buffer()->GetContents();
189
26681
  return static_cast<char*>(ab_c.Data()) + ui->ByteOffset();
190
}
191
192
193
37048
char* Data(Local<Object> obj) {
194
37048
  CHECK(obj->IsUint8Array());
195
37048
  Local<Uint8Array> ui = obj.As<Uint8Array>();
196
74096
  ArrayBuffer::Contents ab_c = ui->Buffer()->GetContents();
197
37048
  return static_cast<char*>(ab_c.Data()) + ui->ByteOffset();
198
}
199
200
201
26680
size_t Length(Local<Value> val) {
202
26680
  CHECK(val->IsUint8Array());
203
26680
  Local<Uint8Array> ui = val.As<Uint8Array>();
204
26680
  return ui->ByteLength();
205
}
206
207
208
36796
size_t Length(Local<Object> obj) {
209
36796
  CHECK(obj->IsUint8Array());
210
36796
  Local<Uint8Array> ui = obj.As<Uint8Array>();
211
36796
  return ui->ByteLength();
212
}
213
214
215
1738
MaybeLocal<Object> New(Isolate* isolate,
216
                       Local<String> string,
217
                       enum encoding enc) {
218
3476
  EscapableHandleScope scope(isolate);
219
220
1738
  const size_t length = StringBytes::Size(isolate, string, enc);
221
1738
  size_t actual = 0;
222
1738
  char* data = nullptr;
223
224
1738
  if (length > 0) {
225
1738
    data = static_cast<char*>(BufferMalloc(length));
226
227
1738
    if (data == nullptr)
228
      return Local<Object>();
229
230
1738
    actual = StringBytes::Write(isolate, data, length, string, enc);
231
1738
    CHECK(actual <= length);
232
233
1738
    if (actual == 0) {
234
1
      free(data);
235
1
      data = nullptr;
236
1737
    } else if (actual < length) {
237
25
      data = node::Realloc(data, actual);
238
    }
239
  }
240
241
1738
  Local<Object> buf;
242
3476
  if (New(isolate, data, actual).ToLocal(&buf))
243
3476
    return scope.Escape(buf);
244
245
  // Object failed to be created. Clean up resources.
246
  free(data);
247
  return Local<Object>();
248
}
249
250
251
MaybeLocal<Object> New(Isolate* isolate, size_t length) {
252
  EscapableHandleScope handle_scope(isolate);
253
  Local<Object> obj;
254
  if (Buffer::New(Environment::GetCurrent(isolate), length).ToLocal(&obj))
255
    return handle_scope.Escape(obj);
256
  return Local<Object>();
257
}
258
259
260
258
MaybeLocal<Object> New(Environment* env, size_t length) {
261
516
  EscapableHandleScope scope(env->isolate());
262
263
  // V8 currently only allows a maximum Typed Array index of max Smi.
264
258
  if (length > kMaxLength) {
265
    return Local<Object>();
266
  }
267
268
  void* data;
269
258
  if (length > 0) {
270
148
    data = BufferMalloc(length);
271
148
    if (data == nullptr)
272
      return Local<Object>();
273
  } else {
274
    data = nullptr;
275
  }
276
277
  Local<ArrayBuffer> ab =
278
    ArrayBuffer::New(env->isolate(),
279
        data,
280
        length,
281
258
        ArrayBufferCreationMode::kInternalized);
282
258
  Local<Uint8Array> ui = Uint8Array::New(ab, 0, length);
283
  Maybe<bool> mb =
284
1032
      ui->SetPrototype(env->context(), env->buffer_prototype_object());
285
516
  if (mb.FromMaybe(false))
286
516
    return scope.Escape(ui);
287
288
  // Object failed to be created. Clean up resources.
289
  free(data);
290
  return Local<Object>();
291
}
292
293
294
983
MaybeLocal<Object> Copy(Isolate* isolate, const char* data, size_t length) {
295
1966
  EscapableHandleScope handle_scope(isolate);
296
983
  Environment* env = Environment::GetCurrent(isolate);
297
983
  Local<Object> obj;
298
1966
  if (Buffer::Copy(env, data, length).ToLocal(&obj))
299
1966
    return handle_scope.Escape(obj);
300
  return Local<Object>();
301
}
302
303
304
1348
MaybeLocal<Object> Copy(Environment* env, const char* data, size_t length) {
305
2696
  EscapableHandleScope scope(env->isolate());
306
307
  // V8 currently only allows a maximum Typed Array index of max Smi.
308
1348
  if (length > kMaxLength) {
309
    return Local<Object>();
310
  }
311
312
  void* new_data;
313
1348
  if (length > 0) {
314
1258
    CHECK_NE(data, nullptr);
315
1258
    new_data = node::UncheckedMalloc(length);
316
1258
    if (new_data == nullptr)
317
      return Local<Object>();
318
    memcpy(new_data, data, length);
319
  } else {
320
    new_data = nullptr;
321
  }
322
323
  Local<ArrayBuffer> ab =
324
    ArrayBuffer::New(env->isolate(),
325
        new_data,
326
        length,
327
1348
        ArrayBufferCreationMode::kInternalized);
328
1348
  Local<Uint8Array> ui = Uint8Array::New(ab, 0, length);
329
  Maybe<bool> mb =
330
5392
      ui->SetPrototype(env->context(), env->buffer_prototype_object());
331
2696
  if (mb.FromMaybe(false))
332
2696
    return scope.Escape(ui);
333
334
  // Object failed to be created. Clean up resources.
335
  free(new_data);
336
  return Local<Object>();
337
}
338
339
340
12
MaybeLocal<Object> New(Isolate* isolate,
341
                       char* data,
342
                       size_t length,
343
                       FreeCallback callback,
344
                       void* hint) {
345
24
  EscapableHandleScope handle_scope(isolate);
346
12
  Environment* env = Environment::GetCurrent(isolate);
347
12
  Local<Object> obj;
348
24
  if (Buffer::New(env, data, length, callback, hint).ToLocal(&obj))
349
24
    return handle_scope.Escape(obj);
350
  return Local<Object>();
351
}
352
353
354
12
MaybeLocal<Object> New(Environment* env,
355
                       char* data,
356
                       size_t length,
357
                       FreeCallback callback,
358
                       void* hint) {
359
24
  EscapableHandleScope scope(env->isolate());
360
361
12
  if (length > kMaxLength) {
362
    return Local<Object>();
363
  }
364
365
12
  Local<ArrayBuffer> ab = ArrayBuffer::New(env->isolate(), data, length);
366
  // `Neuter()`ing is required here to prevent materialization of the backing
367
  // store in v8. `nullptr` buffers are not writable, so this is semantically
368
  // correct.
369
12
  if (data == nullptr)
370
1
    ab->Neuter();
371
12
  Local<Uint8Array> ui = Uint8Array::New(ab, 0, length);
372
  Maybe<bool> mb =
373
48
      ui->SetPrototype(env->context(), env->buffer_prototype_object());
374
375
24
  if (!mb.FromMaybe(false))
376
    return Local<Object>();
377
378
12
  CallbackInfo::New(env->isolate(), ab, callback, data, hint);
379
24
  return scope.Escape(ui);
380
}
381
382
383
1740
MaybeLocal<Object> New(Isolate* isolate, char* data, size_t length) {
384
3480
  EscapableHandleScope handle_scope(isolate);
385
1740
  Environment* env = Environment::GetCurrent(isolate);
386
1740
  Local<Object> obj;
387
3480
  if (Buffer::New(env, data, length).ToLocal(&obj))
388
3480
    return handle_scope.Escape(obj);
389
  return Local<Object>();
390
}
391
392
393
20247
MaybeLocal<Object> New(Environment* env, char* data, size_t length) {
394
40494
  EscapableHandleScope scope(env->isolate());
395
396
20247
  if (length > 0) {
397
20230
    CHECK_NE(data, nullptr);
398
20230
    CHECK(length <= kMaxLength);
399
  }
400
401
  Local<ArrayBuffer> ab =
402
      ArrayBuffer::New(env->isolate(),
403
                       data,
404
                       length,
405
20247
                       ArrayBufferCreationMode::kInternalized);
406
20247
  Local<Uint8Array> ui = Uint8Array::New(ab, 0, length);
407
  Maybe<bool> mb =
408
80988
      ui->SetPrototype(env->context(), env->buffer_prototype_object());
409
40494
  if (mb.FromMaybe(false))
410
40494
    return scope.Escape(ui);
411
  return Local<Object>();
412
}
413
414
415
1738
void CreateFromString(const FunctionCallbackInfo<Value>& args) {
416
3476
  CHECK(args[0]->IsString());
417
3476
  CHECK(args[1]->IsString());
418
419
8690
  enum encoding enc = ParseEncoding(args.GetIsolate(),
420
                                    args[1].As<String>(),
421
1738
                                    UTF8);
422
1738
  Local<Object> buf;
423
6952
  if (New(args.GetIsolate(), args[0].As<String>(), enc).ToLocal(&buf))
424
1738
    args.GetReturnValue().Set(buf);
425
1738
}
426
427
428
template <encoding encoding>
429
25652
void StringSlice(const FunctionCallbackInfo<Value>& args) {
430
25652
  Environment* env = Environment::GetCurrent(args);
431
25652
  Isolate* isolate = env->isolate();
432
433


51332
  THROW_AND_RETURN_UNLESS_BUFFER(env, args.This());
434







102608
  SPREAD_BUFFER_ARG(args.This(), ts_obj);
435
436


25652
  if (ts_obj_length == 0)
437
56
    return args.GetReturnValue().SetEmptyString();
438
439










102496
  SLICE_START_END(args[0], args[1], ts_obj_length)
440
441
76872
  args.GetReturnValue().Set(
442
      StringBytes::Encode(isolate, ts_obj_data + start, length, encoding));
443
}
444
445
446
template <>
447
2694
void StringSlice<UCS2>(const FunctionCallbackInfo<Value>& args) {
448
2694
  Environment* env = Environment::GetCurrent(args);
449
450
5388
  THROW_AND_RETURN_UNLESS_BUFFER(env, args.This());
451

10776
  SPREAD_BUFFER_ARG(args.This(), ts_obj);
452
453
2694
  if (ts_obj_length == 0)
454
    return args.GetReturnValue().SetEmptyString();
455
456


10776
  SLICE_START_END(args[0], args[1], ts_obj_length)
457
2694
  length /= 2;
458
459
2694
  const char* data = ts_obj_data + start;
460
  const uint16_t* buf;
461
2694
  bool release = false;
462
463
  // Node's "ucs2" encoding expects LE character data inside a Buffer, so we
464
  // need to reorder on BE platforms.  See http://nodejs.org/api/buffer.html
465
  // regarding Node's "ucs2" encoding specification.
466
2694
  const bool aligned = (reinterpret_cast<uintptr_t>(data) % sizeof(*buf) == 0);
467

2694
  if (IsLittleEndian() && !aligned) {
468
    // Make a copy to avoid unaligned accesses in v8::String::NewFromTwoByte().
469
    // This applies ONLY to little endian platforms, as misalignment will be
470
    // handled by a byte-swapping operation in StringBytes::Encode on
471
    // big endian platforms.
472
4
    uint16_t* copy = new uint16_t[length];
473
24
    for (size_t i = 0, k = 0; i < length; i += 1, k += 2) {
474
      // Assumes that the input is little endian.
475
20
      const uint8_t lo = static_cast<uint8_t>(data[k + 0]);
476
20
      const uint8_t hi = static_cast<uint8_t>(data[k + 1]);
477
20
      copy[i] = lo | hi << 8;
478
    }
479
    buf = copy;
480
    release = true;
481
  } else {
482
    buf = reinterpret_cast<const uint16_t*>(data);
483
  }
484
485
8082
  args.GetReturnValue().Set(StringBytes::Encode(env->isolate(), buf, length));
486
487
2694
  if (release)
488
4
    delete[] buf;
489
}
490
491
492
90
void Latin1Slice(const FunctionCallbackInfo<Value>& args) {
493
90
  StringSlice<LATIN1>(args);
494
90
}
495
496
497
4311
void AsciiSlice(const FunctionCallbackInfo<Value>& args) {
498
4311
  StringSlice<ASCII>(args);
499
4311
}
500
501
502
20494
void Utf8Slice(const FunctionCallbackInfo<Value>& args) {
503
20494
  StringSlice<UTF8>(args);
504
20494
}
505
506
507
2694
void Ucs2Slice(const FunctionCallbackInfo<Value>& args) {
508
2694
  StringSlice<UCS2>(args);
509
2694
}
510
511
512
570
void HexSlice(const FunctionCallbackInfo<Value>& args) {
513
570
  StringSlice<HEX>(args);
514
570
}
515
516
517
187
void Base64Slice(const FunctionCallbackInfo<Value>& args) {
518
187
  StringSlice<BASE64>(args);
519
187
}
520
521
522
// bytesCopied = buffer.copy(target[, targetStart][, sourceStart][, sourceEnd]);
523
268953
void Copy(const FunctionCallbackInfo<Value> &args) {
524
268953
  Environment* env = Environment::GetCurrent(args);
525
526
537925
  THROW_AND_RETURN_UNLESS_BUFFER(env, args.This());
527
537906
  THROW_AND_RETURN_UNLESS_BUFFER(env, args[0]);
528
537904
  Local<Object> target_obj = args[0].As<Object>();
529

1075808
  SPREAD_BUFFER_ARG(args.This(), ts_obj);
530

806856
  SPREAD_BUFFER_ARG(target_obj, target);
531
532
  size_t target_start;
533
  size_t source_start;
534
  size_t source_end;
535
536
268952
  THROW_AND_RETURN_IF_OOB(ParseArrayIndex(args[1], 0, &target_start));
537
268952
  THROW_AND_RETURN_IF_OOB(ParseArrayIndex(args[2], 0, &source_start));
538
268951
  THROW_AND_RETURN_IF_OOB(ParseArrayIndex(args[3], ts_obj_length, &source_end));
539
540
  // Copy 0 bytes; we're done
541

268950
  if (target_start >= target_length || source_start >= source_end)
542
30
    return args.GetReturnValue().Set(0);
543
544
268935
  if (source_start > ts_obj_length)
545
    return env->ThrowRangeError("out of range index");
546
547
268934
  if (source_end - source_start > target_length - target_start)
548
3
    source_end = source_start + target_length - target_start;
549
550
268934
  uint32_t to_copy = MIN(MIN(source_end - source_start,
551
                             target_length - target_start),
552
                             ts_obj_length - source_start);
553
554
537868
  memmove(target_data + target_start, ts_obj_data + source_start, to_copy);
555
537868
  args.GetReturnValue().Set(to_copy);
556
}
557
558
559
847
void Fill(const FunctionCallbackInfo<Value>& args) {
560
847
  Environment* env = Environment::GetCurrent(args);
561
562
2414
  THROW_AND_RETURN_UNLESS_BUFFER(env, args[0]);
563

3388
  SPREAD_BUFFER_ARG(args[0], ts_obj);
564
565
847
  size_t start = args[2]->Uint32Value();
566
847
  size_t end = args[3]->Uint32Value();
567
847
  size_t fill_length = end - start;
568
847
  Local<String> str_obj;
569
  size_t str_length;
570
  enum encoding enc;
571
847
  THROW_AND_RETURN_IF_OOB(start <= end);
572
845
  THROW_AND_RETURN_IF_OOB(fill_length + start <= ts_obj_length);
573
574
  // First check if Buffer has been passed.
575
1684
  if (Buffer::HasInstance(args[1])) {
576

24
    SPREAD_BUFFER_ARG(args[1], fill_obj);
577
6
    str_length = fill_obj_length;
578
12
    memcpy(ts_obj_data + start, fill_obj_data, MIN(str_length, fill_length));
579
    goto start_fill;
580
  }
581
582
  // Then coerce everything that's not a string.
583
1672
  if (!args[1]->IsString()) {
584
697
    int value = args[1]->Uint32Value() & 255;
585
697
    memset(ts_obj_data + start, value, fill_length);
586
    return;
587
  }
588
589
278
  str_obj = args[1]->ToString(env->isolate());
590
139
  enc = ParseEncoding(env->isolate(), args[4], UTF8);
591
  str_length =
592
48
      enc == UTF8 ? str_obj->Utf8Length() :
593

187
      enc == UCS2 ? str_obj->Length() * sizeof(uint16_t) : str_obj->Length();
594
595

139
  if (enc == HEX && str_length  % 2 != 0)
596
    return env->ThrowTypeError("Invalid hex string");
597
598
138
  if (str_length == 0)
599
    return;
600
601
  // Can't use StringBytes::Write() in all cases. For example if attempting
602
  // to write a two byte character into a one byte Buffer.
603
138
  if (enc == UTF8) {
604
96
    node::Utf8Value str(env->isolate(), args[1]);
605
96
    memcpy(ts_obj_data + start, *str, MIN(str_length, fill_length));
606
607
90
  } else if (enc == UCS2) {
608
66
    node::TwoByteValue str(env->isolate(), args[1]);
609
66
    memcpy(ts_obj_data + start, *str, MIN(str_length, fill_length));
610
611
  } else {
612
    // Write initial String to Buffer, then use that memory to copy remainder
613
    // of string. Correct the string length for cases like HEX where less than
614
    // the total string length is written.
615
114
    str_length = StringBytes::Write(env->isolate(),
616
                                    ts_obj_data + start,
617
                                    fill_length,
618
                                    str_obj,
619
                                    enc,
620
57
                                    nullptr);
621
    // This check is also needed in case Write() returns that no bytes could
622
    // be written.
623
    // TODO(trevnorris): Should this throw? Because of the string length was
624
    // greater than 0 but couldn't be written then the string was invalid.
625
57
    if (str_length == 0)
626
      return;
627
  }
628
629
 start_fill:
630
631
143
  if (str_length >= fill_length)
632
    return;
633
634
635
127
  size_t in_there = str_length;
636
127
  char* ptr = ts_obj_data + start + str_length;
637
638
541
  while (in_there < fill_length - in_there) {
639
414
    memcpy(ptr, ts_obj_data + start, in_there);
640
207
    ptr += in_there;
641
207
    in_there *= 2;
642
  }
643
644
127
  if (in_there < fill_length) {
645
127
    memcpy(ptr, ts_obj_data + start, fill_length - in_there);
646
  }
647
}
648
649
650
template <encoding encoding>
651
26481
void StringWrite(const FunctionCallbackInfo<Value>& args) {
652
26481
  Environment* env = Environment::GetCurrent(args);
653
654



52967
  THROW_AND_RETURN_UNLESS_BUFFER(env, args.This());
655









105924
  SPREAD_BUFFER_ARG(args.This(), ts_obj);
656
657



52962
  if (!args[0]->IsString())
658
    return env->ThrowTypeError("Argument must be a string");
659
660
52962
  Local<String> str = args[0]->ToString(env->isolate());
661
662
724
  if (encoding == HEX && str->Length() % 2 != 0)
663
    return env->ThrowTypeError("Invalid hex string");
664
665
  size_t offset;
666
  size_t max_length;
667
668



26480
  THROW_AND_RETURN_IF_OOB(ParseArrayIndex(args[1], 0, &offset));
669



26480
  if (offset > ts_obj_length)
670
    return env->ThrowRangeError("Offset is out of bounds");
671
672



52958
  THROW_AND_RETURN_IF_OOB(ParseArrayIndex(args[2], ts_obj_length - offset,
673
                                          &max_length));
674
675
26479
  max_length = MIN(ts_obj_length - offset, max_length);
676
677



26479
  if (max_length == 0)
678
6
    return args.GetReturnValue().Set(0);
679
680
52952
  uint32_t written = StringBytes::Write(env->isolate(),
681
                                        ts_obj_data + offset,
682
                                        max_length,
683
                                        str,
684
                                        encoding,
685
26476
                                        nullptr);
686
52952
  args.GetReturnValue().Set(written);
687
}
688
689
690
89
void Base64Write(const FunctionCallbackInfo<Value>& args) {
691
89
  StringWrite<BASE64>(args);
692
89
}
693
694
695
187
void Latin1Write(const FunctionCallbackInfo<Value>& args) {
696
187
  StringWrite<LATIN1>(args);
697
187
}
698
699
700
25322
void Utf8Write(const FunctionCallbackInfo<Value>& args) {
701
25322
  StringWrite<UTF8>(args);
702
25322
}
703
704
705
129
void Ucs2Write(const FunctionCallbackInfo<Value>& args) {
706
129
  StringWrite<UCS2>(args);
707
129
}
708
709
710
724
void HexWrite(const FunctionCallbackInfo<Value>& args) {
711
724
  StringWrite<HEX>(args);
712
724
}
713
714
715
30
void AsciiWrite(const FunctionCallbackInfo<Value>& args) {
716
30
  StringWrite<ASCII>(args);
717
30
}
718
719
720
static inline void Swizzle(char* start, unsigned int len) {
721
  char* end = start + len - 1;
722




190
  while (start < end) {
723
144
    char tmp = *start;
724
144
    *start++ = *end;
725
144
    *end-- = tmp;
726
  }
727
}
728
729
730
template <typename T, enum Endianness endianness>
731
60
void ReadFloatGeneric(const FunctionCallbackInfo<Value>& args) {
732


120
  THROW_AND_RETURN_UNLESS_BUFFER(Environment::GetCurrent(args), args[0]);
733






240
  SPREAD_BUFFER_ARG(args[0], ts_obj);
734
735
60
  uint32_t offset = args[1]->Uint32Value();
736


60
  CHECK_LE(offset + sizeof(T), ts_obj_length);
737
738
  union NoAlias {
739
    T val;
740
    char bytes[sizeof(T)];
741
  };
742
743
  union NoAlias na;
744
60
  const char* ptr = static_cast<const char*>(ts_obj_data) + offset;
745
60
  memcpy(na.bytes, ptr, sizeof(na.bytes));
746


60
  if (endianness != GetEndianness())
747
    Swizzle(na.bytes, sizeof(na.bytes));
748
749
180
  args.GetReturnValue().Set(na.val);
750
}
751
752
753
13
void ReadFloatLE(const FunctionCallbackInfo<Value>& args) {
754
13
  ReadFloatGeneric<float, kLittleEndian>(args);
755
13
}
756
757
758
11
void ReadFloatBE(const FunctionCallbackInfo<Value>& args) {
759
11
  ReadFloatGeneric<float, kBigEndian>(args);
760
11
}
761
762
763
19
void ReadDoubleLE(const FunctionCallbackInfo<Value>& args) {
764
19
  ReadFloatGeneric<double, kLittleEndian>(args);
765
19
}
766
767
768
17
void ReadDoubleBE(const FunctionCallbackInfo<Value>& args) {
769
17
  ReadFloatGeneric<double, kBigEndian>(args);
770
17
}
771
772
773
template <typename T, enum Endianness endianness>
774
45
void WriteFloatGeneric(const FunctionCallbackInfo<Value>& args) {
775
45
  Environment* env = Environment::GetCurrent(args);
776
777
45
  bool should_assert = args.Length() < 4;
778
779


45
  if (should_assert) {
780


89
    THROW_AND_RETURN_UNLESS_BUFFER(env, args[0]);
781
  }
782
783
88
  Local<Uint8Array> ts_obj = args[0].As<Uint8Array>();
784
88
  ArrayBuffer::Contents ts_obj_c = ts_obj->Buffer()->GetContents();
785
44
  const size_t ts_obj_offset = ts_obj->ByteOffset();
786
44
  const size_t ts_obj_length = ts_obj->ByteLength();
787
  char* const ts_obj_data =
788
44
      static_cast<char*>(ts_obj_c.Data()) + ts_obj_offset;
789


44
  if (ts_obj_length > 0)
790


44
    CHECK_NE(ts_obj_data, nullptr);
791
792
176
  T val = args[1]->NumberValue(env->context()).FromMaybe(0);
793
176
  size_t offset = args[2]->IntegerValue(env->context()).FromMaybe(0);
794
795
44
  size_t memcpy_num = sizeof(T);
796
797


44
  if (should_assert) {
798


40
    THROW_AND_RETURN_IF_OOB(offset + memcpy_num >= memcpy_num);
799


40
    THROW_AND_RETURN_IF_OOB(offset + memcpy_num <= ts_obj_length);
800
  }
801
802


38
  if (offset + memcpy_num > ts_obj_length)
803
4
    memcpy_num = ts_obj_length - offset;
804
805
  union NoAlias {
806
    T val;
807
    char bytes[sizeof(T)];
808
  };
809
810
38
  union NoAlias na = { val };
811
38
  char* ptr = static_cast<char*>(ts_obj_data) + offset;
812


38
  if (endianness != GetEndianness())
813
    Swizzle(na.bytes, sizeof(na.bytes));
814
38
  memcpy(ptr, na.bytes, memcpy_num);
815
}
816
817
818
15
void WriteFloatLE(const FunctionCallbackInfo<Value>& args) {
819
15
  WriteFloatGeneric<float, kLittleEndian>(args);
820
15
}
821
822
823
9
void WriteFloatBE(const FunctionCallbackInfo<Value>& args) {
824
9
  WriteFloatGeneric<float, kBigEndian>(args);
825
9
}
826
827
828
12
void WriteDoubleLE(const FunctionCallbackInfo<Value>& args) {
829
12
  WriteFloatGeneric<double, kLittleEndian>(args);
830
12
}
831
832
833
9
void WriteDoubleBE(const FunctionCallbackInfo<Value>& args) {
834
9
  WriteFloatGeneric<double, kBigEndian>(args);
835
9
}
836
837
838
29920
void ByteLengthUtf8(const FunctionCallbackInfo<Value> &args) {
839
59840
  CHECK(args[0]->IsString());
840
841
  // Fast case: avoid StringBytes on UTF8 string. Jump to v8.
842
119680
  args.GetReturnValue().Set(args[0].As<String>()->Utf8Length());
843
29920
}
844
845
// Normalize val to be an integer in the range of [1, -1] since
846
// implementations of memcmp() can vary by platform.
847
static int normalizeCompareVal(int val, size_t a_length, size_t b_length) {
848

309
  if (val == 0) {
849

293
    if (a_length > b_length)
850
      return 1;
851

287
    else if (a_length < b_length)
852
      return -1;
853
  } else {
854

16
    if (val > 0)
855
      return 1;
856
    else
857
      return -1;
858
  }
859
  return val;
860
}
861
862
16
void CompareOffset(const FunctionCallbackInfo<Value> &args) {
863
16
  Environment* env = Environment::GetCurrent(args);
864
865
32
  THROW_AND_RETURN_UNLESS_BUFFER(env, args[0]);
866
32
  THROW_AND_RETURN_UNLESS_BUFFER(env, args[1]);
867

64
  SPREAD_BUFFER_ARG(args[0], ts_obj);
868

64
  SPREAD_BUFFER_ARG(args[1], target);
869
870
  size_t target_start;
871
  size_t source_start;
872
  size_t source_end;
873
  size_t target_end;
874
875
16
  THROW_AND_RETURN_IF_OOB(ParseArrayIndex(args[2], 0, &target_start));
876
16
  THROW_AND_RETURN_IF_OOB(ParseArrayIndex(args[3], 0, &source_start));
877
16
  THROW_AND_RETURN_IF_OOB(ParseArrayIndex(args[4], target_length, &target_end));
878
16
  THROW_AND_RETURN_IF_OOB(ParseArrayIndex(args[5], ts_obj_length, &source_end));
879
880
16
  if (source_start > ts_obj_length)
881
    return env->ThrowRangeError("out of range index");
882
16
  if (target_start > target_length)
883
    return env->ThrowRangeError("out of range index");
884
885
16
  CHECK_LE(source_start, source_end);
886
16
  CHECK_LE(target_start, target_end);
887
888
16
  size_t to_cmp = MIN(MIN(source_end - source_start,
889
                      target_end - target_start),
890
                      ts_obj_length - source_start);
891
892
32
  int val = normalizeCompareVal(to_cmp > 0 ?
893
16
                                  memcmp(ts_obj_data + source_start,
894
                                         target_data + target_start,
895
                                         to_cmp) : 0,
896
                                source_end - source_start,
897
16
                                target_end - target_start);
898
899
32
  args.GetReturnValue().Set(val);
900
}
901
902
295
void Compare(const FunctionCallbackInfo<Value> &args) {
903
295
  Environment* env = Environment::GetCurrent(args);
904
905
592
  THROW_AND_RETURN_UNLESS_BUFFER(env, args[0]);
906
586
  THROW_AND_RETURN_UNLESS_BUFFER(env, args[1]);
907

1172
  SPREAD_BUFFER_ARG(args[0], obj_a);
908

1172
  SPREAD_BUFFER_ARG(args[1], obj_b);
909
910
293
  size_t cmp_length = MIN(obj_a_length, obj_b_length);
911
912
293
  int val = normalizeCompareVal(cmp_length > 0 ?
913
                                memcmp(obj_a_data, obj_b_data, cmp_length) : 0,
914
293
                                obj_a_length, obj_b_length);
915
586
  args.GetReturnValue().Set(val);
916
}
917
918
919
// Computes the offset for starting an indexOf or lastIndexOf search.
920
// Returns either a valid offset in [0...<length - 1>], ie inside the Buffer,
921
// or -1 to signal that there is no possible match.
922
int64_t IndexOfOffset(size_t length, int64_t offset_i64, bool is_forward) {
923
1109
  int64_t length_i64 = static_cast<int64_t>(length);
924


1109
  if (length_i64 == 0) {
925
    // Empty buffer, no match.
926
    return -1;
927
  }
928


1109
  if (offset_i64 < 0) {
929


77
    if (offset_i64 + length_i64 >= 0) {
930
      // Negative offsets count backwards from the end of the buffer.
931
      return length_i64 + offset_i64;
932


18
    } else if (is_forward) {
933
      // indexOf from before the start of the buffer: search the whole buffer.
934
      return 0;
935
    } else {
936
      // lastIndexOf from before the start of the buffer: no match.
937
      return -1;
938
    }
939
  } else {
940


1032
    if (offset_i64 < length_i64) {
941
      // Valid positive offset.
942
      return offset_i64;
943


25
    } else if (is_forward) {
944
      // indexOf from past the end of the buffer: no match.
945
      return -1;
946
    } else {
947
      // lastIndexOf from past the end of the buffer: search the whole buffer.
948
11
      return length_i64 - 1;
949
    }
950
  }
951
}
952
953
863
void IndexOfString(const FunctionCallbackInfo<Value>& args) {
954
1726
  ASSERT(args[1]->IsString());
955
863
  ASSERT(args[2]->IsNumber());
956
863
  ASSERT(args[4]->IsBoolean());
957
958
1726
  enum encoding enc = ParseEncoding(args.GetIsolate(),
959
                                    args[3],
960
863
                                    UTF8);
961
962
1759
  THROW_AND_RETURN_UNLESS_BUFFER(Environment::GetCurrent(args), args[0]);
963

3452
  SPREAD_BUFFER_ARG(args[0], ts_obj);
964
965
1726
  Local<String> needle = args[1].As<String>();
966
863
  int64_t offset_i64 = args[2]->IntegerValue();
967
863
  bool is_forward = args[4]->IsTrue();
968
969
863
  const char* haystack = ts_obj_data;
970
  // Round down to the nearest multiple of 2 in case of UCS2.
971
  const size_t haystack_length = (enc == UCS2) ?
972
863
      ts_obj_length &~ 1 : ts_obj_length;  // NOLINT(whitespace/operators)
973
974
  const size_t needle_length =
975
1726
      StringBytes::Size(args.GetIsolate(), needle, enc);
976
977
863
  if (needle_length == 0 || haystack_length == 0) {
978
16
    return args.GetReturnValue().Set(-1);
979
  }
980
981
1710
  int64_t opt_offset = IndexOfOffset(haystack_length, offset_i64, is_forward);
982
855
  if (opt_offset <= -1) {
983
18
    return args.GetReturnValue().Set(-1);
984
  }
985
846
  size_t offset = static_cast<size_t>(opt_offset);
986
846
  CHECK_LT(offset, haystack_length);
987

846
  if ((is_forward && needle_length + offset > haystack_length) ||
988
      needle_length > haystack_length) {
989
32
    return args.GetReturnValue().Set(-1);
990
  }
991
992
830
  size_t result = haystack_length;
993
994
830
  if (enc == UCS2) {
995
170
    String::Value needle_value(needle);
996
85
    if (*needle_value == nullptr)
997
      return args.GetReturnValue().Set(-1);
998
999

85
    if (haystack_length < 2 || needle_value.length() < 1) {
1000
      return args.GetReturnValue().Set(-1);
1001
    }
1002
1003
85
    if (IsBigEndian()) {
1004
      StringBytes::InlineDecoder decoder;
1005
      decoder.Decode(Environment::GetCurrent(args), needle, args[3], UCS2);
1006
      const uint16_t* decoded_string =
1007
          reinterpret_cast<const uint16_t*>(decoder.out());
1008
1009
      if (decoded_string == nullptr)
1010
        return args.GetReturnValue().Set(-1);
1011
1012
      result = SearchString(reinterpret_cast<const uint16_t*>(haystack),
1013
                            haystack_length / 2,
1014
                            decoded_string,
1015
                            decoder.size() / 2,
1016
                            offset / 2,
1017
                            is_forward);
1018
    } else {
1019
255
      result = SearchString(reinterpret_cast<const uint16_t*>(haystack),
1020
                            haystack_length / 2,
1021
85
                            reinterpret_cast<const uint16_t*>(*needle_value),
1022
85
                            needle_value.length(),
1023
                            offset / 2,
1024
85
                            is_forward);
1025
    }
1026
85
    result *= 2;
1027
745
  } else if (enc == UTF8) {
1028
1466
    String::Utf8Value needle_value(needle);
1029
733
    if (*needle_value == nullptr)
1030
      return args.GetReturnValue().Set(-1);
1031
1032
733
    result = SearchString(reinterpret_cast<const uint8_t*>(haystack),
1033
                          haystack_length,
1034
733
                          reinterpret_cast<const uint8_t*>(*needle_value),
1035
                          needle_length,
1036
                          offset,
1037
733
                          is_forward);
1038
12
  } else if (enc == LATIN1) {
1039
12
    uint8_t* needle_data = node::UncheckedMalloc<uint8_t>(needle_length);
1040
12
    if (needle_data == nullptr) {
1041
      return args.GetReturnValue().Set(-1);
1042
    }
1043
12
    needle->WriteOneByte(
1044
12
        needle_data, 0, needle_length, String::NO_NULL_TERMINATION);
1045
1046
12
    result = SearchString(reinterpret_cast<const uint8_t*>(haystack),
1047
                          haystack_length,
1048
                          needle_data,
1049
                          needle_length,
1050
                          offset,
1051
12
                          is_forward);
1052
12
    free(needle_data);
1053
  }
1054
1055
1660
  args.GetReturnValue().Set(
1056
830
      result == haystack_length ? -1 : static_cast<int>(result));
1057
}
1058
1059
216
void IndexOfBuffer(const FunctionCallbackInfo<Value>& args) {
1060
216
  ASSERT(args[1]->IsObject());
1061
216
  ASSERT(args[2]->IsNumber());
1062
216
  ASSERT(args[4]->IsBoolean());
1063
1064
432
  enum encoding enc = ParseEncoding(args.GetIsolate(),
1065
                                    args[3],
1066
216
                                    UTF8);
1067
1068
462
  THROW_AND_RETURN_UNLESS_BUFFER(Environment::GetCurrent(args), args[0]);
1069
432
  THROW_AND_RETURN_UNLESS_BUFFER(Environment::GetCurrent(args), args[1]);
1070

864
  SPREAD_BUFFER_ARG(args[0], ts_obj);
1071

864
  SPREAD_BUFFER_ARG(args[1], buf);
1072
216
  int64_t offset_i64 = args[2]->IntegerValue();
1073
216
  bool is_forward = args[4]->IsTrue();
1074
1075
216
  const char* haystack = ts_obj_data;
1076
216
  const size_t haystack_length = ts_obj_length;
1077
216
  const char* needle = buf_data;
1078
216
  const size_t needle_length = buf_length;
1079
1080
216
  if (needle_length == 0 || haystack_length == 0) {
1081
24
    return args.GetReturnValue().Set(-1);
1082
  }
1083
1084
408
  int64_t opt_offset = IndexOfOffset(haystack_length, offset_i64, is_forward);
1085
204
  if (opt_offset <= -1) {
1086
18
    return args.GetReturnValue().Set(-1);
1087
  }
1088
195
  size_t offset = static_cast<size_t>(opt_offset);
1089
195
  CHECK_LT(offset, haystack_length);
1090

195
  if ((is_forward && needle_length + offset > haystack_length) ||
1091
      needle_length > haystack_length) {
1092
14
    return args.GetReturnValue().Set(-1);
1093
  }
1094
1095
188
  size_t result = haystack_length;
1096
1097
188
  if (enc == UCS2) {
1098
58
    if (haystack_length < 2 || needle_length < 2) {
1099
4
      return args.GetReturnValue().Set(-1);
1100
    }
1101
56
    result = SearchString(
1102
        reinterpret_cast<const uint16_t*>(haystack),
1103
        haystack_length / 2,
1104
        reinterpret_cast<const uint16_t*>(needle),
1105
        needle_length / 2,
1106
        offset / 2,
1107
56
        is_forward);
1108
56
    result *= 2;
1109
  } else {
1110
130
    result = SearchString(
1111
        reinterpret_cast<const uint8_t*>(haystack),
1112
        haystack_length,
1113
        reinterpret_cast<const uint8_t*>(needle),
1114
        needle_length,
1115
        offset,
1116
130
        is_forward);
1117
  }
1118
1119
372
  args.GetReturnValue().Set(
1120
186
      result == haystack_length ? -1 : static_cast<int>(result));
1121
}
1122
1123
51
void IndexOfNumber(const FunctionCallbackInfo<Value>& args) {
1124
51
  ASSERT(args[1]->IsNumber());
1125
51
  ASSERT(args[2]->IsNumber());
1126
51
  ASSERT(args[3]->IsBoolean());
1127
1128
107
  THROW_AND_RETURN_UNLESS_BUFFER(Environment::GetCurrent(args), args[0]);
1129

200
  SPREAD_BUFFER_ARG(args[0], ts_obj);
1130
1131
50
  uint32_t needle = args[1]->Uint32Value();
1132
50
  int64_t offset_i64 = args[2]->IntegerValue();
1133
50
  bool is_forward = args[3]->IsTrue();
1134
1135
100
  int64_t opt_offset = IndexOfOffset(ts_obj_length, offset_i64, is_forward);
1136
50
  if (opt_offset <= -1) {
1137
8
    return args.GetReturnValue().Set(-1);
1138
  }
1139
46
  size_t offset = static_cast<size_t>(opt_offset);
1140
46
  CHECK_LT(offset, ts_obj_length);
1141
1142
  const void* ptr;
1143
46
  if (is_forward) {
1144
76
    ptr = memchr(ts_obj_data + offset, needle, ts_obj_length - offset);
1145
  } else {
1146
16
    ptr = node::stringsearch::MemrchrFill(ts_obj_data, needle, offset + 1);
1147
  }
1148
46
  const char* ptr_char = static_cast<const char*>(ptr);
1149
92
  args.GetReturnValue().Set(ptr ? static_cast<int>(ptr_char - ts_obj_data)
1150
46
                                : -1);
1151
}
1152
1153
1154
2
void Swap16(const FunctionCallbackInfo<Value>& args) {
1155
2
  Environment* env = Environment::GetCurrent(args);
1156
4
  THROW_AND_RETURN_UNLESS_BUFFER(env, args[0]);
1157

8
  SPREAD_BUFFER_ARG(args[0], ts_obj);
1158
2
  SwapBytes16(ts_obj_data, ts_obj_length);
1159
6
  args.GetReturnValue().Set(args[0]);
1160
}
1161
1162
1163
2
void Swap32(const FunctionCallbackInfo<Value>& args) {
1164
2
  Environment* env = Environment::GetCurrent(args);
1165
4
  THROW_AND_RETURN_UNLESS_BUFFER(env, args[0]);
1166

8
  SPREAD_BUFFER_ARG(args[0], ts_obj);
1167
2
  SwapBytes32(ts_obj_data, ts_obj_length);
1168
6
  args.GetReturnValue().Set(args[0]);
1169
}
1170
1171
1172
2
void Swap64(const FunctionCallbackInfo<Value>& args) {
1173
2
  Environment* env = Environment::GetCurrent(args);
1174
4
  THROW_AND_RETURN_UNLESS_BUFFER(env, args[0]);
1175

8
  SPREAD_BUFFER_ARG(args[0], ts_obj);
1176
2
  SwapBytes64(ts_obj_data, ts_obj_length);
1177
6
  args.GetReturnValue().Set(args[0]);
1178
}
1179
1180
1181
// pass Buffer object to load prototype methods
1182
1698
void SetupBufferJS(const FunctionCallbackInfo<Value>& args) {
1183
1698
  Environment* env = Environment::GetCurrent(args);
1184
1185
1698
  CHECK(args[0]->IsObject());
1186
3396
  Local<Object> proto = args[0].As<Object>();
1187
1698
  env->set_buffer_prototype_object(proto);
1188
1189
1698
  env->SetMethod(proto, "asciiSlice", AsciiSlice);
1190
1698
  env->SetMethod(proto, "base64Slice", Base64Slice);
1191
1698
  env->SetMethod(proto, "latin1Slice", Latin1Slice);
1192
1698
  env->SetMethod(proto, "hexSlice", HexSlice);
1193
1698
  env->SetMethod(proto, "ucs2Slice", Ucs2Slice);
1194
1698
  env->SetMethod(proto, "utf8Slice", Utf8Slice);
1195
1196
1698
  env->SetMethod(proto, "asciiWrite", AsciiWrite);
1197
1698
  env->SetMethod(proto, "base64Write", Base64Write);
1198
1698
  env->SetMethod(proto, "latin1Write", Latin1Write);
1199
1698
  env->SetMethod(proto, "hexWrite", HexWrite);
1200
1698
  env->SetMethod(proto, "ucs2Write", Ucs2Write);
1201
1698
  env->SetMethod(proto, "utf8Write", Utf8Write);
1202
1203
1698
  env->SetMethod(proto, "copy", Copy);
1204
1205
1698
  if (auto zero_fill_field = env->isolate_data()->zero_fill_field()) {
1206
1698
    CHECK(args[1]->IsObject());
1207
3396
    auto binding_object = args[1].As<Object>();
1208
    auto array_buffer = ArrayBuffer::New(env->isolate(),
1209
                                         zero_fill_field,
1210
1698
                                         sizeof(*zero_fill_field));
1211
1698
    auto name = FIXED_ONE_BYTE_STRING(env->isolate(), "zeroFill");
1212
1698
    auto value = Uint32Array::New(array_buffer, 0, 1);
1213
6792
    CHECK(binding_object->Set(env->context(), name, value).FromJust());
1214
  }
1215
1698
}
1216
1217
1218
1698
void Initialize(Local<Object> target,
1219
                Local<Value> unused,
1220
                Local<Context> context) {
1221
1698
  Environment* env = Environment::GetCurrent(context);
1222
1223
1698
  env->SetMethod(target, "setupBufferJS", SetupBufferJS);
1224
1698
  env->SetMethod(target, "createFromString", CreateFromString);
1225
1226
1698
  env->SetMethod(target, "byteLengthUtf8", ByteLengthUtf8);
1227
1698
  env->SetMethod(target, "compare", Compare);
1228
1698
  env->SetMethod(target, "compareOffset", CompareOffset);
1229
1698
  env->SetMethod(target, "fill", Fill);
1230
1698
  env->SetMethod(target, "indexOfBuffer", IndexOfBuffer);
1231
1698
  env->SetMethod(target, "indexOfNumber", IndexOfNumber);
1232
1698
  env->SetMethod(target, "indexOfString", IndexOfString);
1233
1234
1698
  env->SetMethod(target, "readDoubleBE", ReadDoubleBE);
1235
1698
  env->SetMethod(target, "readDoubleLE", ReadDoubleLE);
1236
1698
  env->SetMethod(target, "readFloatBE", ReadFloatBE);
1237
1698
  env->SetMethod(target, "readFloatLE", ReadFloatLE);
1238
1239
1698
  env->SetMethod(target, "writeDoubleBE", WriteDoubleBE);
1240
1698
  env->SetMethod(target, "writeDoubleLE", WriteDoubleLE);
1241
1698
  env->SetMethod(target, "writeFloatBE", WriteFloatBE);
1242
1698
  env->SetMethod(target, "writeFloatLE", WriteFloatLE);
1243
1244
1698
  env->SetMethod(target, "swap16", Swap16);
1245
1698
  env->SetMethod(target, "swap32", Swap32);
1246
1698
  env->SetMethod(target, "swap64", Swap64);
1247
1248
3396
  target->Set(env->context(),
1249
              FIXED_ONE_BYTE_STRING(env->isolate(), "kMaxLength"),
1250
10188
              Integer::NewFromUnsigned(env->isolate(), kMaxLength)).FromJust();
1251
1252
3396
  target->Set(env->context(),
1253
              FIXED_ONE_BYTE_STRING(env->isolate(), "kStringMaxLength"),
1254
10188
              Integer::New(env->isolate(), String::kMaxLength)).FromJust();
1255
1698
}
1256
1257
1258
}  // namespace Buffer
1259
}  // namespace node
1260
1261
1705
NODE_MODULE_CONTEXT_AWARE_BUILTIN(buffer, node::Buffer::Initialize)