Coverage Report

Created: 2025-08-29 06:43

/src/simdutf/src/westmere/sse_utf16fix.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Process one block of 8 characters.  If in_place is false,
3
 * copy the block from in to out.  If there is a sequencing
4
 * error in the block, overwrite the illsequenced characters
5
 * with the replacement character.  This function reads one
6
 * character before the beginning of the buffer as a lookback.
7
 * If that character is illsequenced, it too is overwritten.
8
 */
9
template <endianness big_endian, bool in_place>
10
simdutf_really_inline void utf16fix_block_sse(char16_t *out,
11
0
                                              const char16_t *in) {
12
0
  const char16_t replacement = scalar::utf16::replacement<big_endian>();
13
0
  auto swap_if_needed = [](uint16_t c) -> uint16_t {
14
0
    return !simdutf::match_system(big_endian) ? scalar::u16_swap_bytes(c) : c;
15
0
  };
Unexecuted instantiation: simdutf.cpp:simdutf::westmere::(anonymous namespace)::utf16fix_block_sse<(simdutf::endianness)0, true>(char16_t*, char16_t const*)::{lambda(unsigned short)#1}::operator()(unsigned short) const
Unexecuted instantiation: simdutf.cpp:simdutf::westmere::(anonymous namespace)::utf16fix_block_sse<(simdutf::endianness)0, false>(char16_t*, char16_t const*)::{lambda(unsigned short)#1}::operator()(unsigned short) const
Unexecuted instantiation: simdutf.cpp:simdutf::westmere::(anonymous namespace)::utf16fix_block_sse<(simdutf::endianness)1, true>(char16_t*, char16_t const*)::{lambda(unsigned short)#1}::operator()(unsigned short) const
Unexecuted instantiation: simdutf.cpp:simdutf::westmere::(anonymous namespace)::utf16fix_block_sse<(simdutf::endianness)1, false>(char16_t*, char16_t const*)::{lambda(unsigned short)#1}::operator()(unsigned short) const
16
17
0
  __m128i lookback, block, lb_masked, block_masked, lb_is_high, block_is_low;
18
0
  __m128i illseq, lb_illseq, block_illseq;
19
20
0
  lookback = _mm_loadu_si128((const __m128i *)(in - 1));
21
0
  block = _mm_loadu_si128((const __m128i *)in);
22
0
  lb_masked = _mm_and_si128(lookback, _mm_set1_epi16(swap_if_needed(0xfc00U)));
23
0
  block_masked = _mm_and_si128(block, _mm_set1_epi16(swap_if_needed(0xfc00U)));
24
0
  lb_is_high =
25
0
      _mm_cmpeq_epi16(lb_masked, _mm_set1_epi16(swap_if_needed(0xd800U)));
26
0
  block_is_low =
27
0
      _mm_cmpeq_epi16(block_masked, _mm_set1_epi16(swap_if_needed(0xdc00U)));
28
29
0
  illseq = _mm_xor_si128(lb_is_high, block_is_low);
30
0
  if (_mm_movemask_epi8(illseq) != 0) {
31
0
    int lb;
32
33
    /* compute the cause of the illegal sequencing */
34
0
    lb_illseq = _mm_andnot_si128(block_is_low, lb_is_high);
35
0
    block_illseq = _mm_or_si128(_mm_andnot_si128(lb_is_high, block_is_low),
36
0
                                _mm_bsrli_si128(lb_illseq, 2));
37
38
    /* fix illegal sequencing in the lookback */
39
0
    lb = _mm_cvtsi128_si32(lb_illseq);
40
0
    lb = (lb & replacement) | (~lb & out[-1]);
41
0
    out[-1] = char16_t(lb);
42
    /* fix illegal sequencing in the main block */
43
0
    block =
44
0
        _mm_or_si128(_mm_andnot_si128(block_illseq, block),
45
0
                     _mm_and_si128(block_illseq, _mm_set1_epi16(replacement)));
46
0
    _mm_storeu_si128((__m128i *)out, block);
47
0
  } else if (!in_place) {
48
0
    _mm_storeu_si128((__m128i *)out, block);
49
0
  }
50
0
}
Unexecuted instantiation: simdutf.cpp:void simdutf::westmere::(anonymous namespace)::utf16fix_block_sse<(simdutf::endianness)0, true>(char16_t*, char16_t const*)
Unexecuted instantiation: simdutf.cpp:void simdutf::westmere::(anonymous namespace)::utf16fix_block_sse<(simdutf::endianness)0, false>(char16_t*, char16_t const*)
Unexecuted instantiation: simdutf.cpp:void simdutf::westmere::(anonymous namespace)::utf16fix_block_sse<(simdutf::endianness)1, true>(char16_t*, char16_t const*)
Unexecuted instantiation: simdutf.cpp:void simdutf::westmere::(anonymous namespace)::utf16fix_block_sse<(simdutf::endianness)1, false>(char16_t*, char16_t const*)
51
52
template <endianness big_endian>
53
0
void utf16fix_sse(const char16_t *in, size_t n, char16_t *out) {
54
0
  const char16_t replacement = scalar::utf16::replacement<big_endian>();
55
0
  size_t i;
56
0
  if (n < 9) {
57
0
    scalar::utf16::to_well_formed_utf16<big_endian>(in, n, out);
58
0
    return;
59
0
  }
60
61
0
  out[0] =
62
0
      scalar::utf16::is_low_surrogate<big_endian>(in[0]) ? replacement : in[0];
63
64
  /* duplicate code to have the compiler specialise utf16fix_block() */
65
0
  if (in == out) {
66
0
    for (i = 1; i + 8 < n; i += 8) {
67
0
      utf16fix_block_sse<big_endian, true>(out + i, in + i);
68
0
    }
69
70
0
    utf16fix_block_sse<big_endian, true>(out + n - 8, in + n - 8);
71
0
  } else {
72
0
    for (i = 1; i + 8 < n; i += 8) {
73
0
      utf16fix_block_sse<big_endian, false>(out + i, in + i);
74
0
    }
75
76
0
    utf16fix_block_sse<big_endian, false>(out + n - 8, in + n - 8);
77
0
  }
78
79
0
  out[n - 1] = scalar::utf16::is_high_surrogate<big_endian>(out[n - 1])
80
0
                   ? replacement
81
0
                   : out[n - 1];
82
0
}
Unexecuted instantiation: simdutf.cpp:void simdutf::westmere::(anonymous namespace)::utf16fix_sse<(simdutf::endianness)0>(char16_t const*, unsigned long, char16_t*)
Unexecuted instantiation: simdutf.cpp:void simdutf::westmere::(anonymous namespace)::utf16fix_sse<(simdutf::endianness)1>(char16_t const*, unsigned long, char16_t*)