// Glaze Library // For the license information refer to glaze.hpp #pragma once #include "glaze/simd/simd.hpp" #include "glaze/util/inline.hpp" #if defined(GLZ_USE_NEON) namespace glz::detail { GLZ_ALWAYS_INLINE uint8_t neon_hmax_u8(const uint8x16_t v) noexcept { #if defined(__aarch64__) || defined(_M_ARM64) return vmaxvq_u8(v); #else uint8x8_t max8 = vmax_u8(vget_low_u8(v), vget_high_u8(v)); max8 = vpmax_u8(max8, max8); max8 = vpmax_u8(max8, max8); max8 = vpmax_u8(max8, max8); return vget_lane_u8(max8, 0); #endif } template GLZ_ALWAYS_INLINE void neon_string_escape(const char*& c, const char* e, Data*& data, size_t n, WriteEscape&& write_escape) { if (n > 15) { const uint8x16_t quote_vec = vdupq_n_u8('"'); const uint8x16_t bs_vec = vdupq_n_u8('\\'); const uint8x16_t ctrl_threshold = vdupq_n_u8(0x20); auto check = [&](uint8x16_t v) { return vorrq_u8(vorrq_u8(vceqq_u8(v, quote_vec), vceqq_u8(v, bs_vec)), vcltq_u8(v, ctrl_threshold)); }; // Wide path: 64 bytes (4×16) per iteration to reduce loop overhead. // When an escape is found anywhere in the 64-byte region, fall through // to the 16-byte loop which locates the exact position. for (const char* end_m63 = e - 63; c < end_m63;) { const uint8x16_t v0 = vld1q_u8(reinterpret_cast(c)); const uint8x16_t v1 = vld1q_u8(reinterpret_cast(c + 16)); const uint8x16_t v2 = vld1q_u8(reinterpret_cast(c + 32)); const uint8x16_t v3 = vld1q_u8(reinterpret_cast(c + 48)); vst1q_u8(reinterpret_cast(data), v0); vst1q_u8(reinterpret_cast(data + 16), v1); vst1q_u8(reinterpret_cast(data + 32), v2); vst1q_u8(reinterpret_cast(data + 48), v3); const uint8x16_t any = vorrq_u8(vorrq_u8(check(v0), check(v1)), vorrq_u8(check(v2), check(v3))); if (neon_hmax_u8(any) == 0) { data += 64; c += 64; continue; } // Escape found somewhere in the 64-byte region. // Fall through to the 16-byte loop to locate and handle it. break; } // 16-byte loop: handles the tail and any escape found in the wide path. for (const char* end_m15 = e - 15; c < end_m15;) { const uint8x16_t v = vld1q_u8(reinterpret_cast(c)); vst1q_u8(reinterpret_cast(data), v); // speculative store if (neon_hmax_u8(check(v)) == 0) { data += 16; c += 16; continue; } // Scalar scan to find first escapable byte — guaranteed to find one // within the 16-byte chunk that neon_hmax_u8 flagged. // The speculative store already wrote clean bytes ahead of this position. while (uint8_t(*c) >= 0x20 && uint8_t(*c) != '"' && uint8_t(*c) != '\\') { ++data; ++c; } write_escape(); } } } } #endif