| 275 | |
| 276 | template <typename BufferedByteReader> |
| 277 | std::pair<size_t, bool> Utf8ValidateImpl(BufferedByteReader* reader) { |
| 278 | size_t count = 0; |
| 279 | while (reader->HasRemaining()) { |
| 280 | const auto b = static_cast<uint8_t>(reader->Read()); |
| 281 | if (b < kUtf8RuneSelf) { |
| 282 | count++; |
| 283 | continue; |
| 284 | } |
| 285 | const auto leading = kLeading[b]; |
| 286 | if (leading == kXX) { |
| 287 | return {count, false}; |
| 288 | } |
| 289 | const auto size = static_cast<size_t>(leading & 7) - 1; |
| 290 | if (size > reader->Remaining()) { |
| 291 | return {count, false}; |
| 292 | } |
| 293 | const absl::string_view segment = reader->Peek(size); |
| 294 | const auto& accept = kAccept[leading >> 4]; |
| 295 | if (static_cast<uint8_t>(segment[0]) < accept.first || |
| 296 | static_cast<uint8_t>(segment[0]) > accept.second) { |
| 297 | return {count, false}; |
| 298 | } else if (size == 1) { |
| 299 | count++; |
| 300 | } else if (static_cast<uint8_t>(segment[1]) < kLow || |
| 301 | static_cast<uint8_t>(segment[1]) > kHigh) { |
| 302 | return {count, false}; |
| 303 | } else if (size == 2) { |
| 304 | count++; |
| 305 | } else if (static_cast<uint8_t>(segment[2]) < kLow || |
| 306 | static_cast<uint8_t>(segment[2]) > kHigh) { |
| 307 | return {count, false}; |
| 308 | } else { |
| 309 | count++; |
| 310 | } |
| 311 | reader->Advance(size); |
| 312 | } |
| 313 | return {count, true}; |
| 314 | } |
| 315 | |
| 316 | } // namespace |
| 317 |
no test coverage detected