| 11483 | bool IsUTF8TrailByte(unsigned char t) { return 0x80 <= t && t<= 0xbf; } |
| 11484 | |
| 11485 | bool IsValidUTF8(const char* str, size_t length) { |
| 11486 | const unsigned char *s = reinterpret_cast<const unsigned char *>(str); |
| 11487 | |
| 11488 | for (size_t i = 0; i < length;) { |
| 11489 | unsigned char lead = s[i++]; |
| 11490 | |
| 11491 | if (lead <= 0x7f) { |
| 11492 | continue; // single-byte character (ASCII) 0..7F |
| 11493 | } |
| 11494 | if (lead < 0xc2) { |
| 11495 | return false; // trail byte or non-shortest form |
| 11496 | } else if (lead <= 0xdf && (i + 1) <= length && IsUTF8TrailByte(s[i])) { |
| 11497 | ++i; // 2-byte character |
| 11498 | } else if (0xe0 <= lead && lead <= 0xef && (i + 2) <= length && |
| 11499 | IsUTF8TrailByte(s[i]) && |
| 11500 | IsUTF8TrailByte(s[i + 1]) && |
| 11501 | // check for non-shortest form and surrogate |
| 11502 | (lead != 0xe0 || s[i] >= 0xa0) && |
| 11503 | (lead != 0xed || s[i] < 0xa0)) { |
| 11504 | i += 2; // 3-byte character |
| 11505 | } else if (0xf0 <= lead && lead <= 0xf4 && (i + 3) <= length && |
| 11506 | IsUTF8TrailByte(s[i]) && |
| 11507 | IsUTF8TrailByte(s[i + 1]) && |
| 11508 | IsUTF8TrailByte(s[i + 2]) && |
| 11509 | // check for non-shortest form |
| 11510 | (lead != 0xf0 || s[i] >= 0x90) && |
| 11511 | (lead != 0xf4 || s[i] < 0x90)) { |
| 11512 | i += 3; // 4-byte character |
| 11513 | } else { |
| 11514 | return false; |
| 11515 | } |
| 11516 | } |
| 11517 | return true; |
| 11518 | } |
| 11519 | |
| 11520 | void ConditionalPrintAsText(const char* str, size_t length, ostream* os) { |
| 11521 | if (!ContainsUnprintableControlCodes(str, length) && |
no test coverage detected