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