| 950 | } |
| 951 | |
| 952 | int str_utf8_decode(const char **ptr) |
| 953 | { |
| 954 | // As per https://encoding.spec.whatwg.org/#utf-8-decoder. |
| 955 | unsigned char utf8_lower_boundary = 0x80; |
| 956 | unsigned char utf8_upper_boundary = 0xBF; |
| 957 | int utf8_code_point = 0; |
| 958 | int utf8_bytes_seen = 0; |
| 959 | int utf8_bytes_needed = 0; |
| 960 | while(true) |
| 961 | { |
| 962 | unsigned char byte_value = str_byte_next(ptr); |
| 963 | if(utf8_bytes_needed == 0) |
| 964 | { |
| 965 | if(byte_value <= 0x7F) |
| 966 | { |
| 967 | return byte_value; |
| 968 | } |
| 969 | else if(0xC2 <= byte_value && byte_value <= 0xDF) |
| 970 | { |
| 971 | utf8_bytes_needed = 1; |
| 972 | utf8_code_point = byte_value - 0xC0; |
| 973 | } |
| 974 | else if(0xE0 <= byte_value && byte_value <= 0xEF) |
| 975 | { |
| 976 | if(byte_value == 0xE0) |
| 977 | utf8_lower_boundary = 0xA0; |
| 978 | if(byte_value == 0xED) |
| 979 | utf8_upper_boundary = 0x9F; |
| 980 | utf8_bytes_needed = 2; |
| 981 | utf8_code_point = byte_value - 0xE0; |
| 982 | } |
| 983 | else if(0xF0 <= byte_value && byte_value <= 0xF4) |
| 984 | { |
| 985 | if(byte_value == 0xF0) |
| 986 | utf8_lower_boundary = 0x90; |
| 987 | if(byte_value == 0xF4) |
| 988 | utf8_upper_boundary = 0x8F; |
| 989 | utf8_bytes_needed = 3; |
| 990 | utf8_code_point = byte_value - 0xF0; |
| 991 | } |
| 992 | else |
| 993 | { |
| 994 | return -1; // Error. |
| 995 | } |
| 996 | utf8_code_point = utf8_code_point << (6 * utf8_bytes_needed); |
| 997 | continue; |
| 998 | } |
| 999 | if(!(utf8_lower_boundary <= byte_value && byte_value <= utf8_upper_boundary)) |
| 1000 | { |
| 1001 | // Resetting variables not necessary, will be done when |
| 1002 | // the function is called again. |
| 1003 | str_byte_rewind(ptr); |
| 1004 | return -1; |
| 1005 | } |
| 1006 | utf8_lower_boundary = 0x80; |
| 1007 | utf8_upper_boundary = 0xBF; |
| 1008 | utf8_bytes_seen += 1; |
| 1009 | utf8_code_point = utf8_code_point + ((byte_value - 0x80) << (6 * (utf8_bytes_needed - utf8_bytes_seen))); |
no test coverage detected