GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: util.h Lines: 135 135 100.0 %
Date: 2022-12-31 04:22:30 Branches: 35 46 76.1 %

Line Branch Exec Source
1
// Copyright Joyent, Inc. and other Node contributors.
2
//
3
// Permission is hereby granted, free of charge, to any person obtaining a
4
// copy of this software and associated documentation files (the
5
// "Software"), to deal in the Software without restriction, including
6
// without limitation the rights to use, copy, modify, merge, publish,
7
// distribute, sublicense, and/or sell copies of the Software, and to permit
8
// persons to whom the Software is furnished to do so, subject to the
9
// following conditions:
10
//
11
// The above copyright notice and this permission notice shall be included
12
// in all copies or substantial portions of the Software.
13
//
14
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20
// USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22
#ifndef SRC_UTIL_H_
23
#define SRC_UTIL_H_
24
25
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
26
27
#include "v8.h"
28
29
#include "node.h"
30
#include "node_exit_code.h"
31
32
#include <climits>
33
#include <cstddef>
34
#include <cstdio>
35
#include <cstdlib>
36
#include <cstring>
37
38
#include <array>
39
#include <limits>
40
#include <memory>
41
#include <string>
42
#include <string_view>
43
#include <type_traits>
44
#include <set>
45
#include <unordered_map>
46
#include <utility>
47
#include <vector>
48
49
#ifdef __GNUC__
50
#define MUST_USE_RESULT __attribute__((warn_unused_result))
51
#else
52
#define MUST_USE_RESULT
53
#endif
54
55
namespace node {
56
57
// Maybe remove kPathSeparator when cpp17 is ready
58
#ifdef _WIN32
59
    constexpr char kPathSeparator = '\\';
60
/* MAX_PATH is in characters, not bytes. Make sure we have enough headroom. */
61
#define PATH_MAX_BYTES (MAX_PATH * 4)
62
#else
63
    constexpr char kPathSeparator = '/';
64
#define PATH_MAX_BYTES (PATH_MAX)
65
#endif
66
67
// These should be used in our code as opposed to the native
68
// versions as they abstract out some platform and or
69
// compiler version specific functionality
70
// malloc(0) and realloc(ptr, 0) have implementation-defined behavior in
71
// that the standard allows them to either return a unique pointer or a
72
// nullptr for zero-sized allocation requests.  Normalize by always using
73
// a nullptr.
74
template <typename T>
75
inline T* UncheckedRealloc(T* pointer, size_t n);
76
template <typename T>
77
inline T* UncheckedMalloc(size_t n);
78
template <typename T>
79
inline T* UncheckedCalloc(size_t n);
80
81
// Same things, but aborts immediately instead of returning nullptr when
82
// no memory is available.
83
template <typename T>
84
inline T* Realloc(T* pointer, size_t n);
85
template <typename T>
86
inline T* Malloc(size_t n);
87
template <typename T>
88
inline T* Calloc(size_t n);
89
90
inline char* Malloc(size_t n);
91
inline char* Calloc(size_t n);
92
inline char* UncheckedMalloc(size_t n);
93
inline char* UncheckedCalloc(size_t n);
94
95
template <typename T>
96
inline T MultiplyWithOverflowCheck(T a, T b);
97
98
namespace per_process {
99
// Tells whether the per-process V8::Initialize() is called and
100
// if it is safe to call v8::Isolate::TryGetCurrent().
101
extern bool v8_initialized;
102
}  // namespace per_process
103
104
// Used by the allocation functions when allocation fails.
105
// Thin wrapper around v8::Isolate::LowMemoryNotification() that checks
106
// whether V8 is initialized.
107
void LowMemoryNotification();
108
109
// The reason that Assert() takes a struct argument instead of individual
110
// const char*s is to ease instruction cache pressure in calls from CHECK.
111
struct AssertionInfo {
112
  const char* file_line;  // filename:line
113
  const char* message;
114
  const char* function;
115
};
116
[[noreturn]] void NODE_EXTERN_PRIVATE Assert(const AssertionInfo& info);
117
[[noreturn]] void NODE_EXTERN_PRIVATE Abort();
118
void DumpBacktrace(FILE* fp);
119
120
// Windows 8+ does not like abort() in Release mode
121
#ifdef _WIN32
122
#define ABORT_NO_BACKTRACE() _exit(static_cast<int>(node::ExitCode::kAbort))
123
#else
124
#define ABORT_NO_BACKTRACE() abort()
125
#endif
126
127
#define ABORT() node::Abort()
128
129
#define ERROR_AND_ABORT(expr)                                                 \
130
  do {                                                                        \
131
    /* Make sure that this struct does not end up in inline code, but      */ \
132
    /* rather in a read-only data section when modifying this code.        */ \
133
    static const node::AssertionInfo args = {                                 \
134
      __FILE__ ":" STRINGIFY(__LINE__), #expr, PRETTY_FUNCTION_NAME           \
135
    };                                                                        \
136
    node::Assert(args);                                                       \
137
  } while (0)
138
139
#ifdef __GNUC__
140
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
141
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
142
#define PRETTY_FUNCTION_NAME __PRETTY_FUNCTION__
143
#else
144
#define LIKELY(expr) expr
145
#define UNLIKELY(expr) expr
146
#define PRETTY_FUNCTION_NAME ""
147
#endif
148
149
#define STRINGIFY_(x) #x
150
#define STRINGIFY(x) STRINGIFY_(x)
151
152
#define CHECK(expr)                                                           \
153
  do {                                                                        \
154
    if (UNLIKELY(!(expr))) {                                                  \
155
      ERROR_AND_ABORT(expr);                                                  \
156
    }                                                                         \
157
  } while (0)
158
159
#define CHECK_EQ(a, b) CHECK((a) == (b))
160
#define CHECK_GE(a, b) CHECK((a) >= (b))
161
#define CHECK_GT(a, b) CHECK((a) > (b))
162
#define CHECK_LE(a, b) CHECK((a) <= (b))
163
#define CHECK_LT(a, b) CHECK((a) < (b))
164
#define CHECK_NE(a, b) CHECK((a) != (b))
165
#define CHECK_NULL(val) CHECK((val) == nullptr)
166
#define CHECK_NOT_NULL(val) CHECK((val) != nullptr)
167
#define CHECK_IMPLIES(a, b) CHECK(!(a) || (b))
168
169
#ifdef DEBUG
170
  #define DCHECK(expr) CHECK(expr)
171
  #define DCHECK_EQ(a, b) CHECK((a) == (b))
172
  #define DCHECK_GE(a, b) CHECK((a) >= (b))
173
  #define DCHECK_GT(a, b) CHECK((a) > (b))
174
  #define DCHECK_LE(a, b) CHECK((a) <= (b))
175
  #define DCHECK_LT(a, b) CHECK((a) < (b))
176
  #define DCHECK_NE(a, b) CHECK((a) != (b))
177
  #define DCHECK_NULL(val) CHECK((val) == nullptr)
178
  #define DCHECK_NOT_NULL(val) CHECK((val) != nullptr)
179
  #define DCHECK_IMPLIES(a, b) CHECK(!(a) || (b))
180
#else
181
  #define DCHECK(expr)
182
  #define DCHECK_EQ(a, b)
183
  #define DCHECK_GE(a, b)
184
  #define DCHECK_GT(a, b)
185
  #define DCHECK_LE(a, b)
186
  #define DCHECK_LT(a, b)
187
  #define DCHECK_NE(a, b)
188
  #define DCHECK_NULL(val)
189
  #define DCHECK_NOT_NULL(val)
190
  #define DCHECK_IMPLIES(a, b)
191
#endif
192
193
194
#define UNREACHABLE(...)                                                      \
195
  ERROR_AND_ABORT("Unreachable code reached" __VA_OPT__(": ") __VA_ARGS__)
196
197
// ECMA262 20.1.2.6 Number.MAX_SAFE_INTEGER (2^53-1)
198
constexpr int64_t kMaxSafeJsInteger = 9007199254740991;
199
200
inline bool IsSafeJsInt(v8::Local<v8::Value> v);
201
202
// TAILQ-style intrusive list node.
203
template <typename T>
204
class ListNode;
205
206
// TAILQ-style intrusive list head.
207
template <typename T, ListNode<T> (T::*M)>
208
class ListHead;
209
210
template <typename T>
211
class ListNode {
212
 public:
213
  inline ListNode();
214
  inline ~ListNode();
215
  inline void Remove();
216
  inline bool IsEmpty() const;
217
218
  ListNode(const ListNode&) = delete;
219
  ListNode& operator=(const ListNode&) = delete;
220
221
 private:
222
  template <typename U, ListNode<U> (U::*M)> friend class ListHead;
223
  friend int GenDebugSymbols();
224
  ListNode* prev_;
225
  ListNode* next_;
226
};
227
228
template <typename T, ListNode<T> (T::*M)>
229
class ListHead {
230
 public:
231
  class Iterator {
232
   public:
233
    inline T* operator*() const;
234
    inline const Iterator& operator++();
235
    inline bool operator!=(const Iterator& that) const;
236
237
   private:
238
    friend class ListHead;
239
    inline explicit Iterator(ListNode<T>* node);
240
    ListNode<T>* node_;
241
  };
242
243
26141
  inline ListHead() = default;
244
  inline ~ListHead();
245
  inline void PushBack(T* element);
246
  inline void PushFront(T* element);
247
  inline bool IsEmpty() const;
248
  inline T* PopFront();
249
  inline Iterator begin() const;
250
  inline Iterator end() const;
251
252
  ListHead(const ListHead&) = delete;
253
  ListHead& operator=(const ListHead&) = delete;
254
255
 private:
256
  friend int GenDebugSymbols();
257
  ListNode<T> head_;
258
};
259
260
// The helper is for doing safe downcasts from base types to derived types.
261
template <typename Inner, typename Outer>
262
class ContainerOfHelper {
263
 public:
264
  inline ContainerOfHelper(Inner Outer::*field, Inner* pointer);
265
  template <typename TypeName>
266
  inline operator TypeName*() const;
267
 private:
268
  Outer* const pointer_;
269
};
270
271
// Calculate the address of the outer (i.e. embedding) struct from
272
// the interior pointer to a data member.
273
template <typename Inner, typename Outer>
274
constexpr ContainerOfHelper<Inner, Outer> ContainerOf(Inner Outer::*field,
275
                                                      Inner* pointer);
276
277
class KVStore {
278
 public:
279
6774
  KVStore() = default;
280
12322
  virtual ~KVStore() = default;
281
  KVStore(const KVStore&) = delete;
282
  KVStore& operator=(const KVStore&) = delete;
283
  KVStore(KVStore&&) = delete;
284
  KVStore& operator=(KVStore&&) = delete;
285
286
  virtual v8::MaybeLocal<v8::String> Get(v8::Isolate* isolate,
287
                                         v8::Local<v8::String> key) const = 0;
288
  virtual v8::Maybe<std::string> Get(const char* key) const = 0;
289
  virtual void Set(v8::Isolate* isolate,
290
                   v8::Local<v8::String> key,
291
                   v8::Local<v8::String> value) = 0;
292
  virtual int32_t Query(v8::Isolate* isolate,
293
                        v8::Local<v8::String> key) const = 0;
294
  virtual int32_t Query(const char* key) const = 0;
295
  virtual void Delete(v8::Isolate* isolate, v8::Local<v8::String> key) = 0;
296
  virtual v8::Local<v8::Array> Enumerate(v8::Isolate* isolate) const = 0;
297
298
  virtual std::shared_ptr<KVStore> Clone(v8::Isolate* isolate) const;
299
  virtual v8::Maybe<bool> AssignFromObject(v8::Local<v8::Context> context,
300
                                           v8::Local<v8::Object> entries);
301
  v8::Maybe<bool> AssignToObject(v8::Isolate* isolate,
302
                                 v8::Local<v8::Context> context,
303
                                 v8::Local<v8::Object> object);
304
305
  static std::shared_ptr<KVStore> CreateMapKVStore();
306
};
307
308
// Convenience wrapper around v8::String::NewFromOneByte().
309
inline v8::Local<v8::String> OneByteString(v8::Isolate* isolate,
310
                                           const char* data,
311
                                           int length = -1);
312
313
// For the people that compile with -funsigned-char.
314
inline v8::Local<v8::String> OneByteString(v8::Isolate* isolate,
315
                                           const signed char* data,
316
                                           int length = -1);
317
318
inline v8::Local<v8::String> OneByteString(v8::Isolate* isolate,
319
                                           const unsigned char* data,
320
                                           int length = -1);
321
322
// Used to be a macro, hence the uppercase name.
323
template <int N>
324
8824372
inline v8::Local<v8::String> FIXED_ONE_BYTE_STRING(
325
    v8::Isolate* isolate,
326
    const char(&data)[N]) {
327
8824372
  return OneByteString(isolate, data, N - 1);
328
}
329
330
template <std::size_t N>
331
720
inline v8::Local<v8::String> FIXED_ONE_BYTE_STRING(
332
    v8::Isolate* isolate,
333
    const std::array<char, N>& arr) {
334
720
  return OneByteString(isolate, arr.data(), N - 1);
335
}
336
337
338
339
// Swaps bytes in place. nbytes is the number of bytes to swap and must be a
340
// multiple of the word size (checked by function).
341
inline void SwapBytes16(char* data, size_t nbytes);
342
inline void SwapBytes32(char* data, size_t nbytes);
343
inline void SwapBytes64(char* data, size_t nbytes);
344
345
// tolower() is locale-sensitive.  Use ToLower() instead.
346
inline char ToLower(char c);
347
inline std::string ToLower(const std::string& in);
348
349
// toupper() is locale-sensitive.  Use ToUpper() instead.
350
inline char ToUpper(char c);
351
inline std::string ToUpper(const std::string& in);
352
353
// strcasecmp() is locale-sensitive.  Use StringEqualNoCase() instead.
354
inline bool StringEqualNoCase(const char* a, const char* b);
355
356
// strncasecmp() is locale-sensitive.  Use StringEqualNoCaseN() instead.
357
inline bool StringEqualNoCaseN(const char* a, const char* b, size_t length);
358
359
template <typename T, size_t N>
360
12075257
constexpr size_t arraysize(const T (&)[N]) {
361
12075257
  return N;
362
}
363
364
template <typename T, size_t N>
365
constexpr size_t strsize(const T (&)[N]) {
366
  return N - 1;
367
}
368
369
// Allocates an array of member type T. For up to kStackStorageSize items,
370
// the stack is used, otherwise malloc().
371
template <typename T, size_t kStackStorageSize = 1024>
372
class MaybeStackBuffer {
373
 public:
374
6097
  const T* out() const {
375
6097
    return buf_;
376
  }
377
378
6519259
  T* out() {
379
6519259
    return buf_;
380
  }
381
382
  // operator* for compatibility with `v8::String::(Utf8)Value`
383
9825045
  T* operator*() {
384
9825045
    return buf_;
385
  }
386
387
30498
  const T* operator*() const {
388
30498
    return buf_;
389
  }
390
391
2707442
  T& operator[](size_t index) {
392
2707442
    CHECK_LT(index, length());
393
2707442
    return buf_[index];
394
  }
395
396
11208
  const T& operator[](size_t index) const {
397
11208
    CHECK_LT(index, length());
398
11208
    return buf_[index];
399
  }
400
401
10623530
  size_t length() const {
402
10623530
    return length_;
403
  }
404
405
  // Current maximum capacity of the buffer with which SetLength() can be used
406
  // without first calling AllocateSufficientStorage().
407
19597098
  size_t capacity() const {
408
19597098
    return capacity_;
409
  }
410
411
  // Make sure enough space for `storage` entries is available.
412
  // This method can be called multiple times throughout the lifetime of the
413
  // buffer, but once this has been called Invalidate() cannot be used.
414
  // Content of the buffer in the range [0, length()) is preserved.
415
6870971
  void AllocateSufficientStorage(size_t storage) {
416
6870971
    CHECK(!IsInvalidated());
417
6870971
    if (storage > capacity()) {
418
301592
      bool was_allocated = IsAllocated();
419
301592
      T* allocated_ptr = was_allocated ? buf_ : nullptr;
420
301592
      buf_ = Realloc(allocated_ptr, storage);
421
301592
      capacity_ = storage;
422

301592
      if (!was_allocated && length_ > 0)
423
4
        memcpy(buf_, buf_st_, length_ * sizeof(buf_[0]));
424
    }
425
426
6870971
    length_ = storage;
427
6870971
  }
428
429
6373022
  void SetLength(size_t length) {
430
    // capacity() returns how much memory is actually available.
431
6373022
    CHECK_LE(length, capacity());
432
6373022
    length_ = length;
433
6373022
  }
434
435
9564263
  void SetLengthAndZeroTerminate(size_t length) {
436
    // capacity() returns how much memory is actually available.
437
9564263
    CHECK_LE(length + 1, capacity());
438
9564263
    SetLength(length);
439
440
    // T() is 0 for integer types, nullptr for pointers, etc.
441
9564263
    buf_[length] = T();
442
9564263
  }
443
444
  // Make dereferencing this object return nullptr.
445
  // This method can be called multiple times throughout the lifetime of the
446
  // buffer, but once this has been called AllocateSufficientStorage() cannot
447
  // be used.
448
2
  void Invalidate() {
449
2
    CHECK(!IsAllocated());
450
2
    capacity_ = 0;
451
2
    length_ = 0;
452
2
    buf_ = nullptr;
453
2
  }
454
455
  // If the buffer is stored in the heap rather than on the stack.
456
9323288
  bool IsAllocated() const {
457

9323288
    return !IsInvalidated() && buf_ != buf_st_;
458
  }
459
460
  // If Invalidate() has been called.
461
16586958
  bool IsInvalidated() const {
462
16586958
    return buf_ == nullptr;
463
  }
464
465
  // Release ownership of the malloc'd buffer.
466
  // Note: This does not free the buffer.
467
8
  void Release() {
468
8
    CHECK(IsAllocated());
469
8
    buf_ = buf_st_;
470
8
    length_ = 0;
471
8
    capacity_ = arraysize(buf_st_);
472
8
  }
473
474
8563253
  MaybeStackBuffer()
475
134628189
      : length_(0), capacity_(arraysize(buf_st_)), buf_(buf_st_) {
476
    // Default to a zero-length, null-terminated buffer.
477
8563253
    buf_[0] = T();
478
8563253
  }
479
480
435667
  explicit MaybeStackBuffer(size_t storage) : MaybeStackBuffer() {
481
435667
    AllocateSufficientStorage(storage);
482
435667
  }
483
484
9020762
  ~MaybeStackBuffer() {
485
9020762
    if (IsAllocated())
486
302445
      free(buf_);
487
9020762
  }
488
489
 private:
490
  size_t length_;
491
  // capacity of the malloc'ed buf_
492
  size_t capacity_;
493
  T* buf_;
494
  T buf_st_[kStackStorageSize];
495
};
496
497
// Provides access to an ArrayBufferView's storage, either the original,
498
// or for small data, a copy of it. This object's lifetime is bound to the
499
// original ArrayBufferView's lifetime.
500
template <typename T, size_t kStackStorageSize = 64>
501
class ArrayBufferViewContents {
502
 public:
503
1252
  ArrayBufferViewContents() = default;
504
505
  ArrayBufferViewContents(const ArrayBufferViewContents&) = delete;
506
  void operator=(const ArrayBufferViewContents&) = delete;
507
508
  explicit inline ArrayBufferViewContents(v8::Local<v8::Value> value);
509
  explicit inline ArrayBufferViewContents(v8::Local<v8::Object> value);
510
  explicit inline ArrayBufferViewContents(v8::Local<v8::ArrayBufferView> abv);
511
  inline void Read(v8::Local<v8::ArrayBufferView> abv);
512
  inline void ReadValue(v8::Local<v8::Value> buf);
513
514
37
  inline bool WasDetached() const { return was_detached_; }
515
178342
  inline const T* data() const { return data_; }
516
450423
  inline size_t length() const { return length_; }
517
518
 private:
519
  // Declaring operator new and delete as deleted is not spec compliant.
520
  // Therefore, declare them private instead to disable dynamic alloc.
521
  void* operator new(size_t size);
522
  void* operator new[](size_t size);
523
  void operator delete(void*, size_t);
524
  void operator delete[](void*, size_t);
525
526
  T stack_storage_[kStackStorageSize];
527
  T* data_ = nullptr;
528
  size_t length_ = 0;
529
  bool was_detached_ = false;
530
};
531
532
class Utf8Value : public MaybeStackBuffer<char> {
533
 public:
534
  explicit Utf8Value(v8::Isolate* isolate, v8::Local<v8::Value> value);
535
536
1136
  inline std::string ToString() const { return std::string(out(), length()); }
537
538
4961
  inline bool operator==(const char* a) const {
539
4961
    return strcmp(out(), a) == 0;
540
  }
541
};
542
543
class TwoByteValue : public MaybeStackBuffer<uint16_t> {
544
 public:
545
  explicit TwoByteValue(v8::Isolate* isolate, v8::Local<v8::Value> value);
546
};
547
548
class BufferValue : public MaybeStackBuffer<char> {
549
 public:
550
  explicit BufferValue(v8::Isolate* isolate, v8::Local<v8::Value> value);
551
552
  inline std::string ToString() const { return std::string(out(), length()); }
553
};
554
555
#define SPREAD_BUFFER_ARG(val, name)                                           \
556
  CHECK((val)->IsArrayBufferView());                                           \
557
  v8::Local<v8::ArrayBufferView> name = (val).As<v8::ArrayBufferView>();       \
558
  const size_t name##_offset = name->ByteOffset();                             \
559
  const size_t name##_length = name->ByteLength();                             \
560
  char* const name##_data =                                                    \
561
      static_cast<char*>(name->Buffer()->Data()) + name##_offset;              \
562
  if (name##_length > 0) CHECK_NE(name##_data, nullptr);
563
564
// Use this when a variable or parameter is unused in order to explicitly
565
// silence a compiler warning about that.
566
5300478
template <typename T> inline void USE(T&&) {}
567
568
template <typename Fn>
569
struct OnScopeLeaveImpl {
570
  Fn fn_;
571
  bool active_;
572
573
3574132
  explicit OnScopeLeaveImpl(Fn&& fn) : fn_(std::move(fn)), active_(true) {}
574
1803107
  ~OnScopeLeaveImpl() { if (active_) fn_(); }
575
576
  OnScopeLeaveImpl(const OnScopeLeaveImpl& other) = delete;
577
  OnScopeLeaveImpl& operator=(const OnScopeLeaveImpl& other) = delete;
578
  OnScopeLeaveImpl(OnScopeLeaveImpl&& other)
579
    : fn_(std::move(other.fn_)), active_(other.active_) {
580
    other.active_ = false;
581
  }
582
  OnScopeLeaveImpl& operator=(OnScopeLeaveImpl&& other) {
583
    if (this == &other) return *this;
584
    this->~OnScopeLeave();
585
    new (this)OnScopeLeaveImpl(std::move(other));
586
    return *this;
587
  }
588
};
589
590
// Run a function when exiting the current scope. Used like this:
591
// auto on_scope_leave = OnScopeLeave([&] {
592
//   // ... run some code ...
593
// });
594
template <typename Fn>
595
3574132
inline MUST_USE_RESULT OnScopeLeaveImpl<Fn> OnScopeLeave(Fn&& fn) {
596
3574132
  return OnScopeLeaveImpl<Fn>{std::move(fn)};
597
}
598
599
// Simple RAII wrapper for contiguous data that uses malloc()/free().
600
template <typename T>
601
struct MallocedBuffer {
602
  T* data;
603
  size_t size;
604
605
  T* release() {
606
    T* ret = data;
607
    data = nullptr;
608
    return ret;
609
  }
610
611
  void Truncate(size_t new_size) {
612
    CHECK(new_size <= size);
613
    size = new_size;
614
  }
615
616
  void Realloc(size_t new_size) {
617
    Truncate(new_size);
618
    data = UncheckedRealloc(data, new_size);
619
  }
620
621
79913
  inline bool is_empty() const { return data == nullptr; }
622
623
116359
  MallocedBuffer() : data(nullptr), size(0) {}
624
890
  explicit MallocedBuffer(size_t size) : data(Malloc<T>(size)), size(size) {}
625
79940
  MallocedBuffer(T* data, size_t size) : data(data), size(size) {}
626
196259
  MallocedBuffer(MallocedBuffer&& other) : data(other.data), size(other.size) {
627
196259
    other.data = nullptr;
628
196259
  }
629
79964
  MallocedBuffer& operator=(MallocedBuffer&& other) {
630
79964
    this->~MallocedBuffer();
631
79964
    return *new(this) MallocedBuffer(std::move(other));
632
  }
633
393421
  ~MallocedBuffer() {
634
393421
    free(data);
635
393421
  }
636
  MallocedBuffer(const MallocedBuffer&) = delete;
637
  MallocedBuffer& operator=(const MallocedBuffer&) = delete;
638
};
639
640
template <typename T>
641
class NonCopyableMaybe {
642
 public:
643
5087
  NonCopyableMaybe() : empty_(true) {}
644
4395
  explicit NonCopyableMaybe(T&& value)
645
      : empty_(false),
646
8790
        value_(std::move(value)) {}
647
648
8728
  bool IsEmpty() const {
649
8728
    return empty_;
650
  }
651
652
1541
  const T* get() const {
653
1541
    return empty_ ? nullptr : &value_;
654
  }
655
656
26
  const T* operator->() const {
657
26
    CHECK(!empty_);
658
26
    return &value_;
659
  }
660
661
4298
  T&& Release() {
662
4298
    CHECK_EQ(empty_, false);
663
4298
    empty_ = true;
664
4298
    return std::move(value_);
665
  }
666
667
 private:
668
  bool empty_;
669
  T value_;
670
};
671
672
// Test whether some value can be called with ().
673
template <typename T, typename = void>
674
struct is_callable : std::is_function<T> { };
675
676
template <typename T>
677
struct is_callable<T, typename std::enable_if<
678
    std::is_same<decltype(void(&T::operator())), void>::value
679
    >::type> : std::true_type { };
680
681
template <typename T, void (*function)(T*)>
682
struct FunctionDeleter {
683
201335
  void operator()(T* pointer) const { function(pointer); }
684
  typedef std::unique_ptr<T, FunctionDeleter> Pointer;
685
};
686
687
template <typename T, void (*function)(T*)>
688
using DeleteFnPtr = typename FunctionDeleter<T, function>::Pointer;
689
690
std::vector<std::string> SplitString(const std::string& in,
691
                                     char delim,
692
                                     bool skipEmpty = true);
693
694
inline v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context,
695
                                           std::string_view str,
696
                                           v8::Isolate* isolate = nullptr);
697
template <typename T, typename test_for_number =
698
    typename std::enable_if<std::numeric_limits<T>::is_specialized, bool>::type>
699
inline v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context,
700
                                           const T& number,
701
                                           v8::Isolate* isolate = nullptr);
702
template <typename T>
703
inline v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context,
704
                                           const std::vector<T>& vec,
705
                                           v8::Isolate* isolate = nullptr);
706
template <typename T>
707
inline v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context,
708
                                           const std::set<T>& set,
709
                                           v8::Isolate* isolate = nullptr);
710
template <typename T, typename U>
711
inline v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context,
712
                                           const std::unordered_map<T, U>& map,
713
                                           v8::Isolate* isolate = nullptr);
714
715
// These macros expects a `Isolate* isolate` and a `Local<Context> context`
716
// to be in the scope.
717
#define READONLY_PROPERTY(obj, name, value)                                    \
718
  do {                                                                         \
719
    obj->DefineOwnProperty(                                                    \
720
           context, FIXED_ONE_BYTE_STRING(isolate, name), value, v8::ReadOnly) \
721
        .Check();                                                              \
722
  } while (0)
723
724
#define READONLY_DONT_ENUM_PROPERTY(obj, name, var)                            \
725
  do {                                                                         \
726
    obj->DefineOwnProperty(                                                    \
727
           context,                                                            \
728
           OneByteString(isolate, name),                                       \
729
           var,                                                                \
730
           static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum))    \
731
        .Check();                                                              \
732
  } while (0)
733
734
#define READONLY_FALSE_PROPERTY(obj, name)                                     \
735
  READONLY_PROPERTY(obj, name, v8::False(isolate))
736
737
#define READONLY_TRUE_PROPERTY(obj, name)                                      \
738
  READONLY_PROPERTY(obj, name, v8::True(isolate))
739
740
#define READONLY_STRING_PROPERTY(obj, name, str)                               \
741
  READONLY_PROPERTY(obj, name, ToV8Value(context, str).ToLocalChecked())
742
743
// Variation on NODE_DEFINE_CONSTANT that sets a String value.
744
#define NODE_DEFINE_STRING_CONSTANT(target, name, constant)                    \
745
  do {                                                                         \
746
    v8::Isolate* isolate = target->GetIsolate();                               \
747
    v8::Local<v8::String> constant_name =                                      \
748
        v8::String::NewFromUtf8(isolate, name).ToLocalChecked();               \
749
    v8::Local<v8::String> constant_value =                                     \
750
        v8::String::NewFromUtf8(isolate, constant).ToLocalChecked();           \
751
    v8::PropertyAttribute constant_attributes =                                \
752
        static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete);     \
753
    target                                                                     \
754
        ->DefineOwnProperty(isolate->GetCurrentContext(),                      \
755
                            constant_name,                                     \
756
                            constant_value,                                    \
757
                            constant_attributes)                               \
758
        .Check();                                                              \
759
  } while (0)
760
761
enum class Endianness { LITTLE, BIG };
762
763
6259
inline Endianness GetEndianness() {
764
  // Constant-folded by the compiler.
765
  const union {
766
    uint8_t u8[2];
767
    uint16_t u16;
768
6259
  } u = {{1, 0}};
769
6259
  return u.u16 == 1 ? Endianness::LITTLE : Endianness::BIG;
770
}
771
772
1
inline bool IsLittleEndian() {
773
1
  return GetEndianness() == Endianness::LITTLE;
774
}
775
776
6258
inline bool IsBigEndian() {
777
6258
  return GetEndianness() == Endianness::BIG;
778
}
779
780
// Round up a to the next highest multiple of b.
781
template <typename T>
782
190406
constexpr T RoundUp(T a, T b) {
783
190406
  return a % b != 0 ? a + b - (a % b) : a;
784
}
785
786
// Align ptr to an `alignment`-bytes boundary.
787
template <typename T, typename U>
788
24104
constexpr T* AlignUp(T* ptr, U alignment) {
789
  return reinterpret_cast<T*>(
790
24104
      RoundUp(reinterpret_cast<uintptr_t>(ptr), alignment));
791
}
792
793
class SlicedArguments : public MaybeStackBuffer<v8::Local<v8::Value>> {
794
 public:
795
  inline explicit SlicedArguments(
796
      const v8::FunctionCallbackInfo<v8::Value>& args, size_t start = 0);
797
};
798
799
// Convert a v8::PersistentBase, e.g. v8::Global, to a Local, with an extra
800
// optimization for strong persistent handles.
801
class PersistentToLocal {
802
 public:
803
  // If persistent.IsWeak() == false, then do not call persistent.Reset()
804
  // while the returned Local<T> is still in scope, it will destroy the
805
  // reference to the object.
806
  template <class TypeName>
807
6916834
  static inline v8::Local<TypeName> Default(
808
      v8::Isolate* isolate,
809
      const v8::PersistentBase<TypeName>& persistent) {
810
6916834
    if (persistent.IsWeak()) {
811
4506836
      return PersistentToLocal::Weak(isolate, persistent);
812
    } else {
813
2409998
      return PersistentToLocal::Strong(persistent);
814
    }
815
  }
816
817
  // Unchecked conversion from a non-weak Persistent<T> to Local<T>,
818
  // use with care!
819
  //
820
  // Do not call persistent.Reset() while the returned Local<T> is still in
821
  // scope, it will destroy the reference to the object.
822
  template <class TypeName>
823
37334841
  static inline v8::Local<TypeName> Strong(
824
      const v8::PersistentBase<TypeName>& persistent) {
825
    DCHECK(!persistent.IsWeak());
826
    return *reinterpret_cast<v8::Local<TypeName>*>(
827
37334841
        const_cast<v8::PersistentBase<TypeName>*>(&persistent));
828
  }
829
830
  template <class TypeName>
831
2368997
  static inline v8::Local<TypeName> Weak(
832
      v8::Isolate* isolate,
833
      const v8::PersistentBase<TypeName>& persistent) {
834
2368997
    return v8::Local<TypeName>::New(isolate, persistent);
835
  }
836
};
837
838
// Can be used as a key for std::unordered_map when lookup performance is more
839
// important than size and the keys are statically used to avoid redundant hash
840
// computations.
841
class FastStringKey {
842
 public:
843
  constexpr explicit FastStringKey(std::string_view name);
844
845
  struct Hash {
846
    constexpr size_t operator()(const FastStringKey& key) const;
847
  };
848
  constexpr bool operator==(const FastStringKey& other) const;
849
850
  constexpr std::string_view as_string_view() const;
851
852
 private:
853
  static constexpr size_t HashImpl(std::string_view str);
854
855
  const std::string_view name_;
856
  const size_t cached_hash_;
857
};
858
859
// Like std::static_pointer_cast but for unique_ptr with the default deleter.
860
template <typename T, typename U>
861
10785
std::unique_ptr<T> static_unique_pointer_cast(std::unique_ptr<U>&& ptr) {
862
10785
  return std::unique_ptr<T>(static_cast<T*>(ptr.release()));
863
}
864
865
#define MAYBE_FIELD_PTR(ptr, field) ptr == nullptr ? nullptr : &(ptr->field)
866
867
// Returns a non-zero code if it fails to open or read the file,
868
// aborts if it fails to close the file.
869
int ReadFileSync(std::string* result, const char* path);
870
871
v8::Local<v8::FunctionTemplate> NewFunctionTemplate(
872
    v8::Isolate* isolate,
873
    v8::FunctionCallback callback,
874
    v8::Local<v8::Signature> signature = v8::Local<v8::Signature>(),
875
    v8::ConstructorBehavior behavior = v8::ConstructorBehavior::kAllow,
876
    v8::SideEffectType side_effect = v8::SideEffectType::kHasSideEffect,
877
    const v8::CFunction* c_function = nullptr);
878
879
// Convenience methods for NewFunctionTemplate().
880
void SetMethod(v8::Local<v8::Context> context,
881
               v8::Local<v8::Object> that,
882
               const char* name,
883
               v8::FunctionCallback callback);
884
// Similar to SetProtoMethod but without receiver signature checks.
885
void SetMethod(v8::Isolate* isolate,
886
               v8::Local<v8::Template> that,
887
               const char* name,
888
               v8::FunctionCallback callback);
889
890
void SetFastMethod(v8::Local<v8::Context> context,
891
                   v8::Local<v8::Object> that,
892
                   const char* name,
893
                   v8::FunctionCallback slow_callback,
894
                   const v8::CFunction* c_function);
895
896
void SetProtoMethod(v8::Isolate* isolate,
897
                    v8::Local<v8::FunctionTemplate> that,
898
                    const char* name,
899
                    v8::FunctionCallback callback);
900
901
void SetInstanceMethod(v8::Isolate* isolate,
902
                       v8::Local<v8::FunctionTemplate> that,
903
                       const char* name,
904
                       v8::FunctionCallback callback);
905
906
// Safe variants denote the function has no side effects.
907
void SetMethodNoSideEffect(v8::Local<v8::Context> context,
908
                           v8::Local<v8::Object> that,
909
                           const char* name,
910
                           v8::FunctionCallback callback);
911
void SetProtoMethodNoSideEffect(v8::Isolate* isolate,
912
                                v8::Local<v8::FunctionTemplate> that,
913
                                const char* name,
914
                                v8::FunctionCallback callback);
915
916
enum class SetConstructorFunctionFlag {
917
  NONE,
918
  SET_CLASS_NAME,
919
};
920
921
void SetConstructorFunction(v8::Local<v8::Context> context,
922
                            v8::Local<v8::Object> that,
923
                            const char* name,
924
                            v8::Local<v8::FunctionTemplate> tmpl,
925
                            SetConstructorFunctionFlag flag =
926
                                SetConstructorFunctionFlag::SET_CLASS_NAME);
927
928
void SetConstructorFunction(v8::Local<v8::Context> context,
929
                            v8::Local<v8::Object> that,
930
                            v8::Local<v8::String> name,
931
                            v8::Local<v8::FunctionTemplate> tmpl,
932
                            SetConstructorFunctionFlag flag =
933
                                SetConstructorFunctionFlag::SET_CLASS_NAME);
934
935
void SetConstructorFunction(v8::Isolate* isolate,
936
                            v8::Local<v8::Template> that,
937
                            const char* name,
938
                            v8::Local<v8::FunctionTemplate> tmpl,
939
                            SetConstructorFunctionFlag flag =
940
                                SetConstructorFunctionFlag::SET_CLASS_NAME);
941
942
void SetConstructorFunction(v8::Isolate* isolate,
943
                            v8::Local<v8::Template> that,
944
                            v8::Local<v8::String> name,
945
                            v8::Local<v8::FunctionTemplate> tmpl,
946
                            SetConstructorFunctionFlag flag =
947
                                SetConstructorFunctionFlag::SET_CLASS_NAME);
948
949
}  // namespace node
950
951
#endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
952
953
#endif  // SRC_UTIL_H_