| 16 | } |
| 17 | |
| 18 | size_t utf8Length(const Utf8Type* utf8, size_t remain) { |
| 19 | bool stopOnNull = remain == NPos; |
| 20 | size_t length = 0; |
| 21 | |
| 22 | while (true) { |
| 23 | if (remain == 0) |
| 24 | break; |
| 25 | |
| 26 | if (stopOnNull && utf8[0] == 0) |
| 27 | break; |
| 28 | |
| 29 | if ((utf8[0] & 0x80) == 0x00) { |
| 30 | ++length; |
| 31 | ++utf8; |
| 32 | --remain; |
| 33 | continue; |
| 34 | } |
| 35 | |
| 36 | if (remain == 1) |
| 37 | throwMissingUtf8End(); |
| 38 | |
| 39 | if ((utf8[0] & 0xe0) == 0xc0 && (utf8[1] & 0xc0) == 0x80) { |
| 40 | if (((utf8[0] & 0x1fL) << 6) >= 0x00000080L) { |
| 41 | ++length; |
| 42 | utf8 += 2; |
| 43 | remain -= 2; |
| 44 | continue; |
| 45 | } else { |
| 46 | throwInvalidUtf8Sequence(); |
| 47 | } |
| 48 | } |
| 49 | |
| 50 | if (remain == 2) |
| 51 | throwMissingUtf8End(); |
| 52 | |
| 53 | if ((utf8[0] & 0xf0) == 0xe0 && (utf8[1] & 0xc0) == 0x80 && (utf8[2] & 0xc0) == 0x80) { |
| 54 | if ((((utf8[0] & 0x0fL) << 12) | ((utf8[1] & 0x3fL) << 6)) >= 0x00000800L) { |
| 55 | ++length; |
| 56 | utf8 += 3; |
| 57 | remain -= 3; |
| 58 | continue; |
| 59 | } else { |
| 60 | throwInvalidUtf8Sequence(); |
| 61 | } |
| 62 | } |
| 63 | |
| 64 | if (remain == 3) |
| 65 | throwMissingUtf8End(); |
| 66 | |
| 67 | if ((utf8[0] & 0xf8) == 0xf0 && (utf8[1] & 0xc0) == 0x80 && (utf8[2] & 0xc0) == 0x80 && (utf8[3] & 0xc0) == 0x80) { |
| 68 | if ((((utf8[0] & 0x07L) << 18) | ((utf8[1] & 0x3fL) << 12)) >= 0x00010000L) { |
| 69 | ++length; |
| 70 | utf8 += 4; |
| 71 | remain -= 4; |
| 72 | continue; |
| 73 | } else { |
| 74 | throwInvalidUtf8Sequence(); |
| 75 | } |