| 88 | bool IsTrailingByte(char ch) { return (ch & 0xC0) == 0x80; } |
| 89 | |
| 90 | bool GetNextCodePointAndAdvance(int& codePoint, |
| 91 | std::string::const_iterator& first, |
| 92 | std::string::const_iterator last) { |
| 93 | if (first == last) |
| 94 | return false; |
| 95 | |
| 96 | int nBytes = Utf8BytesIndicated(*first); |
| 97 | if (nBytes < 1) { |
| 98 | // Bad lead byte |
| 99 | ++first; |
| 100 | codePoint = REPLACEMENT_CHARACTER; |
| 101 | return true; |
| 102 | } |
| 103 | |
| 104 | if (nBytes == 1) { |
| 105 | codePoint = *first++; |
| 106 | return true; |
| 107 | } |
| 108 | |
| 109 | // Gather bits from trailing bytes |
| 110 | codePoint = static_cast<unsigned char>(*first) & ~(0xFF << (7 - nBytes)); |
| 111 | ++first; |
| 112 | --nBytes; |
| 113 | for (; nBytes > 0; ++first, --nBytes) { |
| 114 | if ((first == last) || !IsTrailingByte(*first)) { |
| 115 | codePoint = REPLACEMENT_CHARACTER; |
| 116 | break; |
| 117 | } |
| 118 | codePoint <<= 6; |
| 119 | codePoint |= *first & 0x3F; |
| 120 | } |
| 121 | |
| 122 | // Check for illegal code points |
| 123 | if (codePoint > 0x10FFFF) |
| 124 | codePoint = REPLACEMENT_CHARACTER; |
| 125 | else if (codePoint >= 0xD800 && codePoint <= 0xDFFF) |
| 126 | codePoint = REPLACEMENT_CHARACTER; |
| 127 | else if ((codePoint & 0xFFFE) == 0xFFFE) |
| 128 | codePoint = REPLACEMENT_CHARACTER; |
| 129 | else if (codePoint >= 0xFDD0 && codePoint <= 0xFDEF) |
| 130 | codePoint = REPLACEMENT_CHARACTER; |
| 131 | return true; |
| 132 | } |
| 133 | |
| 134 | void WriteCodePoint(ostream_wrapper& out, int codePoint) { |
| 135 | if (codePoint < 0 || codePoint > 0x10FFFF) { |
no test coverage detected