11cb0ef41Sopenharmony_ci// Copyright Joyent, Inc. and other Node contributors. 21cb0ef41Sopenharmony_ci// 31cb0ef41Sopenharmony_ci// Permission is hereby granted, free of charge, to any person obtaining a 41cb0ef41Sopenharmony_ci// copy of this software and associated documentation files (the 51cb0ef41Sopenharmony_ci// "Software"), to deal in the Software without restriction, including 61cb0ef41Sopenharmony_ci// without limitation the rights to use, copy, modify, merge, publish, 71cb0ef41Sopenharmony_ci// distribute, sublicense, and/or sell copies of the Software, and to permit 81cb0ef41Sopenharmony_ci// persons to whom the Software is furnished to do so, subject to the 91cb0ef41Sopenharmony_ci// following conditions: 101cb0ef41Sopenharmony_ci// 111cb0ef41Sopenharmony_ci// The above copyright notice and this permission notice shall be included 121cb0ef41Sopenharmony_ci// in all copies or substantial portions of the Software. 131cb0ef41Sopenharmony_ci// 141cb0ef41Sopenharmony_ci// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 151cb0ef41Sopenharmony_ci// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 161cb0ef41Sopenharmony_ci// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 171cb0ef41Sopenharmony_ci// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 181cb0ef41Sopenharmony_ci// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 191cb0ef41Sopenharmony_ci// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 201cb0ef41Sopenharmony_ci// USE OR OTHER DEALINGS IN THE SOFTWARE. 211cb0ef41Sopenharmony_ci 221cb0ef41Sopenharmony_ci#ifndef SRC_UTIL_H_ 231cb0ef41Sopenharmony_ci#define SRC_UTIL_H_ 241cb0ef41Sopenharmony_ci 251cb0ef41Sopenharmony_ci#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS 261cb0ef41Sopenharmony_ci 271cb0ef41Sopenharmony_ci#include "v8.h" 281cb0ef41Sopenharmony_ci 291cb0ef41Sopenharmony_ci#include "node.h" 301cb0ef41Sopenharmony_ci 311cb0ef41Sopenharmony_ci#include <climits> 321cb0ef41Sopenharmony_ci#include <cstddef> 331cb0ef41Sopenharmony_ci#include <cstdio> 341cb0ef41Sopenharmony_ci#include <cstdlib> 351cb0ef41Sopenharmony_ci#include <cstring> 361cb0ef41Sopenharmony_ci 371cb0ef41Sopenharmony_ci#include <array> 381cb0ef41Sopenharmony_ci#include <limits> 391cb0ef41Sopenharmony_ci#include <memory> 401cb0ef41Sopenharmony_ci#include <set> 411cb0ef41Sopenharmony_ci#include <string> 421cb0ef41Sopenharmony_ci#include <string_view> 431cb0ef41Sopenharmony_ci#include <type_traits> 441cb0ef41Sopenharmony_ci#include <unordered_map> 451cb0ef41Sopenharmony_ci#include <utility> 461cb0ef41Sopenharmony_ci#include <vector> 471cb0ef41Sopenharmony_ci 481cb0ef41Sopenharmony_ci#ifdef __GNUC__ 491cb0ef41Sopenharmony_ci#define MUST_USE_RESULT __attribute__((warn_unused_result)) 501cb0ef41Sopenharmony_ci#else 511cb0ef41Sopenharmony_ci#define MUST_USE_RESULT 521cb0ef41Sopenharmony_ci#endif 531cb0ef41Sopenharmony_ci 541cb0ef41Sopenharmony_cinamespace node { 551cb0ef41Sopenharmony_ci 561cb0ef41Sopenharmony_cibool ReadSystemXpmState(); 571cb0ef41Sopenharmony_ci 581cb0ef41Sopenharmony_ci// Maybe remove kPathSeparator when cpp17 is ready 591cb0ef41Sopenharmony_ci#ifdef _WIN32 601cb0ef41Sopenharmony_ci constexpr char kPathSeparator = '\\'; 611cb0ef41Sopenharmony_ci/* MAX_PATH is in characters, not bytes. Make sure we have enough headroom. */ 621cb0ef41Sopenharmony_ci#define PATH_MAX_BYTES (MAX_PATH * 4) 631cb0ef41Sopenharmony_ci#else 641cb0ef41Sopenharmony_ci constexpr char kPathSeparator = '/'; 651cb0ef41Sopenharmony_ci#define PATH_MAX_BYTES (PATH_MAX) 661cb0ef41Sopenharmony_ci#endif 671cb0ef41Sopenharmony_ci 681cb0ef41Sopenharmony_ci// These should be used in our code as opposed to the native 691cb0ef41Sopenharmony_ci// versions as they abstract out some platform and or 701cb0ef41Sopenharmony_ci// compiler version specific functionality 711cb0ef41Sopenharmony_ci// malloc(0) and realloc(ptr, 0) have implementation-defined behavior in 721cb0ef41Sopenharmony_ci// that the standard allows them to either return a unique pointer or a 731cb0ef41Sopenharmony_ci// nullptr for zero-sized allocation requests. Normalize by always using 741cb0ef41Sopenharmony_ci// a nullptr. 751cb0ef41Sopenharmony_citemplate <typename T> 761cb0ef41Sopenharmony_ciinline T* UncheckedRealloc(T* pointer, size_t n); 771cb0ef41Sopenharmony_citemplate <typename T> 781cb0ef41Sopenharmony_ciinline T* UncheckedMalloc(size_t n); 791cb0ef41Sopenharmony_citemplate <typename T> 801cb0ef41Sopenharmony_ciinline T* UncheckedCalloc(size_t n); 811cb0ef41Sopenharmony_ci 821cb0ef41Sopenharmony_ci// Same things, but aborts immediately instead of returning nullptr when 831cb0ef41Sopenharmony_ci// no memory is available. 841cb0ef41Sopenharmony_citemplate <typename T> 851cb0ef41Sopenharmony_ciinline T* Realloc(T* pointer, size_t n); 861cb0ef41Sopenharmony_citemplate <typename T> 871cb0ef41Sopenharmony_ciinline T* Malloc(size_t n); 881cb0ef41Sopenharmony_citemplate <typename T> 891cb0ef41Sopenharmony_ciinline T* Calloc(size_t n); 901cb0ef41Sopenharmony_ci 911cb0ef41Sopenharmony_ciinline char* Malloc(size_t n); 921cb0ef41Sopenharmony_ciinline char* Calloc(size_t n); 931cb0ef41Sopenharmony_ciinline char* UncheckedMalloc(size_t n); 941cb0ef41Sopenharmony_ciinline char* UncheckedCalloc(size_t n); 951cb0ef41Sopenharmony_ci 961cb0ef41Sopenharmony_citemplate <typename T> 971cb0ef41Sopenharmony_ciinline T MultiplyWithOverflowCheck(T a, T b); 981cb0ef41Sopenharmony_ci 991cb0ef41Sopenharmony_cinamespace per_process { 1001cb0ef41Sopenharmony_ci// Tells whether the per-process V8::Initialize() is called and 1011cb0ef41Sopenharmony_ci// if it is safe to call v8::Isolate::TryGetCurrent(). 1021cb0ef41Sopenharmony_ciextern bool v8_initialized; 1031cb0ef41Sopenharmony_ci} // namespace per_process 1041cb0ef41Sopenharmony_ci 1051cb0ef41Sopenharmony_ci// Used by the allocation functions when allocation fails. 1061cb0ef41Sopenharmony_ci// Thin wrapper around v8::Isolate::LowMemoryNotification() that checks 1071cb0ef41Sopenharmony_ci// whether V8 is initialized. 1081cb0ef41Sopenharmony_civoid LowMemoryNotification(); 1091cb0ef41Sopenharmony_ci 1101cb0ef41Sopenharmony_ci// The reason that Assert() takes a struct argument instead of individual 1111cb0ef41Sopenharmony_ci// const char*s is to ease instruction cache pressure in calls from CHECK. 1121cb0ef41Sopenharmony_cistruct AssertionInfo { 1131cb0ef41Sopenharmony_ci const char* file_line; // filename:line 1141cb0ef41Sopenharmony_ci const char* message; 1151cb0ef41Sopenharmony_ci const char* function; 1161cb0ef41Sopenharmony_ci}; 1171cb0ef41Sopenharmony_ci[[noreturn]] void NODE_EXTERN_PRIVATE Assert(const AssertionInfo& info); 1181cb0ef41Sopenharmony_ci[[noreturn]] void NODE_EXTERN_PRIVATE Abort(); 1191cb0ef41Sopenharmony_civoid DumpBacktrace(FILE* fp); 1201cb0ef41Sopenharmony_ci 1211cb0ef41Sopenharmony_ci// Windows 8+ does not like abort() in Release mode 1221cb0ef41Sopenharmony_ci#ifdef _WIN32 1231cb0ef41Sopenharmony_ci#define ABORT_NO_BACKTRACE() _exit(134) 1241cb0ef41Sopenharmony_ci#else 1251cb0ef41Sopenharmony_ci#define ABORT_NO_BACKTRACE() abort() 1261cb0ef41Sopenharmony_ci#endif 1271cb0ef41Sopenharmony_ci 1281cb0ef41Sopenharmony_ci#define ABORT() node::Abort() 1291cb0ef41Sopenharmony_ci 1301cb0ef41Sopenharmony_ci#define ERROR_AND_ABORT(expr) \ 1311cb0ef41Sopenharmony_ci do { \ 1321cb0ef41Sopenharmony_ci /* Make sure that this struct does not end up in inline code, but */ \ 1331cb0ef41Sopenharmony_ci /* rather in a read-only data section when modifying this code. */ \ 1341cb0ef41Sopenharmony_ci static const node::AssertionInfo args = { \ 1351cb0ef41Sopenharmony_ci __FILE__ ":" STRINGIFY(__LINE__), #expr, PRETTY_FUNCTION_NAME \ 1361cb0ef41Sopenharmony_ci }; \ 1371cb0ef41Sopenharmony_ci node::Assert(args); \ 1381cb0ef41Sopenharmony_ci } while (0) 1391cb0ef41Sopenharmony_ci 1401cb0ef41Sopenharmony_ci#ifdef __GNUC__ 1411cb0ef41Sopenharmony_ci#define LIKELY(expr) __builtin_expect(!!(expr), 1) 1421cb0ef41Sopenharmony_ci#define UNLIKELY(expr) __builtin_expect(!!(expr), 0) 1431cb0ef41Sopenharmony_ci#define PRETTY_FUNCTION_NAME __PRETTY_FUNCTION__ 1441cb0ef41Sopenharmony_ci#else 1451cb0ef41Sopenharmony_ci#define LIKELY(expr) expr 1461cb0ef41Sopenharmony_ci#define UNLIKELY(expr) expr 1471cb0ef41Sopenharmony_ci#define PRETTY_FUNCTION_NAME "" 1481cb0ef41Sopenharmony_ci#endif 1491cb0ef41Sopenharmony_ci 1501cb0ef41Sopenharmony_ci#define STRINGIFY_(x) #x 1511cb0ef41Sopenharmony_ci#define STRINGIFY(x) STRINGIFY_(x) 1521cb0ef41Sopenharmony_ci 1531cb0ef41Sopenharmony_ci#define CHECK(expr) \ 1541cb0ef41Sopenharmony_ci do { \ 1551cb0ef41Sopenharmony_ci if (UNLIKELY(!(expr))) { \ 1561cb0ef41Sopenharmony_ci ERROR_AND_ABORT(expr); \ 1571cb0ef41Sopenharmony_ci } \ 1581cb0ef41Sopenharmony_ci } while (0) 1591cb0ef41Sopenharmony_ci 1601cb0ef41Sopenharmony_ci#define CHECK_EQ(a, b) CHECK((a) == (b)) 1611cb0ef41Sopenharmony_ci#define CHECK_GE(a, b) CHECK((a) >= (b)) 1621cb0ef41Sopenharmony_ci#define CHECK_GT(a, b) CHECK((a) > (b)) 1631cb0ef41Sopenharmony_ci#define CHECK_LE(a, b) CHECK((a) <= (b)) 1641cb0ef41Sopenharmony_ci#define CHECK_LT(a, b) CHECK((a) < (b)) 1651cb0ef41Sopenharmony_ci#define CHECK_NE(a, b) CHECK((a) != (b)) 1661cb0ef41Sopenharmony_ci#define CHECK_NULL(val) CHECK((val) == nullptr) 1671cb0ef41Sopenharmony_ci#define CHECK_NOT_NULL(val) CHECK((val) != nullptr) 1681cb0ef41Sopenharmony_ci#define CHECK_IMPLIES(a, b) CHECK(!(a) || (b)) 1691cb0ef41Sopenharmony_ci 1701cb0ef41Sopenharmony_ci#ifdef DEBUG 1711cb0ef41Sopenharmony_ci #define DCHECK(expr) CHECK(expr) 1721cb0ef41Sopenharmony_ci #define DCHECK_EQ(a, b) CHECK((a) == (b)) 1731cb0ef41Sopenharmony_ci #define DCHECK_GE(a, b) CHECK((a) >= (b)) 1741cb0ef41Sopenharmony_ci #define DCHECK_GT(a, b) CHECK((a) > (b)) 1751cb0ef41Sopenharmony_ci #define DCHECK_LE(a, b) CHECK((a) <= (b)) 1761cb0ef41Sopenharmony_ci #define DCHECK_LT(a, b) CHECK((a) < (b)) 1771cb0ef41Sopenharmony_ci #define DCHECK_NE(a, b) CHECK((a) != (b)) 1781cb0ef41Sopenharmony_ci #define DCHECK_NULL(val) CHECK((val) == nullptr) 1791cb0ef41Sopenharmony_ci #define DCHECK_NOT_NULL(val) CHECK((val) != nullptr) 1801cb0ef41Sopenharmony_ci #define DCHECK_IMPLIES(a, b) CHECK(!(a) || (b)) 1811cb0ef41Sopenharmony_ci#else 1821cb0ef41Sopenharmony_ci #define DCHECK(expr) 1831cb0ef41Sopenharmony_ci #define DCHECK_EQ(a, b) 1841cb0ef41Sopenharmony_ci #define DCHECK_GE(a, b) 1851cb0ef41Sopenharmony_ci #define DCHECK_GT(a, b) 1861cb0ef41Sopenharmony_ci #define DCHECK_LE(a, b) 1871cb0ef41Sopenharmony_ci #define DCHECK_LT(a, b) 1881cb0ef41Sopenharmony_ci #define DCHECK_NE(a, b) 1891cb0ef41Sopenharmony_ci #define DCHECK_NULL(val) 1901cb0ef41Sopenharmony_ci #define DCHECK_NOT_NULL(val) 1911cb0ef41Sopenharmony_ci #define DCHECK_IMPLIES(a, b) 1921cb0ef41Sopenharmony_ci#endif 1931cb0ef41Sopenharmony_ci 1941cb0ef41Sopenharmony_ci 1951cb0ef41Sopenharmony_ci#define UNREACHABLE(...) \ 1961cb0ef41Sopenharmony_ci ERROR_AND_ABORT("Unreachable code reached" __VA_OPT__(": ") __VA_ARGS__) 1971cb0ef41Sopenharmony_ci 1981cb0ef41Sopenharmony_ci// ECMA262 20.1.2.6 Number.MAX_SAFE_INTEGER (2^53-1) 1991cb0ef41Sopenharmony_ciconstexpr int64_t kMaxSafeJsInteger = 9007199254740991; 2001cb0ef41Sopenharmony_ci 2011cb0ef41Sopenharmony_ciinline bool IsSafeJsInt(v8::Local<v8::Value> v); 2021cb0ef41Sopenharmony_ci 2031cb0ef41Sopenharmony_ci// TAILQ-style intrusive list node. 2041cb0ef41Sopenharmony_citemplate <typename T> 2051cb0ef41Sopenharmony_ciclass ListNode; 2061cb0ef41Sopenharmony_ci 2071cb0ef41Sopenharmony_ci// TAILQ-style intrusive list head. 2081cb0ef41Sopenharmony_citemplate <typename T, ListNode<T> (T::*M)> 2091cb0ef41Sopenharmony_ciclass ListHead; 2101cb0ef41Sopenharmony_ci 2111cb0ef41Sopenharmony_citemplate <typename T> 2121cb0ef41Sopenharmony_ciclass ListNode { 2131cb0ef41Sopenharmony_ci public: 2141cb0ef41Sopenharmony_ci inline ListNode(); 2151cb0ef41Sopenharmony_ci inline ~ListNode(); 2161cb0ef41Sopenharmony_ci inline void Remove(); 2171cb0ef41Sopenharmony_ci inline bool IsEmpty() const; 2181cb0ef41Sopenharmony_ci 2191cb0ef41Sopenharmony_ci ListNode(const ListNode&) = delete; 2201cb0ef41Sopenharmony_ci ListNode& operator=(const ListNode&) = delete; 2211cb0ef41Sopenharmony_ci 2221cb0ef41Sopenharmony_ci private: 2231cb0ef41Sopenharmony_ci template <typename U, ListNode<U> (U::*M)> friend class ListHead; 2241cb0ef41Sopenharmony_ci friend int GenDebugSymbols(); 2251cb0ef41Sopenharmony_ci ListNode* prev_; 2261cb0ef41Sopenharmony_ci ListNode* next_; 2271cb0ef41Sopenharmony_ci}; 2281cb0ef41Sopenharmony_ci 2291cb0ef41Sopenharmony_citemplate <typename T, ListNode<T> (T::*M)> 2301cb0ef41Sopenharmony_ciclass ListHead { 2311cb0ef41Sopenharmony_ci public: 2321cb0ef41Sopenharmony_ci class Iterator { 2331cb0ef41Sopenharmony_ci public: 2341cb0ef41Sopenharmony_ci inline T* operator*() const; 2351cb0ef41Sopenharmony_ci inline const Iterator& operator++(); 2361cb0ef41Sopenharmony_ci inline bool operator!=(const Iterator& that) const; 2371cb0ef41Sopenharmony_ci 2381cb0ef41Sopenharmony_ci private: 2391cb0ef41Sopenharmony_ci friend class ListHead; 2401cb0ef41Sopenharmony_ci inline explicit Iterator(ListNode<T>* node); 2411cb0ef41Sopenharmony_ci ListNode<T>* node_; 2421cb0ef41Sopenharmony_ci }; 2431cb0ef41Sopenharmony_ci 2441cb0ef41Sopenharmony_ci inline ListHead() = default; 2451cb0ef41Sopenharmony_ci inline ~ListHead(); 2461cb0ef41Sopenharmony_ci inline void PushBack(T* element); 2471cb0ef41Sopenharmony_ci inline void PushFront(T* element); 2481cb0ef41Sopenharmony_ci inline bool IsEmpty() const; 2491cb0ef41Sopenharmony_ci inline T* PopFront(); 2501cb0ef41Sopenharmony_ci inline Iterator begin() const; 2511cb0ef41Sopenharmony_ci inline Iterator end() const; 2521cb0ef41Sopenharmony_ci 2531cb0ef41Sopenharmony_ci ListHead(const ListHead&) = delete; 2541cb0ef41Sopenharmony_ci ListHead& operator=(const ListHead&) = delete; 2551cb0ef41Sopenharmony_ci 2561cb0ef41Sopenharmony_ci private: 2571cb0ef41Sopenharmony_ci friend int GenDebugSymbols(); 2581cb0ef41Sopenharmony_ci ListNode<T> head_; 2591cb0ef41Sopenharmony_ci}; 2601cb0ef41Sopenharmony_ci 2611cb0ef41Sopenharmony_ci// The helper is for doing safe downcasts from base types to derived types. 2621cb0ef41Sopenharmony_citemplate <typename Inner, typename Outer> 2631cb0ef41Sopenharmony_ciclass ContainerOfHelper { 2641cb0ef41Sopenharmony_ci public: 2651cb0ef41Sopenharmony_ci inline ContainerOfHelper(Inner Outer::*field, Inner* pointer); 2661cb0ef41Sopenharmony_ci template <typename TypeName> 2671cb0ef41Sopenharmony_ci inline operator TypeName*() const; 2681cb0ef41Sopenharmony_ci private: 2691cb0ef41Sopenharmony_ci Outer* const pointer_; 2701cb0ef41Sopenharmony_ci}; 2711cb0ef41Sopenharmony_ci 2721cb0ef41Sopenharmony_ci// Calculate the address of the outer (i.e. embedding) struct from 2731cb0ef41Sopenharmony_ci// the interior pointer to a data member. 2741cb0ef41Sopenharmony_citemplate <typename Inner, typename Outer> 2751cb0ef41Sopenharmony_ciconstexpr ContainerOfHelper<Inner, Outer> ContainerOf(Inner Outer::*field, 2761cb0ef41Sopenharmony_ci Inner* pointer); 2771cb0ef41Sopenharmony_ci 2781cb0ef41Sopenharmony_ciclass KVStore { 2791cb0ef41Sopenharmony_ci public: 2801cb0ef41Sopenharmony_ci KVStore() = default; 2811cb0ef41Sopenharmony_ci virtual ~KVStore() = default; 2821cb0ef41Sopenharmony_ci KVStore(const KVStore&) = delete; 2831cb0ef41Sopenharmony_ci KVStore& operator=(const KVStore&) = delete; 2841cb0ef41Sopenharmony_ci KVStore(KVStore&&) = delete; 2851cb0ef41Sopenharmony_ci KVStore& operator=(KVStore&&) = delete; 2861cb0ef41Sopenharmony_ci 2871cb0ef41Sopenharmony_ci virtual v8::MaybeLocal<v8::String> Get(v8::Isolate* isolate, 2881cb0ef41Sopenharmony_ci v8::Local<v8::String> key) const = 0; 2891cb0ef41Sopenharmony_ci virtual v8::Maybe<std::string> Get(const char* key) const = 0; 2901cb0ef41Sopenharmony_ci virtual void Set(v8::Isolate* isolate, 2911cb0ef41Sopenharmony_ci v8::Local<v8::String> key, 2921cb0ef41Sopenharmony_ci v8::Local<v8::String> value) = 0; 2931cb0ef41Sopenharmony_ci virtual int32_t Query(v8::Isolate* isolate, 2941cb0ef41Sopenharmony_ci v8::Local<v8::String> key) const = 0; 2951cb0ef41Sopenharmony_ci virtual int32_t Query(const char* key) const = 0; 2961cb0ef41Sopenharmony_ci virtual void Delete(v8::Isolate* isolate, v8::Local<v8::String> key) = 0; 2971cb0ef41Sopenharmony_ci virtual v8::Local<v8::Array> Enumerate(v8::Isolate* isolate) const = 0; 2981cb0ef41Sopenharmony_ci 2991cb0ef41Sopenharmony_ci virtual std::shared_ptr<KVStore> Clone(v8::Isolate* isolate) const; 3001cb0ef41Sopenharmony_ci virtual v8::Maybe<bool> AssignFromObject(v8::Local<v8::Context> context, 3011cb0ef41Sopenharmony_ci v8::Local<v8::Object> entries); 3021cb0ef41Sopenharmony_ci v8::Maybe<bool> AssignToObject(v8::Isolate* isolate, 3031cb0ef41Sopenharmony_ci v8::Local<v8::Context> context, 3041cb0ef41Sopenharmony_ci v8::Local<v8::Object> object); 3051cb0ef41Sopenharmony_ci 3061cb0ef41Sopenharmony_ci static std::shared_ptr<KVStore> CreateMapKVStore(); 3071cb0ef41Sopenharmony_ci}; 3081cb0ef41Sopenharmony_ci 3091cb0ef41Sopenharmony_ci// Convenience wrapper around v8::String::NewFromOneByte(). 3101cb0ef41Sopenharmony_ciinline v8::Local<v8::String> OneByteString(v8::Isolate* isolate, 3111cb0ef41Sopenharmony_ci const char* data, 3121cb0ef41Sopenharmony_ci int length = -1); 3131cb0ef41Sopenharmony_ci 3141cb0ef41Sopenharmony_ci// For the people that compile with -funsigned-char. 3151cb0ef41Sopenharmony_ciinline v8::Local<v8::String> OneByteString(v8::Isolate* isolate, 3161cb0ef41Sopenharmony_ci const signed char* data, 3171cb0ef41Sopenharmony_ci int length = -1); 3181cb0ef41Sopenharmony_ci 3191cb0ef41Sopenharmony_ciinline v8::Local<v8::String> OneByteString(v8::Isolate* isolate, 3201cb0ef41Sopenharmony_ci const unsigned char* data, 3211cb0ef41Sopenharmony_ci int length = -1); 3221cb0ef41Sopenharmony_ci 3231cb0ef41Sopenharmony_ci// Used to be a macro, hence the uppercase name. 3241cb0ef41Sopenharmony_citemplate <int N> 3251cb0ef41Sopenharmony_ciinline v8::Local<v8::String> FIXED_ONE_BYTE_STRING( 3261cb0ef41Sopenharmony_ci v8::Isolate* isolate, 3271cb0ef41Sopenharmony_ci const char(&data)[N]) { 3281cb0ef41Sopenharmony_ci return OneByteString(isolate, data, N - 1); 3291cb0ef41Sopenharmony_ci} 3301cb0ef41Sopenharmony_ci 3311cb0ef41Sopenharmony_citemplate <std::size_t N> 3321cb0ef41Sopenharmony_ciinline v8::Local<v8::String> FIXED_ONE_BYTE_STRING( 3331cb0ef41Sopenharmony_ci v8::Isolate* isolate, 3341cb0ef41Sopenharmony_ci const std::array<char, N>& arr) { 3351cb0ef41Sopenharmony_ci return OneByteString(isolate, arr.data(), N - 1); 3361cb0ef41Sopenharmony_ci} 3371cb0ef41Sopenharmony_ci 3381cb0ef41Sopenharmony_ci 3391cb0ef41Sopenharmony_ci 3401cb0ef41Sopenharmony_ci// Swaps bytes in place. nbytes is the number of bytes to swap and must be a 3411cb0ef41Sopenharmony_ci// multiple of the word size (checked by function). 3421cb0ef41Sopenharmony_ciinline void SwapBytes16(char* data, size_t nbytes); 3431cb0ef41Sopenharmony_ciinline void SwapBytes32(char* data, size_t nbytes); 3441cb0ef41Sopenharmony_ciinline void SwapBytes64(char* data, size_t nbytes); 3451cb0ef41Sopenharmony_ci 3461cb0ef41Sopenharmony_ci// tolower() is locale-sensitive. Use ToLower() instead. 3471cb0ef41Sopenharmony_ciinline char ToLower(char c); 3481cb0ef41Sopenharmony_ciinline std::string ToLower(const std::string& in); 3491cb0ef41Sopenharmony_ci 3501cb0ef41Sopenharmony_ci// toupper() is locale-sensitive. Use ToUpper() instead. 3511cb0ef41Sopenharmony_ciinline char ToUpper(char c); 3521cb0ef41Sopenharmony_ciinline std::string ToUpper(const std::string& in); 3531cb0ef41Sopenharmony_ci 3541cb0ef41Sopenharmony_ci// strcasecmp() is locale-sensitive. Use StringEqualNoCase() instead. 3551cb0ef41Sopenharmony_ciinline bool StringEqualNoCase(const char* a, const char* b); 3561cb0ef41Sopenharmony_ci 3571cb0ef41Sopenharmony_ci// strncasecmp() is locale-sensitive. Use StringEqualNoCaseN() instead. 3581cb0ef41Sopenharmony_ciinline bool StringEqualNoCaseN(const char* a, const char* b, size_t length); 3591cb0ef41Sopenharmony_ci 3601cb0ef41Sopenharmony_citemplate <typename T, size_t N> 3611cb0ef41Sopenharmony_ciconstexpr size_t arraysize(const T (&)[N]) { 3621cb0ef41Sopenharmony_ci return N; 3631cb0ef41Sopenharmony_ci} 3641cb0ef41Sopenharmony_ci 3651cb0ef41Sopenharmony_citemplate <typename T, size_t N> 3661cb0ef41Sopenharmony_ciconstexpr size_t strsize(const T (&)[N]) { 3671cb0ef41Sopenharmony_ci return N - 1; 3681cb0ef41Sopenharmony_ci} 3691cb0ef41Sopenharmony_ci 3701cb0ef41Sopenharmony_ci// Allocates an array of member type T. For up to kStackStorageSize items, 3711cb0ef41Sopenharmony_ci// the stack is used, otherwise malloc(). 3721cb0ef41Sopenharmony_citemplate <typename T, size_t kStackStorageSize = 1024> 3731cb0ef41Sopenharmony_ciclass MaybeStackBuffer { 3741cb0ef41Sopenharmony_ci public: 3751cb0ef41Sopenharmony_ci const T* out() const { 3761cb0ef41Sopenharmony_ci return buf_; 3771cb0ef41Sopenharmony_ci } 3781cb0ef41Sopenharmony_ci 3791cb0ef41Sopenharmony_ci T* out() { 3801cb0ef41Sopenharmony_ci return buf_; 3811cb0ef41Sopenharmony_ci } 3821cb0ef41Sopenharmony_ci 3831cb0ef41Sopenharmony_ci // operator* for compatibility with `v8::String::(Utf8)Value` 3841cb0ef41Sopenharmony_ci T* operator*() { 3851cb0ef41Sopenharmony_ci return buf_; 3861cb0ef41Sopenharmony_ci } 3871cb0ef41Sopenharmony_ci 3881cb0ef41Sopenharmony_ci const T* operator*() const { 3891cb0ef41Sopenharmony_ci return buf_; 3901cb0ef41Sopenharmony_ci } 3911cb0ef41Sopenharmony_ci 3921cb0ef41Sopenharmony_ci T& operator[](size_t index) { 3931cb0ef41Sopenharmony_ci CHECK_LT(index, length()); 3941cb0ef41Sopenharmony_ci return buf_[index]; 3951cb0ef41Sopenharmony_ci } 3961cb0ef41Sopenharmony_ci 3971cb0ef41Sopenharmony_ci const T& operator[](size_t index) const { 3981cb0ef41Sopenharmony_ci CHECK_LT(index, length()); 3991cb0ef41Sopenharmony_ci return buf_[index]; 4001cb0ef41Sopenharmony_ci } 4011cb0ef41Sopenharmony_ci 4021cb0ef41Sopenharmony_ci size_t length() const { 4031cb0ef41Sopenharmony_ci return length_; 4041cb0ef41Sopenharmony_ci } 4051cb0ef41Sopenharmony_ci 4061cb0ef41Sopenharmony_ci // Current maximum capacity of the buffer with which SetLength() can be used 4071cb0ef41Sopenharmony_ci // without first calling AllocateSufficientStorage(). 4081cb0ef41Sopenharmony_ci size_t capacity() const { 4091cb0ef41Sopenharmony_ci return capacity_; 4101cb0ef41Sopenharmony_ci } 4111cb0ef41Sopenharmony_ci 4121cb0ef41Sopenharmony_ci // Make sure enough space for `storage` entries is available. 4131cb0ef41Sopenharmony_ci // This method can be called multiple times throughout the lifetime of the 4141cb0ef41Sopenharmony_ci // buffer, but once this has been called Invalidate() cannot be used. 4151cb0ef41Sopenharmony_ci // Content of the buffer in the range [0, length()) is preserved. 4161cb0ef41Sopenharmony_ci void AllocateSufficientStorage(size_t storage); 4171cb0ef41Sopenharmony_ci 4181cb0ef41Sopenharmony_ci void SetLength(size_t length) { 4191cb0ef41Sopenharmony_ci // capacity() returns how much memory is actually available. 4201cb0ef41Sopenharmony_ci CHECK_LE(length, capacity()); 4211cb0ef41Sopenharmony_ci length_ = length; 4221cb0ef41Sopenharmony_ci } 4231cb0ef41Sopenharmony_ci 4241cb0ef41Sopenharmony_ci void SetLengthAndZeroTerminate(size_t length) { 4251cb0ef41Sopenharmony_ci // capacity() returns how much memory is actually available. 4261cb0ef41Sopenharmony_ci CHECK_LE(length + 1, capacity()); 4271cb0ef41Sopenharmony_ci SetLength(length); 4281cb0ef41Sopenharmony_ci 4291cb0ef41Sopenharmony_ci // T() is 0 for integer types, nullptr for pointers, etc. 4301cb0ef41Sopenharmony_ci buf_[length] = T(); 4311cb0ef41Sopenharmony_ci } 4321cb0ef41Sopenharmony_ci 4331cb0ef41Sopenharmony_ci // Make dereferencing this object return nullptr. 4341cb0ef41Sopenharmony_ci // This method can be called multiple times throughout the lifetime of the 4351cb0ef41Sopenharmony_ci // buffer, but once this has been called AllocateSufficientStorage() cannot 4361cb0ef41Sopenharmony_ci // be used. 4371cb0ef41Sopenharmony_ci void Invalidate() { 4381cb0ef41Sopenharmony_ci CHECK(!IsAllocated()); 4391cb0ef41Sopenharmony_ci capacity_ = 0; 4401cb0ef41Sopenharmony_ci length_ = 0; 4411cb0ef41Sopenharmony_ci buf_ = nullptr; 4421cb0ef41Sopenharmony_ci } 4431cb0ef41Sopenharmony_ci 4441cb0ef41Sopenharmony_ci // If the buffer is stored in the heap rather than on the stack. 4451cb0ef41Sopenharmony_ci bool IsAllocated() const { 4461cb0ef41Sopenharmony_ci return !IsInvalidated() && buf_ != buf_st_; 4471cb0ef41Sopenharmony_ci } 4481cb0ef41Sopenharmony_ci 4491cb0ef41Sopenharmony_ci // If Invalidate() has been called. 4501cb0ef41Sopenharmony_ci bool IsInvalidated() const { 4511cb0ef41Sopenharmony_ci return buf_ == nullptr; 4521cb0ef41Sopenharmony_ci } 4531cb0ef41Sopenharmony_ci 4541cb0ef41Sopenharmony_ci // Release ownership of the malloc'd buffer. 4551cb0ef41Sopenharmony_ci // Note: This does not free the buffer. 4561cb0ef41Sopenharmony_ci void Release() { 4571cb0ef41Sopenharmony_ci CHECK(IsAllocated()); 4581cb0ef41Sopenharmony_ci buf_ = buf_st_; 4591cb0ef41Sopenharmony_ci length_ = 0; 4601cb0ef41Sopenharmony_ci capacity_ = arraysize(buf_st_); 4611cb0ef41Sopenharmony_ci } 4621cb0ef41Sopenharmony_ci 4631cb0ef41Sopenharmony_ci MaybeStackBuffer() 4641cb0ef41Sopenharmony_ci : length_(0), capacity_(arraysize(buf_st_)), buf_(buf_st_) { 4651cb0ef41Sopenharmony_ci // Default to a zero-length, null-terminated buffer. 4661cb0ef41Sopenharmony_ci buf_[0] = T(); 4671cb0ef41Sopenharmony_ci } 4681cb0ef41Sopenharmony_ci 4691cb0ef41Sopenharmony_ci explicit MaybeStackBuffer(size_t storage) : MaybeStackBuffer() { 4701cb0ef41Sopenharmony_ci AllocateSufficientStorage(storage); 4711cb0ef41Sopenharmony_ci } 4721cb0ef41Sopenharmony_ci 4731cb0ef41Sopenharmony_ci ~MaybeStackBuffer() { 4741cb0ef41Sopenharmony_ci if (IsAllocated()) 4751cb0ef41Sopenharmony_ci free(buf_); 4761cb0ef41Sopenharmony_ci } 4771cb0ef41Sopenharmony_ci 4781cb0ef41Sopenharmony_ci inline std::basic_string<T> ToString() const { return {out(), length()}; } 4791cb0ef41Sopenharmony_ci inline std::basic_string_view<T> ToStringView() const { 4801cb0ef41Sopenharmony_ci return {out(), length()}; 4811cb0ef41Sopenharmony_ci } 4821cb0ef41Sopenharmony_ci 4831cb0ef41Sopenharmony_ci private: 4841cb0ef41Sopenharmony_ci size_t length_; 4851cb0ef41Sopenharmony_ci // capacity of the malloc'ed buf_ 4861cb0ef41Sopenharmony_ci size_t capacity_; 4871cb0ef41Sopenharmony_ci T* buf_; 4881cb0ef41Sopenharmony_ci T buf_st_[kStackStorageSize]; 4891cb0ef41Sopenharmony_ci}; 4901cb0ef41Sopenharmony_ci 4911cb0ef41Sopenharmony_ci// Provides access to an ArrayBufferView's storage, either the original, 4921cb0ef41Sopenharmony_ci// or for small data, a copy of it. This object's lifetime is bound to the 4931cb0ef41Sopenharmony_ci// original ArrayBufferView's lifetime. 4941cb0ef41Sopenharmony_citemplate <typename T, size_t kStackStorageSize = 64> 4951cb0ef41Sopenharmony_ciclass ArrayBufferViewContents { 4961cb0ef41Sopenharmony_ci public: 4971cb0ef41Sopenharmony_ci ArrayBufferViewContents() = default; 4981cb0ef41Sopenharmony_ci 4991cb0ef41Sopenharmony_ci ArrayBufferViewContents(const ArrayBufferViewContents&) = delete; 5001cb0ef41Sopenharmony_ci void operator=(const ArrayBufferViewContents&) = delete; 5011cb0ef41Sopenharmony_ci 5021cb0ef41Sopenharmony_ci explicit inline ArrayBufferViewContents(v8::Local<v8::Value> value); 5031cb0ef41Sopenharmony_ci explicit inline ArrayBufferViewContents(v8::Local<v8::Object> value); 5041cb0ef41Sopenharmony_ci explicit inline ArrayBufferViewContents(v8::Local<v8::ArrayBufferView> abv); 5051cb0ef41Sopenharmony_ci inline void Read(v8::Local<v8::ArrayBufferView> abv); 5061cb0ef41Sopenharmony_ci inline void ReadValue(v8::Local<v8::Value> buf); 5071cb0ef41Sopenharmony_ci 5081cb0ef41Sopenharmony_ci inline bool WasDetached() const { return was_detached_; } 5091cb0ef41Sopenharmony_ci inline const T* data() const { return data_; } 5101cb0ef41Sopenharmony_ci inline size_t length() const { return length_; } 5111cb0ef41Sopenharmony_ci 5121cb0ef41Sopenharmony_ci private: 5131cb0ef41Sopenharmony_ci // Declaring operator new and delete as deleted is not spec compliant. 5141cb0ef41Sopenharmony_ci // Therefore, declare them private instead to disable dynamic alloc. 5151cb0ef41Sopenharmony_ci void* operator new(size_t size); 5161cb0ef41Sopenharmony_ci void* operator new[](size_t size); 5171cb0ef41Sopenharmony_ci void operator delete(void*, size_t); 5181cb0ef41Sopenharmony_ci void operator delete[](void*, size_t); 5191cb0ef41Sopenharmony_ci 5201cb0ef41Sopenharmony_ci T stack_storage_[kStackStorageSize]; 5211cb0ef41Sopenharmony_ci T* data_ = nullptr; 5221cb0ef41Sopenharmony_ci size_t length_ = 0; 5231cb0ef41Sopenharmony_ci bool was_detached_ = false; 5241cb0ef41Sopenharmony_ci}; 5251cb0ef41Sopenharmony_ci 5261cb0ef41Sopenharmony_ciclass Utf8Value : public MaybeStackBuffer<char> { 5271cb0ef41Sopenharmony_ci public: 5281cb0ef41Sopenharmony_ci explicit Utf8Value(v8::Isolate* isolate, v8::Local<v8::Value> value); 5291cb0ef41Sopenharmony_ci 5301cb0ef41Sopenharmony_ci inline bool operator==(const char* a) const { return strcmp(out(), a) == 0; } 5311cb0ef41Sopenharmony_ci inline bool operator!=(const char* a) const { return !(*this == a); } 5321cb0ef41Sopenharmony_ci}; 5331cb0ef41Sopenharmony_ci 5341cb0ef41Sopenharmony_ciclass TwoByteValue : public MaybeStackBuffer<uint16_t> { 5351cb0ef41Sopenharmony_ci public: 5361cb0ef41Sopenharmony_ci explicit TwoByteValue(v8::Isolate* isolate, v8::Local<v8::Value> value); 5371cb0ef41Sopenharmony_ci}; 5381cb0ef41Sopenharmony_ci 5391cb0ef41Sopenharmony_ciclass BufferValue : public MaybeStackBuffer<char> { 5401cb0ef41Sopenharmony_ci public: 5411cb0ef41Sopenharmony_ci explicit BufferValue(v8::Isolate* isolate, v8::Local<v8::Value> value); 5421cb0ef41Sopenharmony_ci 5431cb0ef41Sopenharmony_ci inline std::string ToString() const { return std::string(out(), length()); } 5441cb0ef41Sopenharmony_ci}; 5451cb0ef41Sopenharmony_ci 5461cb0ef41Sopenharmony_ci#define SPREAD_BUFFER_ARG(val, name) \ 5471cb0ef41Sopenharmony_ci CHECK((val)->IsArrayBufferView()); \ 5481cb0ef41Sopenharmony_ci v8::Local<v8::ArrayBufferView> name = (val).As<v8::ArrayBufferView>(); \ 5491cb0ef41Sopenharmony_ci const size_t name##_offset = name->ByteOffset(); \ 5501cb0ef41Sopenharmony_ci const size_t name##_length = name->ByteLength(); \ 5511cb0ef41Sopenharmony_ci char* const name##_data = \ 5521cb0ef41Sopenharmony_ci static_cast<char*>(name->Buffer()->Data()) + name##_offset; \ 5531cb0ef41Sopenharmony_ci if (name##_length > 0) CHECK_NE(name##_data, nullptr); 5541cb0ef41Sopenharmony_ci 5551cb0ef41Sopenharmony_ci// Use this when a variable or parameter is unused in order to explicitly 5561cb0ef41Sopenharmony_ci// silence a compiler warning about that. 5571cb0ef41Sopenharmony_citemplate <typename T> inline void USE(T&&) {} 5581cb0ef41Sopenharmony_ci 5591cb0ef41Sopenharmony_citemplate <typename Fn> 5601cb0ef41Sopenharmony_cistruct OnScopeLeaveImpl { 5611cb0ef41Sopenharmony_ci Fn fn_; 5621cb0ef41Sopenharmony_ci bool active_; 5631cb0ef41Sopenharmony_ci 5641cb0ef41Sopenharmony_ci explicit OnScopeLeaveImpl(Fn&& fn) : fn_(std::move(fn)), active_(true) {} 5651cb0ef41Sopenharmony_ci ~OnScopeLeaveImpl() { if (active_) fn_(); } 5661cb0ef41Sopenharmony_ci 5671cb0ef41Sopenharmony_ci OnScopeLeaveImpl(const OnScopeLeaveImpl& other) = delete; 5681cb0ef41Sopenharmony_ci OnScopeLeaveImpl& operator=(const OnScopeLeaveImpl& other) = delete; 5691cb0ef41Sopenharmony_ci OnScopeLeaveImpl(OnScopeLeaveImpl&& other) 5701cb0ef41Sopenharmony_ci : fn_(std::move(other.fn_)), active_(other.active_) { 5711cb0ef41Sopenharmony_ci other.active_ = false; 5721cb0ef41Sopenharmony_ci } 5731cb0ef41Sopenharmony_ci}; 5741cb0ef41Sopenharmony_ci 5751cb0ef41Sopenharmony_ci// Run a function when exiting the current scope. Used like this: 5761cb0ef41Sopenharmony_ci// auto on_scope_leave = OnScopeLeave([&] { 5771cb0ef41Sopenharmony_ci// // ... run some code ... 5781cb0ef41Sopenharmony_ci// }); 5791cb0ef41Sopenharmony_citemplate <typename Fn> 5801cb0ef41Sopenharmony_ciinline MUST_USE_RESULT OnScopeLeaveImpl<Fn> OnScopeLeave(Fn&& fn) { 5811cb0ef41Sopenharmony_ci return OnScopeLeaveImpl<Fn>{std::move(fn)}; 5821cb0ef41Sopenharmony_ci} 5831cb0ef41Sopenharmony_ci 5841cb0ef41Sopenharmony_ci// Simple RAII wrapper for contiguous data that uses malloc()/free(). 5851cb0ef41Sopenharmony_citemplate <typename T> 5861cb0ef41Sopenharmony_cistruct MallocedBuffer { 5871cb0ef41Sopenharmony_ci T* data; 5881cb0ef41Sopenharmony_ci size_t size; 5891cb0ef41Sopenharmony_ci 5901cb0ef41Sopenharmony_ci T* release() { 5911cb0ef41Sopenharmony_ci T* ret = data; 5921cb0ef41Sopenharmony_ci data = nullptr; 5931cb0ef41Sopenharmony_ci return ret; 5941cb0ef41Sopenharmony_ci } 5951cb0ef41Sopenharmony_ci 5961cb0ef41Sopenharmony_ci void Truncate(size_t new_size) { 5971cb0ef41Sopenharmony_ci CHECK_LE(new_size, size); 5981cb0ef41Sopenharmony_ci size = new_size; 5991cb0ef41Sopenharmony_ci } 6001cb0ef41Sopenharmony_ci 6011cb0ef41Sopenharmony_ci void Realloc(size_t new_size) { 6021cb0ef41Sopenharmony_ci Truncate(new_size); 6031cb0ef41Sopenharmony_ci data = UncheckedRealloc(data, new_size); 6041cb0ef41Sopenharmony_ci } 6051cb0ef41Sopenharmony_ci 6061cb0ef41Sopenharmony_ci bool is_empty() const { return data == nullptr; } 6071cb0ef41Sopenharmony_ci 6081cb0ef41Sopenharmony_ci MallocedBuffer() : data(nullptr), size(0) {} 6091cb0ef41Sopenharmony_ci explicit MallocedBuffer(size_t size) : data(Malloc<T>(size)), size(size) {} 6101cb0ef41Sopenharmony_ci MallocedBuffer(T* data, size_t size) : data(data), size(size) {} 6111cb0ef41Sopenharmony_ci MallocedBuffer(MallocedBuffer&& other) : data(other.data), size(other.size) { 6121cb0ef41Sopenharmony_ci other.data = nullptr; 6131cb0ef41Sopenharmony_ci } 6141cb0ef41Sopenharmony_ci MallocedBuffer& operator=(MallocedBuffer&& other) { 6151cb0ef41Sopenharmony_ci this->~MallocedBuffer(); 6161cb0ef41Sopenharmony_ci return *new(this) MallocedBuffer(std::move(other)); 6171cb0ef41Sopenharmony_ci } 6181cb0ef41Sopenharmony_ci ~MallocedBuffer() { 6191cb0ef41Sopenharmony_ci free(data); 6201cb0ef41Sopenharmony_ci } 6211cb0ef41Sopenharmony_ci MallocedBuffer(const MallocedBuffer&) = delete; 6221cb0ef41Sopenharmony_ci MallocedBuffer& operator=(const MallocedBuffer&) = delete; 6231cb0ef41Sopenharmony_ci}; 6241cb0ef41Sopenharmony_ci 6251cb0ef41Sopenharmony_citemplate <typename T> 6261cb0ef41Sopenharmony_ciclass NonCopyableMaybe { 6271cb0ef41Sopenharmony_ci public: 6281cb0ef41Sopenharmony_ci NonCopyableMaybe() : empty_(true) {} 6291cb0ef41Sopenharmony_ci explicit NonCopyableMaybe(T&& value) 6301cb0ef41Sopenharmony_ci : empty_(false), 6311cb0ef41Sopenharmony_ci value_(std::move(value)) {} 6321cb0ef41Sopenharmony_ci 6331cb0ef41Sopenharmony_ci bool IsEmpty() const { 6341cb0ef41Sopenharmony_ci return empty_; 6351cb0ef41Sopenharmony_ci } 6361cb0ef41Sopenharmony_ci 6371cb0ef41Sopenharmony_ci const T* get() const { 6381cb0ef41Sopenharmony_ci return empty_ ? nullptr : &value_; 6391cb0ef41Sopenharmony_ci } 6401cb0ef41Sopenharmony_ci 6411cb0ef41Sopenharmony_ci const T* operator->() const { 6421cb0ef41Sopenharmony_ci CHECK(!empty_); 6431cb0ef41Sopenharmony_ci return &value_; 6441cb0ef41Sopenharmony_ci } 6451cb0ef41Sopenharmony_ci 6461cb0ef41Sopenharmony_ci T&& Release() { 6471cb0ef41Sopenharmony_ci CHECK_EQ(empty_, false); 6481cb0ef41Sopenharmony_ci empty_ = true; 6491cb0ef41Sopenharmony_ci return std::move(value_); 6501cb0ef41Sopenharmony_ci } 6511cb0ef41Sopenharmony_ci 6521cb0ef41Sopenharmony_ci private: 6531cb0ef41Sopenharmony_ci bool empty_; 6541cb0ef41Sopenharmony_ci T value_; 6551cb0ef41Sopenharmony_ci}; 6561cb0ef41Sopenharmony_ci 6571cb0ef41Sopenharmony_ci// Test whether some value can be called with (). 6581cb0ef41Sopenharmony_citemplate <typename T, typename = void> 6591cb0ef41Sopenharmony_cistruct is_callable : std::is_function<T> { }; 6601cb0ef41Sopenharmony_ci 6611cb0ef41Sopenharmony_citemplate <typename T> 6621cb0ef41Sopenharmony_cistruct is_callable<T, typename std::enable_if< 6631cb0ef41Sopenharmony_ci std::is_same<decltype(void(&T::operator())), void>::value 6641cb0ef41Sopenharmony_ci >::type> : std::true_type { }; 6651cb0ef41Sopenharmony_ci 6661cb0ef41Sopenharmony_citemplate <typename T, void (*function)(T*)> 6671cb0ef41Sopenharmony_cistruct FunctionDeleter { 6681cb0ef41Sopenharmony_ci void operator()(T* pointer) const { function(pointer); } 6691cb0ef41Sopenharmony_ci typedef std::unique_ptr<T, FunctionDeleter> Pointer; 6701cb0ef41Sopenharmony_ci}; 6711cb0ef41Sopenharmony_ci 6721cb0ef41Sopenharmony_citemplate <typename T, void (*function)(T*)> 6731cb0ef41Sopenharmony_ciusing DeleteFnPtr = typename FunctionDeleter<T, function>::Pointer; 6741cb0ef41Sopenharmony_ci 6751cb0ef41Sopenharmony_cistd::vector<std::string_view> SplitString(const std::string_view in, 6761cb0ef41Sopenharmony_ci const std::string_view delim); 6771cb0ef41Sopenharmony_ci 6781cb0ef41Sopenharmony_ciinline v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context, 6791cb0ef41Sopenharmony_ci std::string_view str, 6801cb0ef41Sopenharmony_ci v8::Isolate* isolate = nullptr); 6811cb0ef41Sopenharmony_citemplate <typename T, typename test_for_number = 6821cb0ef41Sopenharmony_ci typename std::enable_if<std::numeric_limits<T>::is_specialized, bool>::type> 6831cb0ef41Sopenharmony_ciinline v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context, 6841cb0ef41Sopenharmony_ci const T& number, 6851cb0ef41Sopenharmony_ci v8::Isolate* isolate = nullptr); 6861cb0ef41Sopenharmony_citemplate <typename T> 6871cb0ef41Sopenharmony_ciinline v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context, 6881cb0ef41Sopenharmony_ci const std::vector<T>& vec, 6891cb0ef41Sopenharmony_ci v8::Isolate* isolate = nullptr); 6901cb0ef41Sopenharmony_citemplate <typename T> 6911cb0ef41Sopenharmony_ciinline v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context, 6921cb0ef41Sopenharmony_ci const std::set<T>& set, 6931cb0ef41Sopenharmony_ci v8::Isolate* isolate = nullptr); 6941cb0ef41Sopenharmony_citemplate <typename T, typename U> 6951cb0ef41Sopenharmony_ciinline v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context, 6961cb0ef41Sopenharmony_ci const std::unordered_map<T, U>& map, 6971cb0ef41Sopenharmony_ci v8::Isolate* isolate = nullptr); 6981cb0ef41Sopenharmony_ci 6991cb0ef41Sopenharmony_ci// These macros expects a `Isolate* isolate` and a `Local<Context> context` 7001cb0ef41Sopenharmony_ci// to be in the scope. 7011cb0ef41Sopenharmony_ci#define READONLY_PROPERTY(obj, name, value) \ 7021cb0ef41Sopenharmony_ci do { \ 7031cb0ef41Sopenharmony_ci obj->DefineOwnProperty( \ 7041cb0ef41Sopenharmony_ci context, FIXED_ONE_BYTE_STRING(isolate, name), value, v8::ReadOnly) \ 7051cb0ef41Sopenharmony_ci .Check(); \ 7061cb0ef41Sopenharmony_ci } while (0) 7071cb0ef41Sopenharmony_ci 7081cb0ef41Sopenharmony_ci#define READONLY_DONT_ENUM_PROPERTY(obj, name, var) \ 7091cb0ef41Sopenharmony_ci do { \ 7101cb0ef41Sopenharmony_ci obj->DefineOwnProperty( \ 7111cb0ef41Sopenharmony_ci context, \ 7121cb0ef41Sopenharmony_ci OneByteString(isolate, name), \ 7131cb0ef41Sopenharmony_ci var, \ 7141cb0ef41Sopenharmony_ci static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum)) \ 7151cb0ef41Sopenharmony_ci .Check(); \ 7161cb0ef41Sopenharmony_ci } while (0) 7171cb0ef41Sopenharmony_ci 7181cb0ef41Sopenharmony_ci#define READONLY_FALSE_PROPERTY(obj, name) \ 7191cb0ef41Sopenharmony_ci READONLY_PROPERTY(obj, name, v8::False(isolate)) 7201cb0ef41Sopenharmony_ci 7211cb0ef41Sopenharmony_ci#define READONLY_TRUE_PROPERTY(obj, name) \ 7221cb0ef41Sopenharmony_ci READONLY_PROPERTY(obj, name, v8::True(isolate)) 7231cb0ef41Sopenharmony_ci 7241cb0ef41Sopenharmony_ci#define READONLY_STRING_PROPERTY(obj, name, str) \ 7251cb0ef41Sopenharmony_ci READONLY_PROPERTY(obj, name, ToV8Value(context, str).ToLocalChecked()) 7261cb0ef41Sopenharmony_ci 7271cb0ef41Sopenharmony_ci// Variation on NODE_DEFINE_CONSTANT that sets a String value. 7281cb0ef41Sopenharmony_ci#define NODE_DEFINE_STRING_CONSTANT(target, name, constant) \ 7291cb0ef41Sopenharmony_ci do { \ 7301cb0ef41Sopenharmony_ci v8::Isolate* isolate = target->GetIsolate(); \ 7311cb0ef41Sopenharmony_ci v8::Local<v8::String> constant_name = \ 7321cb0ef41Sopenharmony_ci v8::String::NewFromUtf8(isolate, name).ToLocalChecked(); \ 7331cb0ef41Sopenharmony_ci v8::Local<v8::String> constant_value = \ 7341cb0ef41Sopenharmony_ci v8::String::NewFromUtf8(isolate, constant).ToLocalChecked(); \ 7351cb0ef41Sopenharmony_ci v8::PropertyAttribute constant_attributes = \ 7361cb0ef41Sopenharmony_ci static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete); \ 7371cb0ef41Sopenharmony_ci target \ 7381cb0ef41Sopenharmony_ci ->DefineOwnProperty(isolate->GetCurrentContext(), \ 7391cb0ef41Sopenharmony_ci constant_name, \ 7401cb0ef41Sopenharmony_ci constant_value, \ 7411cb0ef41Sopenharmony_ci constant_attributes) \ 7421cb0ef41Sopenharmony_ci .Check(); \ 7431cb0ef41Sopenharmony_ci } while (0) 7441cb0ef41Sopenharmony_ci 7451cb0ef41Sopenharmony_cienum class Endianness { LITTLE, BIG }; 7461cb0ef41Sopenharmony_ci 7471cb0ef41Sopenharmony_ciinline Endianness GetEndianness() { 7481cb0ef41Sopenharmony_ci // Constant-folded by the compiler. 7491cb0ef41Sopenharmony_ci const union { 7501cb0ef41Sopenharmony_ci uint8_t u8[2]; 7511cb0ef41Sopenharmony_ci uint16_t u16; 7521cb0ef41Sopenharmony_ci } u = {{1, 0}}; 7531cb0ef41Sopenharmony_ci return u.u16 == 1 ? Endianness::LITTLE : Endianness::BIG; 7541cb0ef41Sopenharmony_ci} 7551cb0ef41Sopenharmony_ci 7561cb0ef41Sopenharmony_ciinline bool IsLittleEndian() { 7571cb0ef41Sopenharmony_ci return GetEndianness() == Endianness::LITTLE; 7581cb0ef41Sopenharmony_ci} 7591cb0ef41Sopenharmony_ci 7601cb0ef41Sopenharmony_ciinline bool IsBigEndian() { 7611cb0ef41Sopenharmony_ci return GetEndianness() == Endianness::BIG; 7621cb0ef41Sopenharmony_ci} 7631cb0ef41Sopenharmony_ci 7641cb0ef41Sopenharmony_ci// Round up a to the next highest multiple of b. 7651cb0ef41Sopenharmony_citemplate <typename T> 7661cb0ef41Sopenharmony_ciconstexpr T RoundUp(T a, T b) { 7671cb0ef41Sopenharmony_ci return a % b != 0 ? a + b - (a % b) : a; 7681cb0ef41Sopenharmony_ci} 7691cb0ef41Sopenharmony_ci 7701cb0ef41Sopenharmony_ci// Align ptr to an `alignment`-bytes boundary. 7711cb0ef41Sopenharmony_citemplate <typename T, typename U> 7721cb0ef41Sopenharmony_ciconstexpr T* AlignUp(T* ptr, U alignment) { 7731cb0ef41Sopenharmony_ci return reinterpret_cast<T*>( 7741cb0ef41Sopenharmony_ci RoundUp(reinterpret_cast<uintptr_t>(ptr), alignment)); 7751cb0ef41Sopenharmony_ci} 7761cb0ef41Sopenharmony_ci 7771cb0ef41Sopenharmony_ciclass SlicedArguments : public MaybeStackBuffer<v8::Local<v8::Value>> { 7781cb0ef41Sopenharmony_ci public: 7791cb0ef41Sopenharmony_ci inline explicit SlicedArguments( 7801cb0ef41Sopenharmony_ci const v8::FunctionCallbackInfo<v8::Value>& args, size_t start = 0); 7811cb0ef41Sopenharmony_ci}; 7821cb0ef41Sopenharmony_ci 7831cb0ef41Sopenharmony_ci// Convert a v8::PersistentBase, e.g. v8::Global, to a Local, with an extra 7841cb0ef41Sopenharmony_ci// optimization for strong persistent handles. 7851cb0ef41Sopenharmony_ciclass PersistentToLocal { 7861cb0ef41Sopenharmony_ci public: 7871cb0ef41Sopenharmony_ci // If persistent.IsWeak() == false, then do not call persistent.Reset() 7881cb0ef41Sopenharmony_ci // while the returned Local<T> is still in scope, it will destroy the 7891cb0ef41Sopenharmony_ci // reference to the object. 7901cb0ef41Sopenharmony_ci template <class TypeName> 7911cb0ef41Sopenharmony_ci static inline v8::Local<TypeName> Default( 7921cb0ef41Sopenharmony_ci v8::Isolate* isolate, 7931cb0ef41Sopenharmony_ci const v8::PersistentBase<TypeName>& persistent) { 7941cb0ef41Sopenharmony_ci if (persistent.IsWeak()) { 7951cb0ef41Sopenharmony_ci return PersistentToLocal::Weak(isolate, persistent); 7961cb0ef41Sopenharmony_ci } else { 7971cb0ef41Sopenharmony_ci return PersistentToLocal::Strong(persistent); 7981cb0ef41Sopenharmony_ci } 7991cb0ef41Sopenharmony_ci } 8001cb0ef41Sopenharmony_ci 8011cb0ef41Sopenharmony_ci // Unchecked conversion from a non-weak Persistent<T> to Local<T>, 8021cb0ef41Sopenharmony_ci // use with care! 8031cb0ef41Sopenharmony_ci // 8041cb0ef41Sopenharmony_ci // Do not call persistent.Reset() while the returned Local<T> is still in 8051cb0ef41Sopenharmony_ci // scope, it will destroy the reference to the object. 8061cb0ef41Sopenharmony_ci template <class TypeName> 8071cb0ef41Sopenharmony_ci static inline v8::Local<TypeName> Strong( 8081cb0ef41Sopenharmony_ci const v8::PersistentBase<TypeName>& persistent) { 8091cb0ef41Sopenharmony_ci DCHECK(!persistent.IsWeak()); 8101cb0ef41Sopenharmony_ci return *reinterpret_cast<v8::Local<TypeName>*>( 8111cb0ef41Sopenharmony_ci const_cast<v8::PersistentBase<TypeName>*>(&persistent)); 8121cb0ef41Sopenharmony_ci } 8131cb0ef41Sopenharmony_ci 8141cb0ef41Sopenharmony_ci template <class TypeName> 8151cb0ef41Sopenharmony_ci static inline v8::Local<TypeName> Weak( 8161cb0ef41Sopenharmony_ci v8::Isolate* isolate, 8171cb0ef41Sopenharmony_ci const v8::PersistentBase<TypeName>& persistent) { 8181cb0ef41Sopenharmony_ci return v8::Local<TypeName>::New(isolate, persistent); 8191cb0ef41Sopenharmony_ci } 8201cb0ef41Sopenharmony_ci}; 8211cb0ef41Sopenharmony_ci 8221cb0ef41Sopenharmony_ci// Can be used as a key for std::unordered_map when lookup performance is more 8231cb0ef41Sopenharmony_ci// important than size and the keys are statically used to avoid redundant hash 8241cb0ef41Sopenharmony_ci// computations. 8251cb0ef41Sopenharmony_ciclass FastStringKey { 8261cb0ef41Sopenharmony_ci public: 8271cb0ef41Sopenharmony_ci constexpr explicit FastStringKey(std::string_view name); 8281cb0ef41Sopenharmony_ci 8291cb0ef41Sopenharmony_ci struct Hash { 8301cb0ef41Sopenharmony_ci constexpr size_t operator()(const FastStringKey& key) const; 8311cb0ef41Sopenharmony_ci }; 8321cb0ef41Sopenharmony_ci constexpr bool operator==(const FastStringKey& other) const; 8331cb0ef41Sopenharmony_ci 8341cb0ef41Sopenharmony_ci constexpr std::string_view as_string_view() const; 8351cb0ef41Sopenharmony_ci 8361cb0ef41Sopenharmony_ci private: 8371cb0ef41Sopenharmony_ci static constexpr size_t HashImpl(std::string_view str); 8381cb0ef41Sopenharmony_ci 8391cb0ef41Sopenharmony_ci const std::string_view name_; 8401cb0ef41Sopenharmony_ci const size_t cached_hash_; 8411cb0ef41Sopenharmony_ci}; 8421cb0ef41Sopenharmony_ci 8431cb0ef41Sopenharmony_ci// Like std::static_pointer_cast but for unique_ptr with the default deleter. 8441cb0ef41Sopenharmony_citemplate <typename T, typename U> 8451cb0ef41Sopenharmony_cistd::unique_ptr<T> static_unique_pointer_cast(std::unique_ptr<U>&& ptr) { 8461cb0ef41Sopenharmony_ci return std::unique_ptr<T>(static_cast<T*>(ptr.release())); 8471cb0ef41Sopenharmony_ci} 8481cb0ef41Sopenharmony_ci 8491cb0ef41Sopenharmony_ci#define MAYBE_FIELD_PTR(ptr, field) ptr == nullptr ? nullptr : &(ptr->field) 8501cb0ef41Sopenharmony_ci 8511cb0ef41Sopenharmony_ci// Returns a non-zero code if it fails to open or read the file, 8521cb0ef41Sopenharmony_ci// aborts if it fails to close the file. 8531cb0ef41Sopenharmony_ciint ReadFileSync(std::string* result, const char* path); 8541cb0ef41Sopenharmony_ci 8551cb0ef41Sopenharmony_civ8::Local<v8::FunctionTemplate> NewFunctionTemplate( 8561cb0ef41Sopenharmony_ci v8::Isolate* isolate, 8571cb0ef41Sopenharmony_ci v8::FunctionCallback callback, 8581cb0ef41Sopenharmony_ci v8::Local<v8::Signature> signature = v8::Local<v8::Signature>(), 8591cb0ef41Sopenharmony_ci v8::ConstructorBehavior behavior = v8::ConstructorBehavior::kAllow, 8601cb0ef41Sopenharmony_ci v8::SideEffectType side_effect = v8::SideEffectType::kHasSideEffect, 8611cb0ef41Sopenharmony_ci const v8::CFunction* c_function = nullptr); 8621cb0ef41Sopenharmony_ci 8631cb0ef41Sopenharmony_ci// Convenience methods for NewFunctionTemplate(). 8641cb0ef41Sopenharmony_civoid SetMethod(v8::Local<v8::Context> context, 8651cb0ef41Sopenharmony_ci v8::Local<v8::Object> that, 8661cb0ef41Sopenharmony_ci const char* name, 8671cb0ef41Sopenharmony_ci v8::FunctionCallback callback); 8681cb0ef41Sopenharmony_ci// Similar to SetProtoMethod but without receiver signature checks. 8691cb0ef41Sopenharmony_civoid SetMethod(v8::Isolate* isolate, 8701cb0ef41Sopenharmony_ci v8::Local<v8::Template> that, 8711cb0ef41Sopenharmony_ci const char* name, 8721cb0ef41Sopenharmony_ci v8::FunctionCallback callback); 8731cb0ef41Sopenharmony_ci 8741cb0ef41Sopenharmony_civoid SetFastMethod(v8::Local<v8::Context> context, 8751cb0ef41Sopenharmony_ci v8::Local<v8::Object> that, 8761cb0ef41Sopenharmony_ci const char* name, 8771cb0ef41Sopenharmony_ci v8::FunctionCallback slow_callback, 8781cb0ef41Sopenharmony_ci const v8::CFunction* c_function); 8791cb0ef41Sopenharmony_civoid SetFastMethodNoSideEffect(v8::Local<v8::Context> context, 8801cb0ef41Sopenharmony_ci v8::Local<v8::Object> that, 8811cb0ef41Sopenharmony_ci const char* name, 8821cb0ef41Sopenharmony_ci v8::FunctionCallback slow_callback, 8831cb0ef41Sopenharmony_ci const v8::CFunction* c_function); 8841cb0ef41Sopenharmony_ci 8851cb0ef41Sopenharmony_civoid SetProtoMethod(v8::Isolate* isolate, 8861cb0ef41Sopenharmony_ci v8::Local<v8::FunctionTemplate> that, 8871cb0ef41Sopenharmony_ci const char* name, 8881cb0ef41Sopenharmony_ci v8::FunctionCallback callback); 8891cb0ef41Sopenharmony_ci 8901cb0ef41Sopenharmony_civoid SetInstanceMethod(v8::Isolate* isolate, 8911cb0ef41Sopenharmony_ci v8::Local<v8::FunctionTemplate> that, 8921cb0ef41Sopenharmony_ci const char* name, 8931cb0ef41Sopenharmony_ci v8::FunctionCallback callback); 8941cb0ef41Sopenharmony_ci 8951cb0ef41Sopenharmony_ci// Safe variants denote the function has no side effects. 8961cb0ef41Sopenharmony_civoid SetMethodNoSideEffect(v8::Local<v8::Context> context, 8971cb0ef41Sopenharmony_ci v8::Local<v8::Object> that, 8981cb0ef41Sopenharmony_ci const char* name, 8991cb0ef41Sopenharmony_ci v8::FunctionCallback callback); 9001cb0ef41Sopenharmony_civoid SetProtoMethodNoSideEffect(v8::Isolate* isolate, 9011cb0ef41Sopenharmony_ci v8::Local<v8::FunctionTemplate> that, 9021cb0ef41Sopenharmony_ci const char* name, 9031cb0ef41Sopenharmony_ci v8::FunctionCallback callback); 9041cb0ef41Sopenharmony_ci 9051cb0ef41Sopenharmony_cienum class SetConstructorFunctionFlag { 9061cb0ef41Sopenharmony_ci NONE, 9071cb0ef41Sopenharmony_ci SET_CLASS_NAME, 9081cb0ef41Sopenharmony_ci}; 9091cb0ef41Sopenharmony_ci 9101cb0ef41Sopenharmony_civoid SetConstructorFunction(v8::Local<v8::Context> context, 9111cb0ef41Sopenharmony_ci v8::Local<v8::Object> that, 9121cb0ef41Sopenharmony_ci const char* name, 9131cb0ef41Sopenharmony_ci v8::Local<v8::FunctionTemplate> tmpl, 9141cb0ef41Sopenharmony_ci SetConstructorFunctionFlag flag = 9151cb0ef41Sopenharmony_ci SetConstructorFunctionFlag::SET_CLASS_NAME); 9161cb0ef41Sopenharmony_ci 9171cb0ef41Sopenharmony_civoid SetConstructorFunction(v8::Local<v8::Context> context, 9181cb0ef41Sopenharmony_ci v8::Local<v8::Object> that, 9191cb0ef41Sopenharmony_ci v8::Local<v8::String> name, 9201cb0ef41Sopenharmony_ci v8::Local<v8::FunctionTemplate> tmpl, 9211cb0ef41Sopenharmony_ci SetConstructorFunctionFlag flag = 9221cb0ef41Sopenharmony_ci SetConstructorFunctionFlag::SET_CLASS_NAME); 9231cb0ef41Sopenharmony_ci 9241cb0ef41Sopenharmony_ci} // namespace node 9251cb0ef41Sopenharmony_ci 9261cb0ef41Sopenharmony_ci#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS 9271cb0ef41Sopenharmony_ci 9281cb0ef41Sopenharmony_ci#endif // SRC_UTIL_H_ 929