73 v_delim.fill(delimiter);
74 v_quote.fill(quote_char);
79 std::array<char, 32> v_delim, v_quote, v_lf, v_cr;
82 static_assert(
sizeof(
SentinelVecs) == 128,
"SentinelVecs layout must stay ISA-independent.");
83 static_assert(
alignof(
SentinelVecs) <=
alignof(
void*),
"SentinelVecs must not require over-aligned allocation.");
96 inline size_t find_next_non_special(
102#if defined(CSV_SIMD_AVX2)
103 const __m256i v_delim = _mm256_loadu_si256(
reinterpret_cast<const __m256i*
>(sentinels.v_delim.data()));
104 const __m256i v_quote = _mm256_loadu_si256(
reinterpret_cast<const __m256i*
>(sentinels.v_quote.data()));
105 const __m256i v_lf = _mm256_loadu_si256(
reinterpret_cast<const __m256i*
>(sentinels.v_lf.data()));
106 const __m256i v_cr = _mm256_loadu_si256(
reinterpret_cast<const __m256i*
>(sentinels.v_cr.data()));
108 while (pos + 32 <= data.size()) {
109 __m256i bytes = _mm256_loadu_si256(
reinterpret_cast<const __m256i*
>(data.data() + pos));
110 __m256i special = _mm256_cmpeq_epi8(bytes, v_delim);
111 special = _mm256_or_si256(special, _mm256_cmpeq_epi8(bytes, v_quote));
112 special = _mm256_or_si256(special, _mm256_cmpeq_epi8(bytes, v_lf));
113 special = _mm256_or_si256(special, _mm256_cmpeq_epi8(bytes, v_cr));
114 int mask = _mm256_movemask_epi8(special);
117 return pos + CSV_TZCNT32(
static_cast<unsigned>(mask));
120#elif defined(CSV_SIMD_SSE2)
121 const __m128i v_delim = _mm_loadu_si128(
reinterpret_cast<const __m128i*
>(sentinels.v_delim.data()));
122 const __m128i v_quote = _mm_loadu_si128(
reinterpret_cast<const __m128i*
>(sentinels.v_quote.data()));
123 const __m128i v_lf = _mm_loadu_si128(
reinterpret_cast<const __m128i*
>(sentinels.v_lf.data()));
124 const __m128i v_cr = _mm_loadu_si128(
reinterpret_cast<const __m128i*
>(sentinels.v_cr.data()));
126 while (pos + 16 <= data.size()) {
127 __m128i bytes = _mm_loadu_si128(
reinterpret_cast<const __m128i*
>(data.data() + pos));
128 __m128i special = _mm_cmpeq_epi8(bytes, v_delim);
129 special = _mm_or_si128(special, _mm_cmpeq_epi8(bytes, v_quote));
130 special = _mm_or_si128(special, _mm_cmpeq_epi8(bytes, v_lf));
131 special = _mm_or_si128(special, _mm_cmpeq_epi8(bytes, v_cr));
132 int mask = _mm_movemask_epi8(special);
135 return pos + CSV_TZCNT32(
static_cast<unsigned>(mask));
138#elif defined(CSV_SIMD_NEON)
139 const uint8x16_t v_delim = vld1q_u8(
reinterpret_cast<const uint8_t*
>(sentinels.v_delim.data()));
140 const uint8x16_t v_quote = vld1q_u8(
reinterpret_cast<const uint8_t*
>(sentinels.v_quote.data()));
141 const uint8x16_t v_lf = vld1q_u8(
reinterpret_cast<const uint8_t*
>(sentinels.v_lf.data()));
142 const uint8x16_t v_cr = vld1q_u8(
reinterpret_cast<const uint8_t*
>(sentinels.v_cr.data()));
144 while (pos + 16 <= data.size()) {
145 const uint8x16_t bytes = vld1q_u8(
reinterpret_cast<const uint8_t*
>(data.data() + pos));
146 uint8x16_t special = vceqq_u8(bytes, v_delim);
147 special = vorrq_u8(special, vceqq_u8(bytes, v_quote));
148 special = vorrq_u8(special, vceqq_u8(bytes, v_lf));
149 special = vorrq_u8(special, vceqq_u8(bytes, v_cr));
151#if defined(__aarch64__) || defined(_M_ARM64)
152 if (vmaxvq_u8(special) == 0) {
159 vst1q_u8(lanes, special);
160 for (
size_t i = 0; i < 16; ++i) {
167 (void)data; (void)sentinels;