The C and C++ Include Header Files
/usr/include/nodejs/src/util.h
$ cat -n /usr/include/nodejs/src/util.h 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 #if (__GNUC__ >= 8) && !defined(__clang__) 28 #pragma GCC diagnostic push 29 #pragma GCC diagnostic ignored "-Wcast-function-type" 30 #endif 31 #include "v8.h" 32 #if (__GNUC__ >= 8) && !defined(__clang__) 33 #pragma GCC diagnostic pop 34 #endif 35 36 #include
37 #include
38 #include
39 #include
40 #include
41 42 #include
// std::function 43 #include
44 #include
45 #include
46 #include
47 #include
48 #include
49 50 #ifdef __GNUC__ 51 #define MUST_USE_RESULT __attribute__((warn_unused_result)) 52 #else 53 #define MUST_USE_RESULT 54 #endif 55 56 namespace node { 57 58 // Maybe remove kPathSeparator when cpp17 is ready 59 #ifdef _WIN32 60 constexpr char kPathSeparator = '\\'; 61 /* MAX_PATH is in characters, not bytes. Make sure we have enough headroom. */ 62 #define PATH_MAX_BYTES (MAX_PATH * 4) 63 #else 64 constexpr char kPathSeparator = '/'; 65 #define PATH_MAX_BYTES (PATH_MAX) 66 #endif 67 68 // These should be used in our code as opposed to the native 69 // versions as they abstract out some platform and or 70 // compiler version specific functionality 71 // malloc(0) and realloc(ptr, 0) have implementation-defined behavior in 72 // that the standard allows them to either return a unique pointer or a 73 // nullptr for zero-sized allocation requests. Normalize by always using 74 // a nullptr. 75 template
76 inline T* UncheckedRealloc(T* pointer, size_t n); 77 template
78 inline T* UncheckedMalloc(size_t n); 79 template
80 inline T* UncheckedCalloc(size_t n); 81 82 // Same things, but aborts immediately instead of returning nullptr when 83 // no memory is available. 84 template
85 inline T* Realloc(T* pointer, size_t n); 86 template
87 inline T* Malloc(size_t n); 88 template
89 inline T* Calloc(size_t n); 90 91 inline char* Malloc(size_t n); 92 inline char* Calloc(size_t n); 93 inline char* UncheckedMalloc(size_t n); 94 inline char* UncheckedCalloc(size_t n); 95 96 template
97 inline T MultiplyWithOverflowCheck(T a, T b); 98 99 namespace per_process { 100 // Tells whether the per-process V8::Initialize() is called and 101 // if it is safe to call v8::Isolate::GetCurrent(). 102 extern bool v8_initialized; 103 } // namespace per_process 104 105 // Used by the allocation functions when allocation fails. 106 // Thin wrapper around v8::Isolate::LowMemoryNotification() that checks 107 // whether V8 is initialized. 108 void LowMemoryNotification(); 109 110 // The reason that Assert() takes a struct argument instead of individual 111 // const char*s is to ease instruction cache pressure in calls from CHECK. 112 struct AssertionInfo { 113 const char* file_line; // filename:line 114 const char* message; 115 const char* function; 116 }; 117 [[noreturn]] void Assert(const AssertionInfo& info); 118 [[noreturn]] void Abort(); 119 void DumpBacktrace(FILE* fp); 120 121 // Windows 8+ does not like abort() in Release mode 122 #ifdef _WIN32 123 #define ABORT_NO_BACKTRACE() _exit(134) 124 #else 125 #define ABORT_NO_BACKTRACE() abort() 126 #endif 127 128 #define ABORT() node::Abort() 129 130 #define ERROR_AND_ABORT(expr) \ 131 do { \ 132 /* Make sure that this struct does not end up in inline code, but */ \ 133 /* rather in a read-only data section when modifying this code. */ \ 134 static const node::AssertionInfo args = { \ 135 __FILE__ ":" STRINGIFY(__LINE__), #expr, PRETTY_FUNCTION_NAME \ 136 }; \ 137 node::Assert(args); \ 138 } while (0) 139 140 #ifdef __GNUC__ 141 #define LIKELY(expr) __builtin_expect(!!(expr), 1) 142 #define UNLIKELY(expr) __builtin_expect(!!(expr), 0) 143 #define PRETTY_FUNCTION_NAME __PRETTY_FUNCTION__ 144 #else 145 #define LIKELY(expr) expr 146 #define UNLIKELY(expr) expr 147 #define PRETTY_FUNCTION_NAME "" 148 #endif 149 150 #define STRINGIFY_(x) #x 151 #define STRINGIFY(x) STRINGIFY_(x) 152 153 #define CHECK(expr) \ 154 do { \ 155 if (UNLIKELY(!(expr))) { \ 156 ERROR_AND_ABORT(expr); \ 157 } \ 158 } while (0) 159 160 #define CHECK_EQ(a, b) CHECK((a) == (b)) 161 #define CHECK_GE(a, b) CHECK((a) >= (b)) 162 #define CHECK_GT(a, b) CHECK((a) > (b)) 163 #define CHECK_LE(a, b) CHECK((a) <= (b)) 164 #define CHECK_LT(a, b) CHECK((a) < (b)) 165 #define CHECK_NE(a, b) CHECK((a) != (b)) 166 #define CHECK_NULL(val) CHECK((val) == nullptr) 167 #define CHECK_NOT_NULL(val) CHECK((val) != nullptr) 168 #define CHECK_IMPLIES(a, b) CHECK(!(a) || (b)) 169 170 #ifdef DEBUG 171 #define DCHECK(expr) CHECK(expr) 172 #define DCHECK_EQ(a, b) CHECK((a) == (b)) 173 #define DCHECK_GE(a, b) CHECK((a) >= (b)) 174 #define DCHECK_GT(a, b) CHECK((a) > (b)) 175 #define DCHECK_LE(a, b) CHECK((a) <= (b)) 176 #define DCHECK_LT(a, b) CHECK((a) < (b)) 177 #define DCHECK_NE(a, b) CHECK((a) != (b)) 178 #define DCHECK_NULL(val) CHECK((val) == nullptr) 179 #define DCHECK_NOT_NULL(val) CHECK((val) != nullptr) 180 #define DCHECK_IMPLIES(a, b) CHECK(!(a) || (b)) 181 #else 182 #define DCHECK(expr) 183 #define DCHECK_EQ(a, b) 184 #define DCHECK_GE(a, b) 185 #define DCHECK_GT(a, b) 186 #define DCHECK_LE(a, b) 187 #define DCHECK_LT(a, b) 188 #define DCHECK_NE(a, b) 189 #define DCHECK_NULL(val) 190 #define DCHECK_NOT_NULL(val) 191 #define DCHECK_IMPLIES(a, b) 192 #endif 193 194 195 #define UNREACHABLE(...) \ 196 ERROR_AND_ABORT("Unreachable code reached" __VA_OPT__(": ") __VA_ARGS__) 197 198 // TAILQ-style intrusive list node. 199 template
200 class ListNode; 201 202 // TAILQ-style intrusive list head. 203 template
(T::*M)> 204 class ListHead; 205 206 template
207 class ListNode { 208 public: 209 inline ListNode(); 210 inline ~ListNode(); 211 inline void Remove(); 212 inline bool IsEmpty() const; 213 214 ListNode(const ListNode&) = delete; 215 ListNode& operator=(const ListNode&) = delete; 216 217 private: 218 template
(U::*M)> friend class ListHead; 219 friend int GenDebugSymbols(); 220 ListNode* prev_; 221 ListNode* next_; 222 }; 223 224 template
(T::*M)> 225 class ListHead { 226 public: 227 class Iterator { 228 public: 229 inline T* operator*() const; 230 inline const Iterator& operator++(); 231 inline bool operator!=(const Iterator& that) const; 232 233 private: 234 friend class ListHead; 235 inline explicit Iterator(ListNode
* node); 236 ListNode
* node_; 237 }; 238 239 inline ListHead() = default; 240 inline ~ListHead(); 241 inline void PushBack(T* element); 242 inline void PushFront(T* element); 243 inline bool IsEmpty() const; 244 inline T* PopFront(); 245 inline Iterator begin() const; 246 inline Iterator end() const; 247 248 ListHead(const ListHead&) = delete; 249 ListHead& operator=(const ListHead&) = delete; 250 251 private: 252 friend int GenDebugSymbols(); 253 ListNode
head_; 254 }; 255 256 // The helper is for doing safe downcasts from base types to derived types. 257 template
258 class ContainerOfHelper { 259 public: 260 inline ContainerOfHelper(Inner Outer::*field, Inner* pointer); 261 template
262 inline operator TypeName*() const; 263 private: 264 Outer* const pointer_; 265 }; 266 267 // Calculate the address of the outer (i.e. embedding) struct from 268 // the interior pointer to a data member. 269 template
270 constexpr ContainerOfHelper
ContainerOf(Inner Outer::*field, 271 Inner* pointer); 272 273 // Convenience wrapper around v8::String::NewFromOneByte(). 274 inline v8::Local
OneByteString(v8::Isolate* isolate, 275 const char* data, 276 int length = -1); 277 278 // For the people that compile with -funsigned-char. 279 inline v8::Local
OneByteString(v8::Isolate* isolate, 280 const signed char* data, 281 int length = -1); 282 283 inline v8::Local
OneByteString(v8::Isolate* isolate, 284 const unsigned char* data, 285 int length = -1); 286 287 // Used to be a macro, hence the uppercase name. 288 template
289 inline v8::Local
FIXED_ONE_BYTE_STRING( 290 v8::Isolate* isolate, 291 const char(&data)[N]) { 292 return OneByteString(isolate, data, N - 1); 293 } 294 295 template
296 inline v8::Local
FIXED_ONE_BYTE_STRING( 297 v8::Isolate* isolate, 298 const std::array
& arr) { 299 return OneByteString(isolate, arr.data(), N - 1); 300 } 301 302 303 304 // Swaps bytes in place. nbytes is the number of bytes to swap and must be a 305 // multiple of the word size (checked by function). 306 inline void SwapBytes16(char* data, size_t nbytes); 307 inline void SwapBytes32(char* data, size_t nbytes); 308 inline void SwapBytes64(char* data, size_t nbytes); 309 310 // tolower() is locale-sensitive. Use ToLower() instead. 311 inline char ToLower(char c); 312 inline std::string ToLower(const std::string& in); 313 314 // toupper() is locale-sensitive. Use ToUpper() instead. 315 inline char ToUpper(char c); 316 inline std::string ToUpper(const std::string& in); 317 318 // strcasecmp() is locale-sensitive. Use StringEqualNoCase() instead. 319 inline bool StringEqualNoCase(const char* a, const char* b); 320 321 // strncasecmp() is locale-sensitive. Use StringEqualNoCaseN() instead. 322 inline bool StringEqualNoCaseN(const char* a, const char* b, size_t length); 323 324 template
325 constexpr size_t arraysize(const T (&)[N]) { 326 return N; 327 } 328 329 // Allocates an array of member type T. For up to kStackStorageSize items, 330 // the stack is used, otherwise malloc(). 331 template
332 class MaybeStackBuffer { 333 public: 334 const T* out() const { 335 return buf_; 336 } 337 338 T* out() { 339 return buf_; 340 } 341 342 // operator* for compatibility with `v8::String::(Utf8)Value` 343 T* operator*() { 344 return buf_; 345 } 346 347 const T* operator*() const { 348 return buf_; 349 } 350 351 T& operator[](size_t index) { 352 CHECK_LT(index, length()); 353 return buf_[index]; 354 } 355 356 const T& operator[](size_t index) const { 357 CHECK_LT(index, length()); 358 return buf_[index]; 359 } 360 361 size_t length() const { 362 return length_; 363 } 364 365 // Current maximum capacity of the buffer with which SetLength() can be used 366 // without first calling AllocateSufficientStorage(). 367 size_t capacity() const { 368 return capacity_; 369 } 370 371 // Make sure enough space for `storage` entries is available. 372 // This method can be called multiple times throughout the lifetime of the 373 // buffer, but once this has been called Invalidate() cannot be used. 374 // Content of the buffer in the range [0, length()) is preserved. 375 void AllocateSufficientStorage(size_t storage) { 376 CHECK(!IsInvalidated()); 377 if (storage > capacity()) { 378 bool was_allocated = IsAllocated(); 379 T* allocated_ptr = was_allocated ? buf_ : nullptr; 380 buf_ = Realloc(allocated_ptr, storage); 381 capacity_ = storage; 382 if (!was_allocated && length_ > 0) 383 memcpy(buf_, buf_st_, length_ * sizeof(buf_[0])); 384 } 385 386 length_ = storage; 387 } 388 389 void SetLength(size_t length) { 390 // capacity() returns how much memory is actually available. 391 CHECK_LE(length, capacity()); 392 length_ = length; 393 } 394 395 void SetLengthAndZeroTerminate(size_t length) { 396 // capacity() returns how much memory is actually available. 397 CHECK_LE(length + 1, capacity()); 398 SetLength(length); 399 400 // T() is 0 for integer types, nullptr for pointers, etc. 401 buf_[length] = T(); 402 } 403 404 // Make derefencing this object return nullptr. 405 // This method can be called multiple times throughout the lifetime of the 406 // buffer, but once this has been called AllocateSufficientStorage() cannot 407 // be used. 408 void Invalidate() { 409 CHECK(!IsAllocated()); 410 capacity_ = 0; 411 length_ = 0; 412 buf_ = nullptr; 413 } 414 415 // If the buffer is stored in the heap rather than on the stack. 416 bool IsAllocated() const { 417 return !IsInvalidated() && buf_ != buf_st_; 418 } 419 420 // If Invalidate() has been called. 421 bool IsInvalidated() const { 422 return buf_ == nullptr; 423 } 424 425 // Release ownership of the malloc'd buffer. 426 // Note: This does not free the buffer. 427 void Release() { 428 CHECK(IsAllocated()); 429 buf_ = buf_st_; 430 length_ = 0; 431 capacity_ = arraysize(buf_st_); 432 } 433 434 MaybeStackBuffer() 435 : length_(0), capacity_(arraysize(buf_st_)), buf_(buf_st_) { 436 // Default to a zero-length, null-terminated buffer. 437 buf_[0] = T(); 438 } 439 440 explicit MaybeStackBuffer(size_t storage) : MaybeStackBuffer() { 441 AllocateSufficientStorage(storage); 442 } 443 444 ~MaybeStackBuffer() { 445 if (IsAllocated()) 446 free(buf_); 447 } 448 449 private: 450 size_t length_; 451 // capacity of the malloc'ed buf_ 452 size_t capacity_; 453 T* buf_; 454 T buf_st_[kStackStorageSize]; 455 }; 456 457 // Provides access to an ArrayBufferView's storage, either the original, 458 // or for small data, a copy of it. This object's lifetime is bound to the 459 // original ArrayBufferView's lifetime. 460 template
461 class ArrayBufferViewContents { 462 public: 463 ArrayBufferViewContents() = default; 464 465 explicit inline ArrayBufferViewContents(v8::Local
value); 466 explicit inline ArrayBufferViewContents(v8::Local
value); 467 explicit inline ArrayBufferViewContents(v8::Local
abv); 468 inline void Read(v8::Local
abv); 469 470 inline const T* data() const { return data_; } 471 inline size_t length() const { return length_; } 472 473 private: 474 T stack_storage_[kStackStorageSize]; 475 T* data_ = nullptr; 476 size_t length_ = 0; 477 }; 478 479 class Utf8Value : public MaybeStackBuffer
{ 480 public: 481 explicit Utf8Value(v8::Isolate* isolate, v8::Local
value); 482 483 inline std::string ToString() const { return std::string(out(), length()); } 484 485 inline bool operator==(const char* a) const { 486 return strcmp(out(), a) == 0; 487 } 488 }; 489 490 class TwoByteValue : public MaybeStackBuffer
{ 491 public: 492 explicit TwoByteValue(v8::Isolate* isolate, v8::Local
value); 493 }; 494 495 class BufferValue : public MaybeStackBuffer
{ 496 public: 497 explicit BufferValue(v8::Isolate* isolate, v8::Local
value); 498 499 inline std::string ToString() const { return std::string(out(), length()); } 500 }; 501 502 #define SPREAD_BUFFER_ARG(val, name) \ 503 CHECK((val)->IsArrayBufferView()); \ 504 v8::Local
name = (val).As
(); \ 505 v8::ArrayBuffer::Contents name##_c = name->Buffer()->GetContents(); \ 506 const size_t name##_offset = name->ByteOffset(); \ 507 const size_t name##_length = name->ByteLength(); \ 508 char* const name##_data = \ 509 static_cast
(name##_c.Data()) + name##_offset; \ 510 if (name##_length > 0) \ 511 CHECK_NE(name##_data, nullptr); 512 513 // Use this when a variable or parameter is unused in order to explicitly 514 // silence a compiler warning about that. 515 template
inline void USE(T&&) {} 516 517 template
518 struct OnScopeLeaveImpl { 519 Fn fn_; 520 bool active_; 521 522 explicit OnScopeLeaveImpl(Fn&& fn) : fn_(std::move(fn)), active_(true) {} 523 ~OnScopeLeaveImpl() { if (active_) fn_(); } 524 525 OnScopeLeaveImpl(const OnScopeLeaveImpl& other) = delete; 526 OnScopeLeaveImpl& operator=(const OnScopeLeaveImpl& other) = delete; 527 OnScopeLeaveImpl(OnScopeLeaveImpl&& other) 528 : fn_(std::move(other.fn_)), active_(other.active_) { 529 other.active_ = false; 530 } 531 OnScopeLeaveImpl& operator=(OnScopeLeaveImpl&& other) { 532 if (this == &other) return *this; 533 this->~OnScopeLeave(); 534 new (this)OnScopeLeaveImpl(std::move(other)); 535 return *this; 536 } 537 }; 538 539 // Run a function when exiting the current scope. Used like this: 540 // auto on_scope_leave = OnScopeLeave([&] { 541 // // ... run some code ... 542 // }); 543 template
544 inline MUST_USE_RESULT OnScopeLeaveImpl
OnScopeLeave(Fn&& fn) { 545 return OnScopeLeaveImpl
{std::move(fn)}; 546 } 547 548 // Simple RAII wrapper for contiguous data that uses malloc()/free(). 549 template
550 struct MallocedBuffer { 551 T* data; 552 size_t size; 553 554 T* release() { 555 T* ret = data; 556 data = nullptr; 557 return ret; 558 } 559 560 void Truncate(size_t new_size) { 561 CHECK(new_size <= size); 562 size = new_size; 563 } 564 565 inline bool is_empty() const { return data == nullptr; } 566 567 MallocedBuffer() : data(nullptr), size(0) {} 568 explicit MallocedBuffer(size_t size) : data(Malloc
(size)), size(size) {} 569 MallocedBuffer(T* data, size_t size) : data(data), size(size) {} 570 MallocedBuffer(MallocedBuffer&& other) : data(other.data), size(other.size) { 571 other.data = nullptr; 572 } 573 MallocedBuffer& operator=(MallocedBuffer&& other) { 574 this->~MallocedBuffer(); 575 return *new(this) MallocedBuffer(std::move(other)); 576 } 577 ~MallocedBuffer() { 578 free(data); 579 } 580 MallocedBuffer(const MallocedBuffer&) = delete; 581 MallocedBuffer& operator=(const MallocedBuffer&) = delete; 582 }; 583 584 template
585 class NonCopyableMaybe { 586 public: 587 NonCopyableMaybe() : empty_(true) {} 588 explicit NonCopyableMaybe(T&& value) 589 : empty_(false), 590 value_(std::move(value)) {} 591 592 bool IsEmpty() const { 593 return empty_; 594 } 595 596 T&& Release() { 597 CHECK_EQ(empty_, false); 598 empty_ = true; 599 return std::move(value_); 600 } 601 602 private: 603 bool empty_; 604 T value_; 605 }; 606 607 // Test whether some value can be called with (). 608 template
609 struct is_callable : std::is_function
{ }; 610 611 template
612 struct is_callable
::value 614 >::type> : std::true_type { }; 615 616 template
617 struct FunctionDeleter { 618 void operator()(T* pointer) const { function(pointer); } 619 typedef std::unique_ptr
Pointer; 620 }; 621 622 template
623 using DeleteFnPtr = typename FunctionDeleter
::Pointer; 624 625 std::vector
SplitString(const std::string& in, char delim); 626 627 inline v8::MaybeLocal
ToV8Value(v8::Local
context, 628 const std::string& str, 629 v8::Isolate* isolate = nullptr); 630 template
::is_specialized, bool>::type> 632 inline v8::MaybeLocal
ToV8Value(v8::Local
context, 633 const T& number, 634 v8::Isolate* isolate = nullptr); 635 template
636 inline v8::MaybeLocal
ToV8Value(v8::Local
context, 637 const std::vector
& vec, 638 v8::Isolate* isolate = nullptr); 639 template
640 inline v8::MaybeLocal
ToV8Value(v8::Local
context, 641 const std::unordered_map
& map, 642 v8::Isolate* isolate = nullptr); 643 644 // These macros expects a `Isolate* isolate` and a `Local
context` 645 // to be in the scope. 646 #define READONLY_PROPERTY(obj, name, value) \ 647 do { \ 648 obj->DefineOwnProperty( \ 649 context, FIXED_ONE_BYTE_STRING(isolate, name), value, v8::ReadOnly) \ 650 .Check(); \ 651 } while (0) 652 653 #define READONLY_DONT_ENUM_PROPERTY(obj, name, var) \ 654 do { \ 655 obj->DefineOwnProperty( \ 656 context, \ 657 OneByteString(isolate, name), \ 658 var, \ 659 static_cast
(v8::ReadOnly | v8::DontEnum)) \ 660 .Check(); \ 661 } while (0) 662 663 #define READONLY_FALSE_PROPERTY(obj, name) \ 664 READONLY_PROPERTY(obj, name, v8::False(isolate)) 665 666 #define READONLY_TRUE_PROPERTY(obj, name) \ 667 READONLY_PROPERTY(obj, name, v8::True(isolate)) 668 669 #define READONLY_STRING_PROPERTY(obj, name, str) \ 670 READONLY_PROPERTY(obj, name, ToV8Value(context, str).ToLocalChecked()) 671 672 // Variation on NODE_DEFINE_CONSTANT that sets a String value. 673 #define NODE_DEFINE_STRING_CONSTANT(target, name, constant) \ 674 do { \ 675 v8::Isolate* isolate = target->GetIsolate(); \ 676 v8::Local
constant_name = \ 677 v8::String::NewFromUtf8(isolate, name, v8::NewStringType::kNormal) \ 678 .ToLocalChecked(); \ 679 v8::Local
constant_value = \ 680 v8::String::NewFromUtf8(isolate, constant, v8::NewStringType::kNormal) \ 681 .ToLocalChecked(); \ 682 v8::PropertyAttribute constant_attributes = \ 683 static_cast
(v8::ReadOnly | v8::DontDelete); \ 684 target \ 685 ->DefineOwnProperty(isolate->GetCurrentContext(), \ 686 constant_name, \ 687 constant_value, \ 688 constant_attributes) \ 689 .Check(); \ 690 } while (0) 691 692 enum Endianness { 693 kLittleEndian, // _Not_ LITTLE_ENDIAN, clashes with endian.h. 694 kBigEndian 695 }; 696 697 inline enum Endianness GetEndianness() { 698 // Constant-folded by the compiler. 699 const union { 700 uint8_t u8[2]; 701 uint16_t u16; 702 } u = {{1, 0}}; 703 return u.u16 == 1 ? kLittleEndian : kBigEndian; 704 } 705 706 inline bool IsLittleEndian() { 707 return GetEndianness() == kLittleEndian; 708 } 709 710 inline bool IsBigEndian() { 711 return GetEndianness() == kBigEndian; 712 } 713 714 // Round up a to the next highest multiple of b. 715 template
716 constexpr T RoundUp(T a, T b) { 717 return a % b != 0 ? a + b - (a % b) : a; 718 } 719 720 class SlicedArguments : public MaybeStackBuffer
> { 721 public: 722 inline explicit SlicedArguments( 723 const v8::FunctionCallbackInfo
& args, size_t start = 0); 724 }; 725 726 // Convert a v8::PersistentBase, e.g. v8::Global, to a Local, with an extra 727 // optimization for strong persistent handles. 728 class PersistentToLocal { 729 public: 730 // If persistent.IsWeak() == false, then do not call persistent.Reset() 731 // while the returned Local
is still in scope, it will destroy the 732 // reference to the object. 733 template
734 static inline v8::Local
Default( 735 v8::Isolate* isolate, 736 const v8::PersistentBase
& persistent) { 737 if (persistent.IsWeak()) { 738 return PersistentToLocal::Weak(isolate, persistent); 739 } else { 740 return PersistentToLocal::Strong(persistent); 741 } 742 } 743 744 // Unchecked conversion from a non-weak Persistent
to Local
, 745 // use with care! 746 // 747 // Do not call persistent.Reset() while the returned Local
is still in 748 // scope, it will destroy the reference to the object. 749 template
750 static inline v8::Local
Strong( 751 const v8::PersistentBase
& persistent) { 752 return *reinterpret_cast
*>( 753 const_cast
*>(&persistent)); 754 } 755 756 template
757 static inline v8::Local
Weak( 758 v8::Isolate* isolate, 759 const v8::PersistentBase
& persistent) { 760 return v8::Local
::New(isolate, persistent); 761 } 762 }; 763 764 // Like std::static_pointer_cast but for unique_ptr with the default deleter. 765 template
766 std::unique_ptr
static_unique_pointer_cast(std::unique_ptr
&& ptr) { 767 return std::unique_ptr
(static_cast
(ptr.release())); 768 } 769 770 } // namespace node 771 772 #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS 773 774 #endif // SRC_UTIL_H_
Contact us
|
About us
|
Term of use
|
Copyright © 2000-2024 MyWebUniversity.com ™