| 82 | } |
| 83 | |
| 84 | size_t utf8DecodeChar(const Utf8Type* utf8, Utf32Type* utf32, size_t remain) { |
| 85 | const Utf8Type* start = utf8; |
| 86 | bool stopOnNull = remain == NPos; |
| 87 | |
| 88 | while (true) { |
| 89 | if (remain == 0) |
| 90 | break; |
| 91 | |
| 92 | if (stopOnNull && utf8[0] == 0) |
| 93 | break; |
| 94 | |
| 95 | if ((utf8[0] & 0x80) == 0x00) { |
| 96 | *utf32 = utf8[0]; |
| 97 | return utf8 - start + 1; |
| 98 | } |
| 99 | |
| 100 | if (remain == 1) |
| 101 | throwMissingUtf8End(); |
| 102 | |
| 103 | if ((utf8[0] & 0xe0) == 0xc0 && (utf8[1] & 0xc0) == 0x80) { |
| 104 | *utf32 = ((utf8[0] & 0x1fL) << 6) | ((utf8[1] & 0x3fL) << 0); |
| 105 | if (*utf32 >= 0x00000080L) |
| 106 | return utf8 - start + 2; |
| 107 | else |
| 108 | throwInvalidUtf8Sequence(); |
| 109 | } |
| 110 | |
| 111 | if (remain == 2) |
| 112 | throwMissingUtf8End(); |
| 113 | |
| 114 | if ((utf8[0] & 0xf0) == 0xe0 && (utf8[1] & 0xc0) == 0x80 && (utf8[2] & 0xc0) == 0x80) { |
| 115 | *utf32 = ((utf8[0] & 0x0fL) << 12) | ((utf8[1] & 0x3fL) << 6) | ((utf8[2] & 0x3fL) << 0); |
| 116 | if (*utf32 >= 0x00000800L) |
| 117 | return utf8 - start + 3; |
| 118 | else |
| 119 | throwInvalidUtf8Sequence(); |
| 120 | } |
| 121 | |
| 122 | if (remain == 3) |
| 123 | throwMissingUtf8End(); |
| 124 | |
| 125 | if ((utf8[0] & 0xf8) == 0xf0 && (utf8[1] & 0xc0) == 0x80 && (utf8[2] & 0xc0) == 0x80 && (utf8[3] & 0xc0) == 0x80) { |
| 126 | *utf32 = |
| 127 | ((utf8[0] & 0x07L) << 18) | ((utf8[1] & 0x3fL) << 12) | ((utf8[2] & 0x3fL) << 6) | ((utf8[3] & 0x3fL) << 0); |
| 128 | if (*utf32 >= 0x00010000L) |
| 129 | return utf8 - start + 4; |
| 130 | else |
| 131 | throwInvalidUtf8Sequence(); |
| 132 | } else { |
| 133 | throwInvalidUtf8Sequence(); |
| 134 | } |
| 135 | } |
| 136 | |
| 137 | return utf8 - start; |
| 138 | } |
| 139 | |
| 140 | size_t utf8EncodeChar(Utf8Type* utf8, Utf32Type utf32, size_t len) { |
| 141 | if (utf32 > 0x10FFFFu) |
nothing calls this directly
no test coverage detected