GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: util.h Lines: 132 132 100.0 %
Date: 2022-02-10 04:15:21 Branches: 34 46 73.9 %

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 <climits>
30
#include <cstddef>
31
#include <cstdio>
32
#include <cstdlib>
33
#include <cstring>
34
35
#include <array>
36
#include <limits>
37
#include <memory>
38
#include <string>
39
#include <type_traits>
40
#include <unordered_map>
41
#include <utility>
42
#include <vector>
43
44
#ifdef __GNUC__
45
#define MUST_USE_RESULT __attribute__((warn_unused_result))
46
#else
47
#define MUST_USE_RESULT
48
#endif
49
50
namespace node {
51
52
// Maybe remove kPathSeparator when cpp17 is ready
53
#ifdef _WIN32
54
    constexpr char kPathSeparator = '\\';
55
/* MAX_PATH is in characters, not bytes. Make sure we have enough headroom. */
56
#define PATH_MAX_BYTES (MAX_PATH * 4)
57
#else
58
    constexpr char kPathSeparator = '/';
59
#define PATH_MAX_BYTES (PATH_MAX)
60
#endif
61
62
// These should be used in our code as opposed to the native
63
// versions as they abstract out some platform and or
64
// compiler version specific functionality
65
// malloc(0) and realloc(ptr, 0) have implementation-defined behavior in
66
// that the standard allows them to either return a unique pointer or a
67
// nullptr for zero-sized allocation requests.  Normalize by always using
68
// a nullptr.
69
template <typename T>
70
inline T* UncheckedRealloc(T* pointer, size_t n);
71
template <typename T>
72
inline T* UncheckedMalloc(size_t n);
73
template <typename T>
74
inline T* UncheckedCalloc(size_t n);
75
76
// Same things, but aborts immediately instead of returning nullptr when
77
// no memory is available.
78
template <typename T>
79
inline T* Realloc(T* pointer, size_t n);
80
template <typename T>
81
inline T* Malloc(size_t n);
82
template <typename T>
83
inline T* Calloc(size_t n);
84
85
inline char* Malloc(size_t n);
86
inline char* Calloc(size_t n);
87
inline char* UncheckedMalloc(size_t n);
88
inline char* UncheckedCalloc(size_t n);
89
90
template <typename T>
91
inline T MultiplyWithOverflowCheck(T a, T b);
92
93
namespace per_process {
94
// Tells whether the per-process V8::Initialize() is called and
95
// if it is safe to call v8::Isolate::TryGetCurrent().
96
extern bool v8_initialized;
97
}  // namespace per_process
98
99
// Used by the allocation functions when allocation fails.
100
// Thin wrapper around v8::Isolate::LowMemoryNotification() that checks
101
// whether V8 is initialized.
102
void LowMemoryNotification();
103
104
// The reason that Assert() takes a struct argument instead of individual
105
// const char*s is to ease instruction cache pressure in calls from CHECK.
106
struct AssertionInfo {
107
  const char* file_line;  // filename:line
108
  const char* message;
109
  const char* function;
110
};
111
[[noreturn]] void Assert(const AssertionInfo& info);
112
[[noreturn]] void Abort();
113
void DumpBacktrace(FILE* fp);
114
115
// Windows 8+ does not like abort() in Release mode
116
#ifdef _WIN32
117
#define ABORT_NO_BACKTRACE() _exit(134)
118
#else
119
#define ABORT_NO_BACKTRACE() abort()
120
#endif
121
122
#define ABORT() node::Abort()
123
124
#define ERROR_AND_ABORT(expr)                                                 \
125
  do {                                                                        \
126
    /* Make sure that this struct does not end up in inline code, but      */ \
127
    /* rather in a read-only data section when modifying this code.        */ \
128
    static const node::AssertionInfo args = {                                 \
129
      __FILE__ ":" STRINGIFY(__LINE__), #expr, PRETTY_FUNCTION_NAME           \
130
    };                                                                        \
131
    node::Assert(args);                                                       \
132
  } while (0)
133
134
#ifdef __GNUC__
135
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
136
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
137
#define PRETTY_FUNCTION_NAME __PRETTY_FUNCTION__
138
#else
139
#define LIKELY(expr) expr
140
#define UNLIKELY(expr) expr
141
#define PRETTY_FUNCTION_NAME ""
142
#endif
143
144
#define STRINGIFY_(x) #x
145
#define STRINGIFY(x) STRINGIFY_(x)
146
147
#define CHECK(expr)                                                           \
148
  do {                                                                        \
149
    if (UNLIKELY(!(expr))) {                                                  \
150
      ERROR_AND_ABORT(expr);                                                  \
151
    }                                                                         \
152
  } while (0)
153
154
#define CHECK_EQ(a, b) CHECK((a) == (b))
155
#define CHECK_GE(a, b) CHECK((a) >= (b))
156
#define CHECK_GT(a, b) CHECK((a) > (b))
157
#define CHECK_LE(a, b) CHECK((a) <= (b))
158
#define CHECK_LT(a, b) CHECK((a) < (b))
159
#define CHECK_NE(a, b) CHECK((a) != (b))
160
#define CHECK_NULL(val) CHECK((val) == nullptr)
161
#define CHECK_NOT_NULL(val) CHECK((val) != nullptr)
162
#define CHECK_IMPLIES(a, b) CHECK(!(a) || (b))
163
164
#ifdef DEBUG
165
  #define DCHECK(expr) CHECK(expr)
166
  #define DCHECK_EQ(a, b) CHECK((a) == (b))
167
  #define DCHECK_GE(a, b) CHECK((a) >= (b))
168
  #define DCHECK_GT(a, b) CHECK((a) > (b))
169
  #define DCHECK_LE(a, b) CHECK((a) <= (b))
170
  #define DCHECK_LT(a, b) CHECK((a) < (b))
171
  #define DCHECK_NE(a, b) CHECK((a) != (b))
172
  #define DCHECK_NULL(val) CHECK((val) == nullptr)
173
  #define DCHECK_NOT_NULL(val) CHECK((val) != nullptr)
174
  #define DCHECK_IMPLIES(a, b) CHECK(!(a) || (b))
175
#else
176
  #define DCHECK(expr)
177
  #define DCHECK_EQ(a, b)
178
  #define DCHECK_GE(a, b)
179
  #define DCHECK_GT(a, b)
180
  #define DCHECK_LE(a, b)
181
  #define DCHECK_LT(a, b)
182
  #define DCHECK_NE(a, b)
183
  #define DCHECK_NULL(val)
184
  #define DCHECK_NOT_NULL(val)
185
  #define DCHECK_IMPLIES(a, b)
186
#endif
187
188
189
#define UNREACHABLE(...)                                                      \
190
  ERROR_AND_ABORT("Unreachable code reached" __VA_OPT__(": ") __VA_ARGS__)
191
192
// ECMA262 20.1.2.6 Number.MAX_SAFE_INTEGER (2^53-1)
193
constexpr int64_t kMaxSafeJsInteger = 9007199254740991;
194
195
inline bool IsSafeJsInt(v8::Local<v8::Value> v);
196
197
// TAILQ-style intrusive list node.
198
template <typename T>
199
class ListNode;
200
201
// TAILQ-style intrusive list head.
202
template <typename T, ListNode<T> (T::*M)>
203
class ListHead;
204
205
template <typename T>
206
class ListNode {
207
 public:
208
  inline ListNode();
209
  inline ~ListNode();
210
  inline void Remove();
211
  inline bool IsEmpty() const;
212
213
  ListNode(const ListNode&) = delete;
214
  ListNode& operator=(const ListNode&) = delete;
215
216
 private:
217
  template <typename U, ListNode<U> (U::*M)> friend class ListHead;
218
  friend int GenDebugSymbols();
219
  ListNode* prev_;
220
  ListNode* next_;
221
};
222
223
template <typename T, ListNode<T> (T::*M)>
224
class ListHead {
225
 public:
226
  class Iterator {
227
   public:
228
    inline T* operator*() const;
229
    inline const Iterator& operator++();
230
    inline bool operator!=(const Iterator& that) const;
231
232
   private:
233
    friend class ListHead;
234
    inline explicit Iterator(ListNode<T>* node);
235
    ListNode<T>* node_;
236
  };
237
238
22213
  inline ListHead() = default;
239
  inline ~ListHead();
240
  inline void PushBack(T* element);
241
  inline void PushFront(T* element);
242
  inline bool IsEmpty() const;
243
  inline T* PopFront();
244
  inline Iterator begin() const;
245
  inline Iterator end() const;
246
247
  ListHead(const ListHead&) = delete;
248
  ListHead& operator=(const ListHead&) = delete;
249
250
 private:
251
  friend int GenDebugSymbols();
252
  ListNode<T> head_;
253
};
254
255
// The helper is for doing safe downcasts from base types to derived types.
256
template <typename Inner, typename Outer>
257
class ContainerOfHelper {
258
 public:
259
  inline ContainerOfHelper(Inner Outer::*field, Inner* pointer);
260
  template <typename TypeName>
261
  inline operator TypeName*() const;
262
 private:
263
  Outer* const pointer_;
264
};
265
266
// Calculate the address of the outer (i.e. embedding) struct from
267
// the interior pointer to a data member.
268
template <typename Inner, typename Outer>
269
constexpr ContainerOfHelper<Inner, Outer> ContainerOf(Inner Outer::*field,
270
                                                      Inner* pointer);
271
272
// Convenience wrapper around v8::String::NewFromOneByte().
273
inline v8::Local<v8::String> OneByteString(v8::Isolate* isolate,
274
                                           const char* data,
275
                                           int length = -1);
276
277
// For the people that compile with -funsigned-char.
278
inline v8::Local<v8::String> OneByteString(v8::Isolate* isolate,
279
                                           const signed char* data,
280
                                           int length = -1);
281
282
inline v8::Local<v8::String> OneByteString(v8::Isolate* isolate,
283
                                           const unsigned char* data,
284
                                           int length = -1);
285
286
// Used to be a macro, hence the uppercase name.
287
template <int N>
288
6287973
inline v8::Local<v8::String> FIXED_ONE_BYTE_STRING(
289
    v8::Isolate* isolate,
290
    const char(&data)[N]) {
291
6287973
  return OneByteString(isolate, data, N - 1);
292
}
293
294
template <std::size_t N>
295
536
inline v8::Local<v8::String> FIXED_ONE_BYTE_STRING(
296
    v8::Isolate* isolate,
297
    const std::array<char, N>& arr) {
298
536
  return OneByteString(isolate, arr.data(), N - 1);
299
}
300
301
302
303
// Swaps bytes in place. nbytes is the number of bytes to swap and must be a
304
// multiple of the word size (checked by function).
305
inline void SwapBytes16(char* data, size_t nbytes);
306
inline void SwapBytes32(char* data, size_t nbytes);
307
inline void SwapBytes64(char* data, size_t nbytes);
308
309
// tolower() is locale-sensitive.  Use ToLower() instead.
310
inline char ToLower(char c);
311
inline std::string ToLower(const std::string& in);
312
313
// toupper() is locale-sensitive.  Use ToUpper() instead.
314
inline char ToUpper(char c);
315
inline std::string ToUpper(const std::string& in);
316
317
// strcasecmp() is locale-sensitive.  Use StringEqualNoCase() instead.
318
inline bool StringEqualNoCase(const char* a, const char* b);
319
320
// strncasecmp() is locale-sensitive.  Use StringEqualNoCaseN() instead.
321
inline bool StringEqualNoCaseN(const char* a, const char* b, size_t length);
322
323
template <typename T, size_t N>
324
10989596
constexpr size_t arraysize(const T (&)[N]) {
325
10989596
  return N;
326
}
327
328
template <typename T, size_t N>
329
constexpr size_t strsize(const T (&)[N]) {
330
  return N - 1;
331
}
332
333
// Allocates an array of member type T. For up to kStackStorageSize items,
334
// the stack is used, otherwise malloc().
335
template <typename T, size_t kStackStorageSize = 1024>
336
class MaybeStackBuffer {
337
 public:
338
5655
  const T* out() const {
339
5655
    return buf_;
340
  }
341
342
6079413
  T* out() {
343
6079413
    return buf_;
344
  }
345
346
  // operator* for compatibility with `v8::String::(Utf8)Value`
347
8955235
  T* operator*() {
348
8955235
    return buf_;
349
  }
350
351
30118
  const T* operator*() const {
352
30118
    return buf_;
353
  }
354
355
4283119
  T& operator[](size_t index) {
356
4283119
    CHECK_LT(index, length());
357
4283119
    return buf_[index];
358
  }
359
360
10914
  const T& operator[](size_t index) const {
361
10914
    CHECK_LT(index, length());
362
10914
    return buf_[index];
363
  }
364
365
12455240
  size_t length() const {
366
12455240
    return length_;
367
  }
368
369
  // Current maximum capacity of the buffer with which SetLength() can be used
370
  // without first calling AllocateSufficientStorage().
371
18966393
  size_t capacity() const {
372
18966393
    return capacity_;
373
  }
374
375
  // Make sure enough space for `storage` entries is available.
376
  // This method can be called multiple times throughout the lifetime of the
377
  // buffer, but once this has been called Invalidate() cannot be used.
378
  // Content of the buffer in the range [0, length()) is preserved.
379
6739956
  void AllocateSufficientStorage(size_t storage) {
380
6739956
    CHECK(!IsInvalidated());
381
6739956
    if (storage > capacity()) {
382
268703
      bool was_allocated = IsAllocated();
383
268703
      T* allocated_ptr = was_allocated ? buf_ : nullptr;
384
268703
      buf_ = Realloc(allocated_ptr, storage);
385
268703
      capacity_ = storage;
386

268703
      if (!was_allocated && length_ > 0)
387
4
        memcpy(buf_, buf_st_, length_ * sizeof(buf_[0]));
388
    }
389
390
6739956
    length_ = storage;
391
6739956
  }
392
393
5983091
  void SetLength(size_t length) {
394
    // capacity() returns how much memory is actually available.
395
5983091
    CHECK_LE(length, capacity());
396
5983091
    length_ = length;
397
5983091
  }
398
399
8784806
  void SetLengthAndZeroTerminate(size_t length) {
400
    // capacity() returns how much memory is actually available.
401
8784806
    CHECK_LE(length + 1, capacity());
402
8784806
    SetLength(length);
403
404
    // T() is 0 for integer types, nullptr for pointers, etc.
405
8784806
    buf_[length] = T();
406
8784806
  }
407
408
  // Make dereferencing this object return nullptr.
409
  // This method can be called multiple times throughout the lifetime of the
410
  // buffer, but once this has been called AllocateSufficientStorage() cannot
411
  // be used.
412
2
  void Invalidate() {
413
2
    CHECK(!IsAllocated());
414
2
    capacity_ = 0;
415
2
    length_ = 0;
416
2
    buf_ = nullptr;
417
2
  }
418
419
  // If the buffer is stored in the heap rather than on the stack.
420
8585901
  bool IsAllocated() const {
421

8585901
    return !IsInvalidated() && buf_ != buf_st_;
422
  }
423
424
  // If Invalidate() has been called.
425
15384710
  bool IsInvalidated() const {
426
15384710
    return buf_ == nullptr;
427
  }
428
429
  // Release ownership of the malloc'd buffer.
430
  // Note: This does not free the buffer.
431
588
  void Release() {
432
588
    CHECK(IsAllocated());
433
588
    buf_ = buf_st_;
434
588
    length_ = 0;
435
588
    capacity_ = arraysize(buf_st_);
436
588
  }
437
438
8209595
  MaybeStackBuffer()
439
143369523
      : length_(0), capacity_(arraysize(buf_st_)), buf_(buf_st_) {
440
    // Default to a zero-length, null-terminated buffer.
441
8209595
    buf_[0] = T();
442
8209595
  }
443
444
750022
  explicit MaybeStackBuffer(size_t storage) : MaybeStackBuffer() {
445
750022
    AllocateSufficientStorage(storage);
446
750022
  }
447
448
8309748
  ~MaybeStackBuffer() {
449
8309748
    if (IsAllocated())
450
268112
      free(buf_);
451
8309748
  }
452
453
 private:
454
  size_t length_;
455
  // capacity of the malloc'ed buf_
456
  size_t capacity_;
457
  T* buf_;
458
  T buf_st_[kStackStorageSize];
459
};
460
461
// Provides access to an ArrayBufferView's storage, either the original,
462
// or for small data, a copy of it. This object's lifetime is bound to the
463
// original ArrayBufferView's lifetime.
464
template <typename T, size_t kStackStorageSize = 64>
465
class ArrayBufferViewContents {
466
 public:
467
1216
  ArrayBufferViewContents() = default;
468
469
  explicit inline ArrayBufferViewContents(v8::Local<v8::Value> value);
470
  explicit inline ArrayBufferViewContents(v8::Local<v8::Object> value);
471
  explicit inline ArrayBufferViewContents(v8::Local<v8::ArrayBufferView> abv);
472
  inline void Read(v8::Local<v8::ArrayBufferView> abv);
473
474
172556
  inline const T* data() const { return data_; }
475
697004
  inline size_t length() const { return length_; }
476
477
 private:
478
  T stack_storage_[kStackStorageSize];
479
  T* data_ = nullptr;
480
  size_t length_ = 0;
481
};
482
483
class Utf8Value : public MaybeStackBuffer<char> {
484
 public:
485
  explicit Utf8Value(v8::Isolate* isolate, v8::Local<v8::Value> value);
486
487
841
  inline std::string ToString() const { return std::string(out(), length()); }
488
489
4814
  inline bool operator==(const char* a) const {
490
4814
    return strcmp(out(), a) == 0;
491
  }
492
};
493
494
class TwoByteValue : public MaybeStackBuffer<uint16_t> {
495
 public:
496
  explicit TwoByteValue(v8::Isolate* isolate, v8::Local<v8::Value> value);
497
};
498
499
class BufferValue : public MaybeStackBuffer<char> {
500
 public:
501
  explicit BufferValue(v8::Isolate* isolate, v8::Local<v8::Value> value);
502
503
  inline std::string ToString() const { return std::string(out(), length()); }
504
};
505
506
#define SPREAD_BUFFER_ARG(val, name)                                          \
507
  CHECK((val)->IsArrayBufferView());                                          \
508
  v8::Local<v8::ArrayBufferView> name = (val).As<v8::ArrayBufferView>();      \
509
  std::shared_ptr<v8::BackingStore> name##_bs =                               \
510
      name->Buffer()->GetBackingStore();                                      \
511
  const size_t name##_offset = name->ByteOffset();                            \
512
  const size_t name##_length = name->ByteLength();                            \
513
  char* const name##_data =                                                   \
514
      static_cast<char*>(name##_bs->Data()) + name##_offset;                  \
515
  if (name##_length > 0)                                                      \
516
    CHECK_NE(name##_data, nullptr);
517
518
// Use this when a variable or parameter is unused in order to explicitly
519
// silence a compiler warning about that.
520
4213660
template <typename T> inline void USE(T&&) {}
521
522
template <typename Fn>
523
struct OnScopeLeaveImpl {
524
  Fn fn_;
525
  bool active_;
526
527
3201947
  explicit OnScopeLeaveImpl(Fn&& fn) : fn_(std::move(fn)), active_(true) {}
528
1613689
  ~OnScopeLeaveImpl() { if (active_) fn_(); }
529
530
  OnScopeLeaveImpl(const OnScopeLeaveImpl& other) = delete;
531
  OnScopeLeaveImpl& operator=(const OnScopeLeaveImpl& other) = delete;
532
  OnScopeLeaveImpl(OnScopeLeaveImpl&& other)
533
    : fn_(std::move(other.fn_)), active_(other.active_) {
534
    other.active_ = false;
535
  }
536
  OnScopeLeaveImpl& operator=(OnScopeLeaveImpl&& other) {
537
    if (this == &other) return *this;
538
    this->~OnScopeLeave();
539
    new (this)OnScopeLeaveImpl(std::move(other));
540
    return *this;
541
  }
542
};
543
544
// Run a function when exiting the current scope. Used like this:
545
// auto on_scope_leave = OnScopeLeave([&] {
546
//   // ... run some code ...
547
// });
548
template <typename Fn>
549
3201947
inline MUST_USE_RESULT OnScopeLeaveImpl<Fn> OnScopeLeave(Fn&& fn) {
550
3201947
  return OnScopeLeaveImpl<Fn>{std::move(fn)};
551
}
552
553
// Simple RAII wrapper for contiguous data that uses malloc()/free().
554
template <typename T>
555
struct MallocedBuffer {
556
  T* data;
557
  size_t size;
558
559
  T* release() {
560
    T* ret = data;
561
    data = nullptr;
562
    return ret;
563
  }
564
565
  void Truncate(size_t new_size) {
566
    CHECK(new_size <= size);
567
    size = new_size;
568
  }
569
570
  void Realloc(size_t new_size) {
571
    Truncate(new_size);
572
    data = UncheckedRealloc(data, new_size);
573
  }
574
575
60782
  inline bool is_empty() const { return data == nullptr; }
576
577
96106
  MallocedBuffer() : data(nullptr), size(0) {}
578
23
  explicit MallocedBuffer(size_t size) : data(Malloc<T>(size)), size(size) {}
579
60796
  MallocedBuffer(T* data, size_t size) : data(data), size(size) {}
580
156866
  MallocedBuffer(MallocedBuffer&& other) : data(other.data), size(other.size) {
581
156866
    other.data = nullptr;
582
156866
  }
583
60810
  MallocedBuffer& operator=(MallocedBuffer&& other) {
584
60810
    this->~MallocedBuffer();
585
60810
    return *new(this) MallocedBuffer(std::move(other));
586
  }
587
313766
  ~MallocedBuffer() {
588
313766
    free(data);
589
313766
  }
590
  MallocedBuffer(const MallocedBuffer&) = delete;
591
  MallocedBuffer& operator=(const MallocedBuffer&) = delete;
592
};
593
594
template <typename T>
595
class NonCopyableMaybe {
596
 public:
597
3985
  NonCopyableMaybe() : empty_(true) {}
598
3761
  explicit NonCopyableMaybe(T&& value)
599
      : empty_(false),
600
7522
        value_(std::move(value)) {}
601
602
7476
  bool IsEmpty() const {
603
7476
    return empty_;
604
  }
605
606
1465
  const T* get() const {
607
1465
    return empty_ ? nullptr : &value_;
608
  }
609
610
18
  const T* operator->() const {
611
18
    CHECK(!empty_);
612
18
    return &value_;
613
  }
614
615
3673
  T&& Release() {
616
3673
    CHECK_EQ(empty_, false);
617
3673
    empty_ = true;
618
3673
    return std::move(value_);
619
  }
620
621
 private:
622
  bool empty_;
623
  T value_;
624
};
625
626
// Test whether some value can be called with ().
627
template <typename T, typename = void>
628
struct is_callable : std::is_function<T> { };
629
630
template <typename T>
631
struct is_callable<T, typename std::enable_if<
632
    std::is_same<decltype(void(&T::operator())), void>::value
633
    >::type> : std::true_type { };
634
635
template <typename T, void (*function)(T*)>
636
struct FunctionDeleter {
637
181890
  void operator()(T* pointer) const { function(pointer); }
638
  typedef std::unique_ptr<T, FunctionDeleter> Pointer;
639
};
640
641
template <typename T, void (*function)(T*)>
642
using DeleteFnPtr = typename FunctionDeleter<T, function>::Pointer;
643
644
std::vector<std::string> SplitString(const std::string& in, char delim);
645
646
inline v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context,
647
                                           const std::string& str,
648
                                           v8::Isolate* isolate = nullptr);
649
template <typename T, typename test_for_number =
650
    typename std::enable_if<std::numeric_limits<T>::is_specialized, bool>::type>
651
inline v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context,
652
                                           const T& number,
653
                                           v8::Isolate* isolate = nullptr);
654
template <typename T>
655
inline v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context,
656
                                           const std::vector<T>& vec,
657
                                           v8::Isolate* isolate = nullptr);
658
template <typename T, typename U>
659
inline v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context,
660
                                           const std::unordered_map<T, U>& map,
661
                                           v8::Isolate* isolate = nullptr);
662
663
// These macros expects a `Isolate* isolate` and a `Local<Context> context`
664
// to be in the scope.
665
#define READONLY_PROPERTY(obj, name, value)                                    \
666
  do {                                                                         \
667
    obj->DefineOwnProperty(                                                    \
668
           context, FIXED_ONE_BYTE_STRING(isolate, name), value, v8::ReadOnly) \
669
        .Check();                                                              \
670
  } while (0)
671
672
#define READONLY_DONT_ENUM_PROPERTY(obj, name, var)                            \
673
  do {                                                                         \
674
    obj->DefineOwnProperty(                                                    \
675
           context,                                                            \
676
           OneByteString(isolate, name),                                       \
677
           var,                                                                \
678
           static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum))    \
679
        .Check();                                                              \
680
  } while (0)
681
682
#define READONLY_FALSE_PROPERTY(obj, name)                                     \
683
  READONLY_PROPERTY(obj, name, v8::False(isolate))
684
685
#define READONLY_TRUE_PROPERTY(obj, name)                                      \
686
  READONLY_PROPERTY(obj, name, v8::True(isolate))
687
688
#define READONLY_STRING_PROPERTY(obj, name, str)                               \
689
  READONLY_PROPERTY(obj, name, ToV8Value(context, str).ToLocalChecked())
690
691
// Variation on NODE_DEFINE_CONSTANT that sets a String value.
692
#define NODE_DEFINE_STRING_CONSTANT(target, name, constant)                    \
693
  do {                                                                         \
694
    v8::Isolate* isolate = target->GetIsolate();                               \
695
    v8::Local<v8::String> constant_name =                                      \
696
        v8::String::NewFromUtf8(isolate, name).ToLocalChecked();               \
697
    v8::Local<v8::String> constant_value =                                     \
698
        v8::String::NewFromUtf8(isolate, constant).ToLocalChecked();           \
699
    v8::PropertyAttribute constant_attributes =                                \
700
        static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete);     \
701
    target                                                                     \
702
        ->DefineOwnProperty(isolate->GetCurrentContext(),                      \
703
                            constant_name,                                     \
704
                            constant_value,                                    \
705
                            constant_attributes)                               \
706
        .Check();                                                              \
707
  } while (0)
708
709
enum Endianness {
710
  kLittleEndian,  // _Not_ LITTLE_ENDIAN, clashes with endian.h.
711
  kBigEndian
712
};
713
714
7630
inline enum Endianness GetEndianness() {
715
  // Constant-folded by the compiler.
716
  const union {
717
    uint8_t u8[2];
718
    uint16_t u16;
719
7630
  } u = {{1, 0}};
720
7630
  return u.u16 == 1 ? kLittleEndian : kBigEndian;
721
}
722
723
1
inline bool IsLittleEndian() {
724
1
  return GetEndianness() == kLittleEndian;
725
}
726
727
7629
inline bool IsBigEndian() {
728
7629
  return GetEndianness() == kBigEndian;
729
}
730
731
// Round up a to the next highest multiple of b.
732
template <typename T>
733
132187
constexpr T RoundUp(T a, T b) {
734
132187
  return a % b != 0 ? a + b - (a % b) : a;
735
}
736
737
// Align ptr to an `alignment`-bytes boundary.
738
template <typename T, typename U>
739
23631
constexpr T* AlignUp(T* ptr, U alignment) {
740
  return reinterpret_cast<T*>(
741
23631
      RoundUp(reinterpret_cast<uintptr_t>(ptr), alignment));
742
}
743
744
class SlicedArguments : public MaybeStackBuffer<v8::Local<v8::Value>> {
745
 public:
746
  inline explicit SlicedArguments(
747
      const v8::FunctionCallbackInfo<v8::Value>& args, size_t start = 0);
748
};
749
750
// Convert a v8::PersistentBase, e.g. v8::Global, to a Local, with an extra
751
// optimization for strong persistent handles.
752
class PersistentToLocal {
753
 public:
754
  // If persistent.IsWeak() == false, then do not call persistent.Reset()
755
  // while the returned Local<T> is still in scope, it will destroy the
756
  // reference to the object.
757
  template <class TypeName>
758
6653086
  static inline v8::Local<TypeName> Default(
759
      v8::Isolate* isolate,
760
      const v8::PersistentBase<TypeName>& persistent) {
761
6653086
    if (persistent.IsWeak()) {
762
4416938
      return PersistentToLocal::Weak(isolate, persistent);
763
    } else {
764
2236148
      return PersistentToLocal::Strong(persistent);
765
    }
766
  }
767
768
  // Unchecked conversion from a non-weak Persistent<T> to Local<T>,
769
  // use with care!
770
  //
771
  // Do not call persistent.Reset() while the returned Local<T> is still in
772
  // scope, it will destroy the reference to the object.
773
  template <class TypeName>
774
28808848
  static inline v8::Local<TypeName> Strong(
775
      const v8::PersistentBase<TypeName>& persistent) {
776
    DCHECK(!persistent.IsWeak());
777
    return *reinterpret_cast<v8::Local<TypeName>*>(
778
28808848
        const_cast<v8::PersistentBase<TypeName>*>(&persistent));
779
  }
780
781
  template <class TypeName>
782
2311307
  static inline v8::Local<TypeName> Weak(
783
      v8::Isolate* isolate,
784
      const v8::PersistentBase<TypeName>& persistent) {
785
2311307
    return v8::Local<TypeName>::New(isolate, persistent);
786
  }
787
};
788
789
// Can be used as a key for std::unordered_map when lookup performance is more
790
// important than size and the keys are statically used to avoid redundant hash
791
// computations.
792
class FastStringKey {
793
 public:
794
  constexpr explicit FastStringKey(const char* name);
795
796
  struct Hash {
797
    constexpr size_t operator()(const FastStringKey& key) const;
798
  };
799
  constexpr bool operator==(const FastStringKey& other) const;
800
801
  constexpr const char* c_str() const;
802
803
 private:
804
  static constexpr size_t HashImpl(const char* str);
805
806
  const char* name_;
807
  size_t cached_hash_;
808
};
809
810
// Like std::static_pointer_cast but for unique_ptr with the default deleter.
811
template <typename T, typename U>
812
10596
std::unique_ptr<T> static_unique_pointer_cast(std::unique_ptr<U>&& ptr) {
813
10596
  return std::unique_ptr<T>(static_cast<T*>(ptr.release()));
814
}
815
816
#define MAYBE_FIELD_PTR(ptr, field) ptr == nullptr ? nullptr : &(ptr->field)
817
818
// Returns a non-zero code if it fails to open or read the file,
819
// aborts if it fails to close the file.
820
int ReadFileSync(std::string* result, const char* path);
821
}  // namespace node
822
823
#endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
824
825
#endif  // SRC_UTIL_H_