| 123 | |
| 124 | #define utf_cont(ch) (((ch) & 0xc0) == 0x80) |
| 125 | UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_iterate( |
| 126 | const utf8proc_uint8_t *str, utf8proc_ssize_t strlen, utf8proc_int32_t *dst |
| 127 | ) { |
| 128 | utf8proc_int32_t uc; |
| 129 | const utf8proc_uint8_t *end; |
| 130 | |
| 131 | *dst = -1; |
| 132 | if (!strlen) return 0; |
| 133 | end = str + ((strlen < 0) ? 4 : strlen); |
| 134 | uc = *str++; |
| 135 | if (uc < 0x80) { |
| 136 | *dst = uc; |
| 137 | return 1; |
| 138 | } |
| 139 | // Must be between 0xc2 and 0xf4 inclusive to be valid |
| 140 | if ((utf8proc_uint32_t)(uc - 0xc2) > (0xf4-0xc2)) return UTF8PROC_ERROR_INVALIDUTF8; |
| 141 | if (uc < 0xe0) { // 2-byte sequence |
| 142 | // Must have valid continuation character |
| 143 | if (str >= end || !utf_cont(*str)) return UTF8PROC_ERROR_INVALIDUTF8; |
| 144 | *dst = ((uc & 0x1f)<<6) | (*str & 0x3f); |
| 145 | return 2; |
| 146 | } |
| 147 | if (uc < 0xf0) { // 3-byte sequence |
| 148 | if ((str + 1 >= end) || !utf_cont(*str) || !utf_cont(str[1])) |
| 149 | return UTF8PROC_ERROR_INVALIDUTF8; |
| 150 | // Check for surrogate chars |
| 151 | if (uc == 0xed && *str > 0x9f) |
| 152 | return UTF8PROC_ERROR_INVALIDUTF8; |
| 153 | uc = ((uc & 0xf)<<12) | ((*str & 0x3f)<<6) | (str[1] & 0x3f); |
| 154 | if (uc < 0x800) |
| 155 | return UTF8PROC_ERROR_INVALIDUTF8; |
| 156 | *dst = uc; |
| 157 | return 3; |
| 158 | } |
| 159 | // 4-byte sequence |
| 160 | // Must have 3 valid continuation characters |
| 161 | if ((str + 2 >= end) || !utf_cont(*str) || !utf_cont(str[1]) || !utf_cont(str[2])) |
| 162 | return UTF8PROC_ERROR_INVALIDUTF8; |
| 163 | // Make sure in correct range (0x10000 - 0x10ffff) |
| 164 | if (uc == 0xf0) { |
| 165 | if (*str < 0x90) return UTF8PROC_ERROR_INVALIDUTF8; |
| 166 | } else if (uc == 0xf4) { |
| 167 | if (*str > 0x8f) return UTF8PROC_ERROR_INVALIDUTF8; |
| 168 | } |
| 169 | *dst = ((uc & 7)<<18) | ((*str & 0x3f)<<12) | ((str[1] & 0x3f)<<6) | (str[2] & 0x3f); |
| 170 | return 4; |
| 171 | } |
| 172 | |
| 173 | UTF8PROC_DLLEXPORT utf8proc_bool utf8proc_codepoint_valid(utf8proc_int32_t uc) { |
| 174 | return (((utf8proc_uint32_t)uc)-0xd800 > 0x07ff) && ((utf8proc_uint32_t)uc < 0x110000); |
no outgoing calls