| 11504 | // For use within get_host_delimiter_location. |
| 11505 | #if ADA_NEON |
| 11506 | ada_really_inline size_t find_next_host_delimiter(std::string_view view, |
| 11507 | size_t location) noexcept { |
| 11508 | // first check for short strings in which case we do it naively. |
| 11509 | if (view.size() - location < 16) { // slow path |
| 11510 | for (size_t i = location; i < view.size(); i++) { |
| 11511 | if (view[i] == ':' || view[i] == '/' || view[i] == '?' || |
| 11512 | view[i] == '[') { |
| 11513 | return i; |
| 11514 | } |
| 11515 | } |
| 11516 | return size_t(view.size()); |
| 11517 | } |
| 11518 | auto to_bitmask = [](uint8x16_t input) -> uint16_t { |
| 11519 | uint8x16_t bit_mask = |
| 11520 | ada_make_uint8x16_t(0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x01, |
| 11521 | 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80); |
| 11522 | uint8x16_t minput = vandq_u8(input, bit_mask); |
| 11523 | uint8x16_t tmp = vpaddq_u8(minput, minput); |
| 11524 | tmp = vpaddq_u8(tmp, tmp); |
| 11525 | tmp = vpaddq_u8(tmp, tmp); |
| 11526 | return vgetq_lane_u16(vreinterpretq_u16_u8(tmp), 0); |
| 11527 | }; |
| 11528 | |
| 11529 | // fast path for long strings (expected to be common) |
| 11530 | size_t i = location; |
| 11531 | uint8x16_t low_mask = |
| 11532 | ada_make_uint8x16_t(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 11533 | 0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x03); |
| 11534 | uint8x16_t high_mask = |
| 11535 | ada_make_uint8x16_t(0x00, 0x00, 0x02, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, |
| 11536 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); |
| 11537 | uint8x16_t fmask = vmovq_n_u8(0xf); |
| 11538 | uint8x16_t zero{0}; |
| 11539 | for (; i + 15 < view.size(); i += 16) { |
| 11540 | uint8x16_t word = vld1q_u8((const uint8_t*)view.data() + i); |
| 11541 | uint8x16_t lowpart = vqtbl1q_u8(low_mask, vandq_u8(word, fmask)); |
| 11542 | uint8x16_t highpart = vqtbl1q_u8(high_mask, vshrq_n_u8(word, 4)); |
| 11543 | uint8x16_t classify = vandq_u8(lowpart, highpart); |
| 11544 | if (vmaxvq_u32(vreinterpretq_u32_u8(classify)) != 0) { |
| 11545 | uint8x16_t is_zero = vceqq_u8(classify, zero); |
| 11546 | uint16_t is_non_zero = ~to_bitmask(is_zero); |
| 11547 | return i + trailing_zeroes(is_non_zero); |
| 11548 | } |
| 11549 | } |
| 11550 | |
| 11551 | if (i < view.size()) { |
| 11552 | uint8x16_t word = |
| 11553 | vld1q_u8((const uint8_t*)view.data() + view.length() - 16); |
| 11554 | uint8x16_t lowpart = vqtbl1q_u8(low_mask, vandq_u8(word, fmask)); |
| 11555 | uint8x16_t highpart = vqtbl1q_u8(high_mask, vshrq_n_u8(word, 4)); |
| 11556 | uint8x16_t classify = vandq_u8(lowpart, highpart); |
| 11557 | if (vmaxvq_u32(vreinterpretq_u32_u8(classify)) != 0) { |
| 11558 | uint8x16_t is_zero = vceqq_u8(classify, zero); |
| 11559 | uint16_t is_non_zero = ~to_bitmask(is_zero); |
| 11560 | return view.length() - 16 + trailing_zeroes(is_non_zero); |
| 11561 | } |
| 11562 | } |
| 11563 | return size_t(view.size()); |
no test coverage detected