// Glaze Library // For the license information refer to glaze.hpp #pragma once #include "glaze/simd/simd.hpp" #include "glaze/util/bit.hpp" #include "glaze/util/inline.hpp" #if defined(GLZ_USE_AVX2) namespace glz::detail { template GLZ_ALWAYS_INLINE void avx2_string_escape(const char*& c, const char* e, Data*& data, size_t n, WriteEscape&& write_escape) { // AVX2: 32 bytes at a time with direct comparison instructions if (n > 31) { const __m256i quote_vec = _mm256_set1_epi8('"'); const __m256i bs_vec = _mm256_set1_epi8('\\'); // Control char detection: (v & 0xE0) == 0 iff v is 0x00-0x1F const __m256i ctrl_mask = _mm256_set1_epi8(static_cast(0xE0)); const __m256i zero = _mm256_setzero_si256(); for (const char* end_m31 = e - 31; c < end_m31;) { __m256i v = _mm256_loadu_si256(reinterpret_cast(c)); _mm256_storeu_si256(reinterpret_cast<__m256i*>(data), v); const uint32_t mask = _mm256_movemask_epi8( _mm256_or_si256(_mm256_or_si256(_mm256_cmpeq_epi8(v, quote_vec), _mm256_cmpeq_epi8(v, bs_vec)), _mm256_cmpeq_epi8(_mm256_and_si256(v, ctrl_mask), zero))); if (mask == 0) { data += 32; c += 32; continue; } const uint32_t length = countr_zero(mask); c += length; data += length; write_escape(); } } } } #endif