| 239 | |
| 240 | template <typename BufferedByteReader> |
| 241 | size_t Utf8CodePointCountImpl(BufferedByteReader* reader) { |
| 242 | size_t count = 0; |
| 243 | while (reader->HasRemaining()) { |
| 244 | count++; |
| 245 | const auto b = static_cast<uint8_t>(reader->Read()); |
| 246 | if (b < kUtf8RuneSelf) { |
| 247 | continue; |
| 248 | } |
| 249 | const auto leading = kLeading[b]; |
| 250 | if (leading == kXX) { |
| 251 | continue; |
| 252 | } |
| 253 | auto size = static_cast<size_t>(leading & 7) - 1; |
| 254 | if (size > reader->Remaining()) { |
| 255 | continue; |
| 256 | } |
| 257 | const absl::string_view segment = reader->Peek(size); |
| 258 | const auto& accept = kAccept[leading >> 4]; |
| 259 | if (static_cast<uint8_t>(segment[0]) < accept.first || |
| 260 | static_cast<uint8_t>(segment[0]) > accept.second) { |
| 261 | size = 0; |
| 262 | } else if (size == 1) { |
| 263 | } else if (static_cast<uint8_t>(segment[1]) < kLow || |
| 264 | static_cast<uint8_t>(segment[1]) > kHigh) { |
| 265 | size = 0; |
| 266 | } else if (size == 2) { |
| 267 | } else if (static_cast<uint8_t>(segment[2]) < kLow || |
| 268 | static_cast<uint8_t>(segment[2]) > kHigh) { |
| 269 | size = 0; |
| 270 | } |
| 271 | reader->Advance(size); |
| 272 | } |
| 273 | return count; |
| 274 | } |
| 275 | |
| 276 | template <typename BufferedByteReader> |
| 277 | std::pair<size_t, bool> Utf8ValidateImpl(BufferedByteReader* reader) { |
no test coverage detected