diff --git a/.github/workflows/tools.yml b/.github/workflows/tools.yml index 4d5d7343a36456..891ab1e1bda6f4 100644 --- a/.github/workflows/tools.yml +++ b/.github/workflows/tools.yml @@ -31,6 +31,7 @@ on: - lint-md-dependencies - llhttp - minimatch + - nbytes - nghttp2 - nghttp3 - ngtcp2 @@ -220,6 +221,14 @@ jobs: cat temp-output tail -n1 temp-output | grep "NEW_VERSION=" >> "$GITHUB_ENV" || true rm temp-output + - id: nbytes + subsystem: deps + label: dependencies + run: | + ./tools/dep_updaters/update-nbytes.sh > temp-output + cat temp-output + tail -n1 temp-output | grep "NEW_VERSION=" >> "$GITHUB_ENV" || true + rm temp-output - id: nghttp2 subsystem: deps label: dependencies diff --git a/deps/nbytes/.clang-format b/deps/nbytes/.clang-format new file mode 100644 index 00000000000000..59d0684df39c9c --- /dev/null +++ b/deps/nbytes/.clang-format @@ -0,0 +1,2 @@ +BasedOnStyle: Google +SortIncludes: Never diff --git a/deps/nbytes/.gitignore b/deps/nbytes/.gitignore new file mode 100644 index 00000000000000..f1a825f2a0f689 --- /dev/null +++ b/deps/nbytes/.gitignore @@ -0,0 +1,2 @@ +cmake-build-debug +build diff --git a/deps/nbytes/.python-version b/deps/nbytes/.python-version new file mode 100644 index 00000000000000..e4fba218358722 --- /dev/null +++ b/deps/nbytes/.python-version @@ -0,0 +1 @@ +3.12 diff --git a/deps/nbytes/CMakeLists.txt b/deps/nbytes/CMakeLists.txt new file mode 100644 index 00000000000000..f2efa3c52ba1d1 --- /dev/null +++ b/deps/nbytes/CMakeLists.txt @@ -0,0 +1,42 @@ +cmake_minimum_required(VERSION 3.28) +project(nbytes) + +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED True) +if (NOT CMAKE_BUILD_TYPE) + message(STATUS "No build type selected, default to Release") + set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build." FORCE) +endif() + +option(NBYTES_DEVELOPMENT_CHECKS "Enable development checks" OFF) + +include(GNUInstallDirs) +include(FetchContent) + +FetchContent_Declare( + googletest + URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip +) +# For Windows: Prevent overriding the parent project's compiler/linker settings +set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) +FetchContent_MakeAvailable(googletest) + +add_subdirectory(src) +enable_testing() +add_subdirectory(tests) + +install( + FILES include/nbytes.h + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" + COMPONENT nbytes_development +) + +install( + TARGETS nbytes + EXPORT nbytes_targets + RUNTIME COMPONENT nbytes_runtime + LIBRARY COMPONENT nbytes_runtime + NAMELINK_COMPONENT nbytes_development + ARCHIVE COMPONENT nbytes_development + INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" +) diff --git a/deps/nbytes/LICENSE b/deps/nbytes/LICENSE new file mode 100644 index 00000000000000..83c1fb9f1d90c4 --- /dev/null +++ b/deps/nbytes/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Node.js + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/deps/nbytes/nbytes.h b/deps/nbytes/include/nbytes.h similarity index 81% rename from deps/nbytes/nbytes.h rename to deps/nbytes/include/nbytes.h index 7af92ddc3d538e..627bfd5837a9f1 100644 --- a/deps/nbytes/nbytes.h +++ b/deps/nbytes/include/nbytes.h @@ -1,24 +1,24 @@ -#pragma once - +#ifndef NBYTES_H +#define NBYTES_H #include -#include +#include #include #include #include -#include +#include namespace nbytes { #if NBYTES_DEVELOPMENT_CHECKS #define NBYTES_STR(x) #x -#define NBYTES_REQUIRE(EXPR) \ - { \ +#define NBYTES_REQUIRE(EXPR) \ + { \ if (!(EXPR) { abort(); }) } -#define NBYTES_FAIL(MESSAGE) \ - do { \ - std::cerr << "FAIL: " << (MESSAGE) << std::endl; \ - abort(); \ +#define NBYTES_FAIL(MESSAGE) \ + do { \ + std::cerr << "FAIL: " << (MESSAGE) << std::endl; \ + abort(); \ } while (0); #define NBYTES_ASSERT_EQUAL(LHS, RHS, MESSAGE) \ do { \ @@ -27,13 +27,13 @@ namespace nbytes { NBYTES_FAIL(MESSAGE); \ } \ } while (0); -#define NBYTES_ASSERT_TRUE(COND) \ - do { \ - if (!(COND)) { \ - std::cerr << "Assert at line " << __LINE__ << " of file " << __FILE__ \ - << std::endl; \ - NBYTES_FAIL(NBYTES_STR(COND)); \ - } \ +#define NBYTES_ASSERT_TRUE(COND) \ + do { \ + if (!(COND)) { \ + std::cerr << "Assert at line " << __LINE__ << " of file " << __FILE__ \ + << std::endl; \ + NBYTES_FAIL(NBYTES_STR(COND)); \ + } \ } while (0); #else #define NBYTES_FAIL(MESSAGE) @@ -64,8 +64,8 @@ constexpr T RoundUp(T a, T b) { // Align ptr to an `alignment`-bytes boundary. template -constexpr T* AlignUp(T* ptr, U alignment) { - return reinterpret_cast( +constexpr T *AlignUp(T *ptr, U alignment) { + return reinterpret_cast( RoundUp(reinterpret_cast(ptr), alignment)); } @@ -85,17 +85,17 @@ inline T MultiplyWithOverflowCheck(T a, T b) { return ret; } -void ForceAsciiSlow(const char* src, char* dst, size_t len); -void ForceAscii(const char* src, char* dst, size_t len); +void ForceAsciiSlow(const char *src, char *dst, size_t len); +void ForceAscii(const char *src, char *dst, size_t len); // ============================================================================ // Byte Swapping // Swaps bytes in place. nbytes is the number of bytes to swap and must be a // multiple of the word size (checked by function). -bool SwapBytes16(void* data, size_t nbytes); -bool SwapBytes32(void* data, size_t nbytes); -bool SwapBytes64(void* data, size_t nbytes); +bool SwapBytes16(void *data, size_t nbytes); +bool SwapBytes32(void *data, size_t nbytes); +bool SwapBytes64(void *data, size_t nbytes); // ============================================================================ // Base64 (legacy) @@ -109,22 +109,22 @@ bool SwapBytes64(void* data, size_t nbytes); extern const int8_t unbase64_table[256]; template -bool Base64DecodeGroupSlow(char* const dst, const size_t dstlen, - const TypeName* const src, const size_t srclen, - size_t* const i, size_t* const k) { +bool Base64DecodeGroupSlow(char *const dst, const size_t dstlen, + const TypeName *const src, const size_t srclen, + size_t *const i, size_t *const k) { uint8_t hi; uint8_t lo; -#define V(expr) \ - for (;;) { \ - const uint8_t c = static_cast(src[*i]); \ - lo = unbase64_table[c]; \ - *i += 1; \ - if (lo < 64) break; /* Legal character. */ \ - if (c == '=' || *i >= srclen) return false; /* Stop decoding. */ \ - } \ - expr; \ - if (*i >= srclen) return false; \ - if (*k >= dstlen) return false; \ +#define V(expr) \ + for (;;) { \ + const uint8_t c = static_cast(src[*i]); \ + lo = unbase64_table[c]; \ + *i += 1; \ + if (lo < 64) break; /* Legal character. */ \ + if (c == '=' || *i >= srclen) return false; /* Stop decoding. */ \ + } \ + expr; \ + if (*i >= srclen) return false; \ + if (*k >= dstlen) return false; \ hi = lo; V(/* Nothing. */); V(dst[(*k)++] = ((hi & 0x3F) << 2) | ((lo & 0x30) >> 4)); @@ -134,14 +134,10 @@ bool Base64DecodeGroupSlow(char* const dst, const size_t dstlen, return true; // Continue decoding. } -enum class Base64Mode { - NORMAL, - URL -}; +enum class Base64Mode { NORMAL, URL }; inline constexpr size_t Base64EncodedSize( - size_t size, - Base64Mode mode = Base64Mode::NORMAL) { + size_t size, Base64Mode mode = Base64Mode::NORMAL) { return mode == Base64Mode::NORMAL ? ((size + 2) / 3 * 4) : static_cast(std::ceil( static_cast(size * 4) / 3)); @@ -153,30 +149,27 @@ inline constexpr size_t Base64DecodedSizeFast(size_t size) { return size > 1 ? (size / 4) * 3 + (size % 4 + 1) / 2 : 0; } -inline uint32_t ReadUint32BE(const unsigned char* p) { +inline uint32_t ReadUint32BE(const unsigned char *p) { return static_cast(p[0] << 24U) | static_cast(p[1] << 16U) | - static_cast(p[2] << 8U) | - static_cast(p[3]); + static_cast(p[2] << 8U) | static_cast(p[3]); } template -size_t Base64DecodedSize(const TypeName* src, size_t size) { +size_t Base64DecodedSize(const TypeName *src, size_t size) { // 1-byte input cannot be decoded - if (size < 2) - return 0; + if (size < 2) return 0; if (src[size - 1] == '=') { size--; - if (src[size - 1] == '=') - size--; + if (src[size - 1] == '=') size--; } return Base64DecodedSizeFast(size); } template -size_t Base64DecodeFast(char* const dst, const size_t dstlen, - const TypeName* const src, const size_t srclen, +size_t Base64DecodeFast(char *const dst, const size_t dstlen, + const TypeName *const src, const size_t srclen, const size_t decoded_size) { const size_t available = dstlen < decoded_size ? dstlen : decoded_size; const size_t max_k = available / 3 * 3; @@ -185,22 +178,25 @@ size_t Base64DecodeFast(char* const dst, const size_t dstlen, size_t k = 0; while (i < max_i && k < max_k) { const unsigned char txt[] = { - static_cast(unbase64_table[static_cast(src[i + 0])]), - static_cast(unbase64_table[static_cast(src[i + 1])]), - static_cast(unbase64_table[static_cast(src[i + 2])]), - static_cast(unbase64_table[static_cast(src[i + 3])]), + static_cast( + unbase64_table[static_cast(src[i + 0])]), + static_cast( + unbase64_table[static_cast(src[i + 1])]), + static_cast( + unbase64_table[static_cast(src[i + 2])]), + static_cast( + unbase64_table[static_cast(src[i + 3])]), }; const uint32_t v = ReadUint32BE(txt); // If MSB is set, input contains whitespace or is not valid base64. if (v & 0x80808080) { - if (!Base64DecodeGroupSlow(dst, dstlen, src, srclen, &i, &k)) - return k; + if (!Base64DecodeGroupSlow(dst, dstlen, src, srclen, &i, &k)) return k; max_i = i + (srclen - i) / 4 * 4; // Align max_i again. } else { dst[k + 0] = ((v >> 22) & 0xFC) | ((v >> 20) & 0x03); dst[k + 1] = ((v >> 12) & 0xF0) | ((v >> 10) & 0x0F); - dst[k + 2] = ((v >> 2) & 0xC0) | ((v >> 0) & 0x3F); + dst[k + 2] = ((v >> 2) & 0xC0) | ((v >> 0) & 0x3F); i += 4; k += 3; } @@ -212,8 +208,8 @@ size_t Base64DecodeFast(char* const dst, const size_t dstlen, } template -size_t Base64Decode(char* const dst, const size_t dstlen, - const TypeName* const src, const size_t srclen) { +size_t Base64Decode(char *const dst, const size_t dstlen, + const TypeName *const src, const size_t srclen) { const size_t decoded_size = Base64DecodedSize(src, srclen); return Base64DecodeFast(dst, dstlen, src, srclen, decoded_size); } @@ -228,29 +224,22 @@ size_t Base64Decode(char* const dst, const size_t dstlen, extern const int8_t unhex_table[256]; template -static size_t HexDecode(char* buf, - size_t len, - const TypeName* src, +static size_t HexDecode(char *buf, size_t len, const TypeName *src, const size_t srcLen) { size_t i; for (i = 0; i < len && i * 2 + 1 < srcLen; ++i) { unsigned a = unhex_table[static_cast(src[i * 2 + 0])]; unsigned b = unhex_table[static_cast(src[i * 2 + 1])]; - if (!~a || !~b) - return i; + if (!~a || !~b) return i; buf[i] = (a << 4) | b; } return i; } -size_t HexEncode( - const char* src, - size_t slen, - char* dst, - size_t dlen); +size_t HexEncode(const char *src, size_t slen, char *dst, size_t dlen); -std::string HexEncode(const char* src, size_t slen); +std::string HexEncode(const char *src, size_t slen); // ============================================================================ // StringSearch @@ -260,14 +249,14 @@ namespace stringsearch { template class Vector { public: - Vector(T* data, size_t length, bool isForward) + Vector(T *data, size_t length, bool isForward) : start_(data), length_(length), is_forward_(isForward) { CHECK(length > 0 && data != nullptr); } // Returns the start of the memory range. // For vector v this is NOT necessarily &v[0], see forward(). - const T* start() const { return start_; } + const T *start() const { return start_; } // Returns the length of the vector, in characters. size_t length() const { return length_; } @@ -277,13 +266,13 @@ class Vector { bool forward() const { return is_forward_; } // Access individual vector elements - checks bounds in debug mode. - T& operator[](size_t index) const { + T &operator[](size_t index) const { NBYTES_ASSERT_TRUE(index < length_); return start_[is_forward_ ? index : (length_ - index - 1)]; } private: - T* start_; + T *start_; size_t length_; bool is_forward_; }; @@ -331,8 +320,7 @@ class StringSearch : private StringSearchBase { public: typedef stringsearch::Vector Vector; - explicit StringSearch(Vector pattern) - : pattern_(pattern), start_(0) { + explicit StringSearch(Vector pattern) : pattern_(pattern), start_(0) { if (pattern.length() >= kBMMaxShift) { start_ = pattern.length() - kBMMaxShift; } @@ -375,9 +363,9 @@ class StringSearch : private StringSearchBase { return kUC16AlphabetSize; } - static_assert(sizeof(Char) == sizeof(uint8_t) || - sizeof(Char) == sizeof(uint16_t), - "sizeof(Char) == sizeof(uint16_t) || sizeof(uint8_t)"); + static_assert( + sizeof(Char) == sizeof(uint8_t) || sizeof(Char) == sizeof(uint16_t), + "sizeof(Char) == sizeof(uint16_t) || sizeof(uint8_t)"); } private: @@ -392,8 +380,7 @@ class StringSearch : private StringSearchBase { void PopulateBoyerMooreTable(); - static inline int CharOccurrence(int* bad_char_occurrence, - Char char_code) { + static inline int CharOccurrence(int *bad_char_occurrence, Char char_code) { if (sizeof(Char) == 1) { return bad_char_occurrence[static_cast(char_code)]; } @@ -427,12 +414,12 @@ inline uint8_t GetHighestValueByte(uint8_t character) { return character; } // Searches for a byte value in a memory buffer, back to front. // Uses memrchr(3) on systems which support it, for speed. // Falls back to a vanilla for loop on non-GNU systems such as Windows. -inline const void* MemrchrFill(const void* haystack, uint8_t needle, +inline const void *MemrchrFill(const void *haystack, uint8_t needle, size_t haystack_len) { #ifdef _GNU_SOURCE return memrchr(haystack, needle, haystack_len); #else - const uint8_t* haystack8 = static_cast(haystack); + const uint8_t *haystack8 = static_cast(haystack); for (size_t i = haystack_len - 1; i != static_cast(-1); i--) { if (haystack8[i] == needle) { return haystack8 + i; @@ -456,7 +443,7 @@ inline size_t FindFirstCharacter(Vector pattern, size_t pos = index; do { const size_t bytes_to_search = (max_n - pos) * sizeof(Char); - const void* void_pos; + const void *void_pos; if (subject.forward()) { // Assert that bytes_to_search won't overflow NBYTES_ASSERT_TRUE(pos <= max_n); @@ -466,12 +453,10 @@ inline size_t FindFirstCharacter(Vector pattern, NBYTES_ASSERT_TRUE(pos <= subject.length()); NBYTES_ASSERT_TRUE(subject.length() - pos <= SIZE_MAX / sizeof(Char)); void_pos = MemrchrFill(subject.start() + pattern.length() - 1, - search_byte, - bytes_to_search); + search_byte, bytes_to_search); } - const Char* char_pos = static_cast(void_pos); - if (char_pos == nullptr) - return subject.length(); + const Char *char_pos = static_cast(void_pos); + if (char_pos == nullptr) return subject.length(); // Then, for each match, verify that the full two bytes match pattern[0]. char_pos = AlignDown(char_pos, sizeof(Char)); @@ -491,21 +476,19 @@ inline size_t FindFirstCharacter(Vector pattern, // Does not verify that the whole pattern matches. template <> inline size_t FindFirstCharacter(Vector pattern, - Vector subject, - size_t index) { + Vector subject, size_t index) { const uint8_t pattern_first_char = pattern[0]; const size_t subj_len = subject.length(); const size_t max_n = (subject.length() - pattern.length() + 1); - const void* pos; + const void *pos; if (subject.forward()) { pos = memchr(subject.start() + index, pattern_first_char, max_n - index); } else { pos = MemrchrFill(subject.start() + pattern.length() - 1, - pattern_first_char, - max_n - index); + pattern_first_char, max_n - index); } - const uint8_t* char_pos = static_cast(pos); + const uint8_t *char_pos = static_cast(pos); if (char_pos == nullptr) { return subj_len; } @@ -519,9 +502,7 @@ inline size_t FindFirstCharacter(Vector pattern, //--------------------------------------------------------------------- template -size_t StringSearch::SingleCharSearch( - Vector subject, - size_t index) { +size_t StringSearch::SingleCharSearch(Vector subject, size_t index) { NBYTES_ASSERT_TRUE(1 == pattern_.length()); return FindFirstCharacter(pattern_, subject, index); } @@ -532,15 +513,12 @@ size_t StringSearch::SingleCharSearch( // Simple linear search for short patterns. Never bails out. template -size_t StringSearch::LinearSearch( - Vector subject, - size_t index) { +size_t StringSearch::LinearSearch(Vector subject, size_t index) { NBYTES_ASSERT_TRUE(pattern_.length() > 1); const size_t n = subject.length() - pattern_.length(); for (size_t i = index; i <= n; i++) { i = FindFirstCharacter(pattern_, subject, i); - if (i == subject.length()) - return subject.length(); + if (i == subject.length()) return subject.length(); NBYTES_ASSERT_TRUE(i <= n); bool matches = true; @@ -562,16 +540,15 @@ size_t StringSearch::LinearSearch( //--------------------------------------------------------------------- template -size_t StringSearch::BoyerMooreSearch( - Vector subject, - size_t start_index) { +size_t StringSearch::BoyerMooreSearch(Vector subject, + size_t start_index) { const size_t subject_length = subject.length(); const size_t pattern_length = pattern_.length(); // Only preprocess at most kBMMaxShift last characters of pattern. size_t start = start_; - int* bad_char_occurrence = bad_char_shift_table_; - int* good_suffix_shift = good_suffix_shift_table_ - start_; + int *bad_char_occurrence = bad_char_shift_table_; + int *good_suffix_shift = good_suffix_shift_table_ - start_; Char last_char = pattern_[pattern_length - 1]; size_t index = start_index; @@ -595,8 +572,8 @@ size_t StringSearch::BoyerMooreSearch( if (j < start) { // we have matched more than our tables allow us to be smart about. // Fall back on BMH shift. - index += pattern_length - 1 - - CharOccurrence(bad_char_occurrence, last_char); + index += + pattern_length - 1 - CharOccurrence(bad_char_occurrence, last_char); } else { int gs_shift = good_suffix_shift[j + 1]; int bc_occ = CharOccurrence(bad_char_occurrence, c); @@ -621,8 +598,8 @@ void StringSearch::PopulateBoyerMooreTable() { // Biased tables so that we can use pattern indices as table indices, // even if we only cover the part of the pattern from offset start. - int* shift_table = good_suffix_shift_table_ - start_; - int* suffix_table = suffix_table_ - start_; + int *shift_table = good_suffix_shift_table_ - start_; + int *suffix_table = suffix_table_ - start_; // Initialize table. for (size_t i = start; i < pattern_length; i++) { @@ -681,19 +658,17 @@ void StringSearch::PopulateBoyerMooreTable() { //--------------------------------------------------------------------- template -size_t StringSearch::BoyerMooreHorspoolSearch( - Vector subject, - size_t start_index) { +size_t StringSearch::BoyerMooreHorspoolSearch(Vector subject, + size_t start_index) { const size_t subject_length = subject.length(); const size_t pattern_length = pattern_.length(); - int* char_occurrences = bad_char_shift_table_; + int *char_occurrences = bad_char_shift_table_; int64_t badness = -static_cast(pattern_length); // How bad we are doing without a good-suffix table. Char last_char = pattern_[pattern_length - 1]; int last_char_shift = - pattern_length - 1 - - CharOccurrence(char_occurrences, last_char); + pattern_length - 1 - CharOccurrence(char_occurrences, last_char); // Perform search size_t index = start_index; // No matches found prior to this index. @@ -735,7 +710,7 @@ template void StringSearch::PopulateBoyerMooreHorspoolTable() { const size_t pattern_length = pattern_.length(); - int* bad_char_occurrence = bad_char_shift_table_; + int *bad_char_occurrence = bad_char_shift_table_; // Only preprocess at most kBMMaxShift last characters of pattern. const size_t start = start_; @@ -765,9 +740,7 @@ void StringSearch::PopulateBoyerMooreHorspoolTable() { // Simple linear search for short patterns, which bails out if the string // isn't found very early in the subject. Upgrades to BoyerMooreHorspool. template -size_t StringSearch::InitialSearch( - Vector subject, - size_t index) { +size_t StringSearch::InitialSearch(Vector subject, size_t index) { const size_t pattern_length = pattern_.length(); // Badness is a count of how much work we have done. When we have // done enough work we decide it's probably worth switching to a better @@ -780,8 +753,7 @@ size_t StringSearch::InitialSearch( badness++; if (badness <= 0) { i = FindFirstCharacter(pattern_, subject, i); - if (i == subject.length()) - return subject.length(); + if (i == subject.length()) return subject.length(); NBYTES_ASSERT_TRUE(i <= n); size_t j = 1; do { @@ -808,8 +780,7 @@ size_t StringSearch::InitialSearch( // object should be constructed once and the Search function then called // for each search. template -size_t SearchString(Vector subject, - Vector pattern, +size_t SearchString(Vector subject, Vector pattern, size_t start_index) { StringSearch search(pattern); return search.Search(subject, start_index); @@ -817,20 +788,17 @@ size_t SearchString(Vector subject, } // namespace stringsearch template -size_t SearchString(const Char* haystack, - size_t haystack_length, - const Char* needle, - size_t needle_length, - size_t start_index, - bool is_forward) { +size_t SearchString(const Char *haystack, size_t haystack_length, + const Char *needle, size_t needle_length, + size_t start_index, bool is_forward) { if (haystack_length < needle_length) return haystack_length; // To do a reverse search (lastIndexOf instead of indexOf) without redundant // code, create two vectors that are reversed views into the input strings. // For example, v_needle[0] would return the *last* character of the needle. // So we're searching for the first instance of rev(needle) in rev(haystack) stringsearch::Vector v_needle(needle, needle_length, is_forward); - stringsearch::Vector v_haystack( - haystack, haystack_length, is_forward); + stringsearch::Vector v_haystack(haystack, haystack_length, + is_forward); size_t diff = haystack_length - needle_length; size_t relative_start_index; if (is_forward) { @@ -840,8 +808,8 @@ size_t SearchString(const Char* haystack, } else { relative_start_index = diff - start_index; } - size_t pos = stringsearch::SearchString( - v_haystack, v_needle, relative_start_index); + size_t pos = + stringsearch::SearchString(v_haystack, v_needle, relative_start_index); if (pos == haystack_length) { // not found return pos; @@ -850,21 +818,23 @@ size_t SearchString(const Char* haystack, } template -size_t SearchString(const char* haystack, size_t haystack_length, +size_t SearchString(const char *haystack, size_t haystack_length, const char (&needle)[N]) { return SearchString( - reinterpret_cast(haystack), haystack_length, - reinterpret_cast(needle), N - 1, 0, true); + reinterpret_cast(haystack), haystack_length, + reinterpret_cast(needle), N - 1, 0, true); } // ============================================================================ // Version metadata -#define NBYTES_VERSION "0.0.1" +#define NBYTES_VERSION "0.1.0" enum { NBYTES_VERSION_MAJOR = 0, - NBYTES_VERSION_MINOR = 0, - NBYTES_VERSION_REVISION = 1, + NBYTES_VERSION_MINOR = 1, + NBYTES_VERSION_REVISION = 0, }; } // namespace nbytes + +#endif // NBYTES_H diff --git a/deps/nbytes/nbytes.gyp b/deps/nbytes/nbytes.gyp index 0c1b76752e98b5..1d82c3760d54e6 100644 --- a/deps/nbytes/nbytes.gyp +++ b/deps/nbytes/nbytes.gyp @@ -1,14 +1,14 @@ { 'variables': { - 'nbytes_sources': [ 'nbytes.cpp' ], + 'nbytes_sources': [ 'src/nbytes.cpp' ], }, 'targets': [ { 'target_name': 'nbytes', 'type': 'static_library', - 'include_dirs': ['.'], + 'include_dirs': ['src', 'include'], 'direct_dependent_settings': { - 'include_dirs': ['.'], + 'include_dirs': ['src', 'include'], }, 'sources': [ '<@(nbytes_sources)' ] }, diff --git a/deps/nbytes/pyproject.toml b/deps/nbytes/pyproject.toml new file mode 100644 index 00000000000000..5e107c7fcd9e1a --- /dev/null +++ b/deps/nbytes/pyproject.toml @@ -0,0 +1,38 @@ +[project] +name = "nbytes" +requires-python = ">=3.12" + +[tool.ruff] +line-length = 120 +target-version = "py312" + +[tool.ruff.format] +quote-style = "single" +indent-style = "space" +docstring-code-format = true + +[tool.ruff.lint] +select = [ + "C90", # McCabe cyclomatic complexity + "E", # pycodestyle + "F", # Pyflakes + "ICN", # flake8-import-conventions + "INT", # flake8-gettext + "PLC", # Pylint conventions + "PLE", # Pylint errors + "PLR09", # Pylint refactoring: max-args, max-branches, max returns, max-statements + "PYI", # flake8-pyi + "RSE", # flake8-raise + "RUF", # Ruff-specific rules + "T10", # flake8-debugger + "TCH", # flake8-type-checking + "TID", # flake8-tidy-imports + "W", # pycodestyle + "YTT", # flake8-2020 + "ANN" # flake8-annotations +] +ignore = [ + "E722", # Do not use bare `except` + "ANN101", # Missing type annotation for self in method + "TID252", # Prefer absolute imports over relative imports from parent modules +] diff --git a/deps/nbytes/src/CMakeLists.txt b/deps/nbytes/src/CMakeLists.txt new file mode 100644 index 00000000000000..554fb4a014a6fd --- /dev/null +++ b/deps/nbytes/src/CMakeLists.txt @@ -0,0 +1,6 @@ +add_library(nbytes nbytes.cpp) +target_include_directories(nbytes + PUBLIC + $ + $ +) diff --git a/deps/nbytes/nbytes.cpp b/deps/nbytes/src/nbytes.cpp similarity index 62% rename from deps/nbytes/nbytes.cpp rename to deps/nbytes/src/nbytes.cpp index 4eb4b6e6aa72a8..149f2163ad7268 100644 --- a/deps/nbytes/nbytes.cpp +++ b/deps/nbytes/src/nbytes.cpp @@ -1,7 +1,7 @@ #include "nbytes.h" -#include #include #include +#include namespace nbytes { @@ -12,13 +12,13 @@ namespace { // These are defined by or on some systems. // To avoid warnings, undefine them before redefining them. #ifdef BSWAP_2 -# undef BSWAP_2 +#undef BSWAP_2 #endif #ifdef BSWAP_4 -# undef BSWAP_4 +#undef BSWAP_4 #endif #ifdef BSWAP_8 -# undef BSWAP_8 +#undef BSWAP_8 #endif #if defined(_MSC_VER) @@ -28,30 +28,28 @@ namespace { #define BSWAP_8(x) _byteswap_uint64(x) #else #define BSWAP_2(x) ((x) << 8) | ((x) >> 8) -#define BSWAP_4(x) \ - (((x) & 0xFF) << 24) | \ - (((x) & 0xFF00) << 8) | \ - (((x) >> 8) & 0xFF00) | \ - (((x) >> 24) & 0xFF) -#define BSWAP_8(x) \ - (((x) & 0xFF00000000000000ull) >> 56) | \ - (((x) & 0x00FF000000000000ull) >> 40) | \ - (((x) & 0x0000FF0000000000ull) >> 24) | \ - (((x) & 0x000000FF00000000ull) >> 8) | \ - (((x) & 0x00000000FF000000ull) << 8) | \ - (((x) & 0x0000000000FF0000ull) << 24) | \ - (((x) & 0x000000000000FF00ull) << 40) | \ - (((x) & 0x00000000000000FFull) << 56) +#define BSWAP_4(x) \ + (((x) & 0xFF) << 24) | (((x) & 0xFF00) << 8) | (((x) >> 8) & 0xFF00) | \ + (((x) >> 24) & 0xFF) +#define BSWAP_8(x) \ + (((x) & 0xFF00000000000000ull) >> 56) | \ + (((x) & 0x00FF000000000000ull) >> 40) | \ + (((x) & 0x0000FF0000000000ull) >> 24) | \ + (((x) & 0x000000FF00000000ull) >> 8) | \ + (((x) & 0x00000000FF000000ull) << 8) | \ + (((x) & 0x0000000000FF0000ull) << 24) | \ + (((x) & 0x000000000000FF00ull) << 40) | \ + (((x) & 0x00000000000000FFull) << 56) #endif } // namespace -bool SwapBytes16(void* data, size_t nbytes) { +bool SwapBytes16(void *data, size_t nbytes) { if (nbytes % sizeof(uint16_t) != 0) return false; #if defined(_MSC_VER) if (AlignUp(data, sizeof(uint16_t)) == data) { // MSVC has no strict aliasing, and is able to highly optimize this case. - uint16_t* data16 = reinterpret_cast(data); + uint16_t *data16 = reinterpret_cast(data); size_t len16 = nbytes / sizeof(uint16_t); for (size_t i = 0; i < len16; i++) { data16[i] = BSWAP_2(data16[i]); @@ -61,7 +59,7 @@ bool SwapBytes16(void* data, size_t nbytes) { #endif uint16_t temp; - uint8_t* ptr = reinterpret_cast(data); + uint8_t *ptr = reinterpret_cast(data); for (size_t i = 0; i < nbytes; i += sizeof(uint16_t)) { memcpy(&temp, &ptr[i], sizeof(uint16_t)); temp = BSWAP_2(temp); @@ -71,13 +69,13 @@ bool SwapBytes16(void* data, size_t nbytes) { return true; } -bool SwapBytes32(void* data, size_t nbytes) { +bool SwapBytes32(void *data, size_t nbytes) { if (nbytes % sizeof(uint32_t) != 0) return false; #if defined(_MSC_VER) // MSVC has no strict aliasing, and is able to highly optimize this case. if (AlignUp(data, sizeof(uint32_t)) == data) { - uint32_t* data32 = reinterpret_cast(data); + uint32_t *data32 = reinterpret_cast(data); size_t len32 = nbytes / sizeof(uint32_t); for (size_t i = 0; i < len32; i++) { data32[i] = BSWAP_4(data32[i]); @@ -87,7 +85,7 @@ bool SwapBytes32(void* data, size_t nbytes) { #endif uint32_t temp = 0; - uint8_t* ptr = reinterpret_cast(data); + uint8_t *ptr = reinterpret_cast(data); for (size_t i = 0; i < nbytes; i += sizeof(uint32_t)) { memcpy(&temp, &ptr[i], sizeof(uint32_t)); temp = BSWAP_4(temp); @@ -97,13 +95,13 @@ bool SwapBytes32(void* data, size_t nbytes) { return true; } -bool SwapBytes64(void* data, size_t nbytes) { +bool SwapBytes64(void *data, size_t nbytes) { if (nbytes % sizeof(uint64_t) != 0) return false; #if defined(_MSC_VER) if (AlignUp(data, sizeof(uint64_t)) == data) { // MSVC has no strict aliasing, and is able to highly optimize this case. - uint64_t* data64 = reinterpret_cast(data); + uint64_t *data64 = reinterpret_cast(data); size_t len64 = nbytes / sizeof(uint64_t); for (size_t i = 0; i < len64; i++) { data64[i] = BSWAP_8(data64[i]); @@ -113,7 +111,7 @@ bool SwapBytes64(void* data, size_t nbytes) { #endif uint64_t temp = 0; - uint8_t* ptr = reinterpret_cast(data); + uint8_t *ptr = reinterpret_cast(data); for (size_t i = 0; i < nbytes; i += sizeof(uint64_t)) { memcpy(&temp, &ptr[i], sizeof(uint64_t)); temp = BSWAP_8(temp); @@ -127,56 +125,45 @@ bool SwapBytes64(void* data, size_t nbytes) { // Base64 (legacy) // supports regular and URL-safe base64 -const int8_t unbase64_table[256] = - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -1, -1, -2, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, 62, -1, 63, - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, - -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, 63, - -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, - 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 - }; +const int8_t unbase64_table[256] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -1, -1, -2, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 62, -1, 62, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, + 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, + 63, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, + 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1}; // ============================================================================ // Hex -const int8_t unhex_table[256] = - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, - -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 - }; - -size_t HexEncode( - const char* src, - size_t slen, - char* dst, - size_t dlen) { +const int8_t unhex_table[256] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, + 9, -1, -1, -1, -1, -1, -1, -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1}; + +size_t HexEncode(const char *src, size_t slen, char *dst, size_t dlen) { // We know how much we'll write, just make sure that there's space. - NBYTES_ASSERT_TRUE( - dlen >= MultiplyWithOverflowCheck(slen, 2u) && - "not enough space provided for hex encode"); + NBYTES_ASSERT_TRUE(dlen >= MultiplyWithOverflowCheck(slen, 2u) && + "not enough space provided for hex encode"); dlen = slen * 2; for (size_t i = 0, k = 0; k < dlen; i += 1, k += 2) { @@ -189,7 +176,7 @@ size_t HexEncode( return dlen; } -std::string HexEncode(const char* src, size_t slen) { +std::string HexEncode(const char *src, size_t slen) { size_t dlen = slen * 2; std::string dst(dlen, '\0'); HexEncode(src, slen, dst.data(), dlen); @@ -198,13 +185,13 @@ std::string HexEncode(const char* src, size_t slen) { // ============================================================================ -void ForceAsciiSlow(const char* src, char* dst, size_t len) { +void ForceAsciiSlow(const char *src, char *dst, size_t len) { for (size_t i = 0; i < len; ++i) { dst[i] = src[i] & 0x7f; } } -void ForceAscii(const char* src, char* dst, size_t len) { +void ForceAscii(const char *src, char *dst, size_t len) { if (len < 16) { ForceAsciiSlow(src, dst, len); return; @@ -234,8 +221,8 @@ void ForceAscii(const char* src, char* dst, size_t len) { const uintptr_t mask = ~0x80808080l; #endif - const uintptr_t* srcw = reinterpret_cast(src); - uintptr_t* dstw = reinterpret_cast(dst); + const uintptr_t *srcw = reinterpret_cast(src); + uintptr_t *dstw = reinterpret_cast(dst); for (size_t i = 0, n = len / bytes_per_word; i < n; ++i) { dstw[i] = srcw[i] & mask; diff --git a/deps/nbytes/tests/CMakeLists.txt b/deps/nbytes/tests/CMakeLists.txt new file mode 100644 index 00000000000000..00fc8cb2608302 --- /dev/null +++ b/deps/nbytes/tests/CMakeLists.txt @@ -0,0 +1,10 @@ +include(GoogleTest) +include(CTest) +add_executable(basic basic.cpp) +target_link_libraries( + basic + GTest::gtest_main +) +target_link_libraries(basic nbytes) +add_test(basic_test basic) +gtest_discover_tests(basic) diff --git a/deps/nbytes/tests/basic.cpp b/deps/nbytes/tests/basic.cpp new file mode 100644 index 00000000000000..8f0a8635cbece8 --- /dev/null +++ b/deps/nbytes/tests/basic.cpp @@ -0,0 +1,7 @@ +#include +#include +#include + +#include + +TEST(basic, it_works) { SUCCEED(); } diff --git a/deps/nbytes/tools/run-clang-format.sh b/deps/nbytes/tools/run-clang-format.sh new file mode 100755 index 00000000000000..ce1a664a890af8 --- /dev/null +++ b/deps/nbytes/tools/run-clang-format.sh @@ -0,0 +1,42 @@ +#!/usr/bin/env bash + +# Copyright 2023 Yagiz Nizipli and Daniel Lemire + +# Permission is hereby granted, free of charge, to any person obtaining a copy of +# this software and associated documentation files (the "Software"), to deal in +# the Software without restriction, including without limitation the rights to +# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +# the Software, and to permit persons to whom the Software is furnished to do so, +# subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +set -e +COMMAND=$* +SCRIPTPATH="$( cd "$(dirname "$0")" ; pwd -P )" +MAINSOURCE=$SCRIPTPATH/.. +ALL_FILES=$(cd $MAINSOURCE && git ls-tree --full-tree --name-only -r HEAD | grep -e ".*\.\(c\|h\|cc\|cpp\|hh\)\$") + +if clang-format-17 --version 2>/dev/null | grep -qF 'version 17.'; then + cd $MAINSOURCE; clang-format-17 --style=file --verbose -i "$@" $ALL_FILES + exit 0 +elif clang-format --version 2>/dev/null | grep -qF 'version 17.'; then + cd $MAINSOURCE; clang-format --style=file --verbose -i "$@" $ALL_FILES + exit 0 +fi +echo "Trying to use docker" +command -v docker >/dev/null 2>&1 || { echo >&2 "Please install docker. E.g., go to https://www.docker.com/products/docker-desktop Type 'docker' to diagnose the problem."; exit 1; } +docker info >/dev/null 2>&1 || { echo >&2 "Docker server is not running? type 'docker info'."; exit 1; } + +if [ -t 0 ]; then DOCKER_ARGS=-it; fi +docker pull kszonek/clang-format-17 + +docker run --rm $DOCKER_ARGS -v "$MAINSOURCE":"$MAINSOURCE":Z -w "$MAINSOURCE" -u "$(id -u $USER):$(id -g $USER)" kszonek/clang-format-17 --style=file --verbose -i "$@" $ALL_FILES diff --git a/tools/dep_updaters/update-nbytes.sh b/tools/dep_updaters/update-nbytes.sh new file mode 100755 index 00000000000000..b86598bf44b94c --- /dev/null +++ b/tools/dep_updaters/update-nbytes.sh @@ -0,0 +1,61 @@ +#!/bin/sh +set -e +# Shell script to update nbytes in the source tree to a specific version + +BASE_DIR=$(cd "$(dirname "$0")/../.." && pwd) +DEPS_DIR="$BASE_DIR/deps" +[ -z "$NODE" ] && NODE="$BASE_DIR/out/Release/node" +[ -x "$NODE" ] || NODE=$(command -v node) + +# shellcheck disable=SC1091 +. "$BASE_DIR/tools/dep_updaters/utils.sh" + +NEW_VERSION="$("$NODE" --input-type=module <<'EOF' +const res = await fetch('https://api.github.com/repos/nodejs/nbytes/releases/latest', + process.env.GITHUB_TOKEN && { + headers: { + "Authorization": `Bearer ${process.env.GITHUB_TOKEN}` + }, + }); +if (!res.ok) throw new Error(`FetchError: ${res.status} ${res.statusText}`, { cause: res }); +const { tag_name } = await res.json(); +console.log(tag_name.replace('v', '')); +EOF +)" + +CURRENT_VERSION=$(grep "#define NBYTES_VERSION" "$DEPS_DIR/nbytes/nbytes.h" | sed -n "s/^.*VERSION \"\(.*\)\"/\1/p") + +# This function exit with 0 if new version and current version are the same +compare_dependency_version "nbytes" "$NEW_VERSION" "$CURRENT_VERSION" + +echo "Making temporary workspace..." + +WORKSPACE=$(mktemp -d 2> /dev/null || mktemp -d -t 'tmp') + +cleanup () { + EXIT_CODE=$? + [ -d "$WORKSPACE" ] && rm -rf "$WORKSPACE" + exit $EXIT_CODE +} + +trap cleanup INT TERM EXIT + +cd "$WORKSPACE" + +echo "Fetching nbytes source archive..." +NBYTES_TARBALL="nbytes-v$NEW_VERSION.tar.gz" +curl -sL -o "$NBYTES_TARBALL" "https://api.github.com/repos/nodejs/nbytes/tarball/v$NEW_VERSION" +log_and_verify_sha256sum "nbytes" "$NBYTES_TARBALL" +gzip -dc "$NBYTES_TARBALL" | tar xf - +mv nodejs-nbytes-* source +rm "$NBYTES_TARBALL" + +echo "Replacing existing nbytes (except GYP and GN build files)" +mv "$DEPS_DIR/nbytes/"*.gyp "$DEPS_DIR/nbytes/"*.gn "$DEPS_DIR/nbytes/"*.gni "$DEPS_DIR/nbytes/README.md" "$WORKSPACE/source" +rm -rf "$DEPS_DIR/nbytes" +mv "$WORKSPACE/source" "$DEPS_DIR/nbytes" + +# Update the version number on maintaining-dependencies.md +# and print the new version as the last line of the script as we need +# to add it to $GITHUB_ENV variable +finalize_version_update "nbytes" "$NEW_VERSION"