* xmlGetUTF8Char: * @utf: a sequence of UTF-8 encoded bytes * @len: a pointer to the minimum number of bytes present in * the sequence. This is used to assure the next character * is completely contained within the sequence. * * Read the first UTF8 character from @utf * * Returns the char value or -1 in case of error, and sets *len to * the actual number of bytes c
| 855 | * the actual number of bytes consumed (0 in case of error) |
| 856 | */ |
| 857 | int |
| 858 | xmlGetUTF8Char(const unsigned char *utf, int *len) { |
| 859 | unsigned int c; |
| 860 | |
| 861 | if (utf == NULL) |
| 862 | goto error; |
| 863 | if (len == NULL) |
| 864 | goto error; |
| 865 | |
| 866 | c = utf[0]; |
| 867 | if (c < 0x80) { |
| 868 | if (*len < 1) |
| 869 | goto error; |
| 870 | /* 1-byte code */ |
| 871 | *len = 1; |
| 872 | } else { |
| 873 | if ((*len < 2) || ((utf[1] & 0xc0) != 0x80)) |
| 874 | goto error; |
| 875 | if (c < 0xe0) { |
| 876 | if (c < 0xc2) |
| 877 | goto error; |
| 878 | /* 2-byte code */ |
| 879 | *len = 2; |
| 880 | c = (c & 0x1f) << 6; |
| 881 | c |= utf[1] & 0x3f; |
| 882 | } else { |
| 883 | if ((*len < 3) || ((utf[2] & 0xc0) != 0x80)) |
| 884 | goto error; |
| 885 | if (c < 0xf0) { |
| 886 | /* 3-byte code */ |
| 887 | *len = 3; |
| 888 | c = (c & 0xf) << 12; |
| 889 | c |= (utf[1] & 0x3f) << 6; |
| 890 | c |= utf[2] & 0x3f; |
| 891 | if ((c < 0x800) || ((c >= 0xd800) && (c < 0xe000))) |
| 892 | goto error; |
| 893 | } else { |
| 894 | if ((*len < 4) || ((utf[3] & 0xc0) != 0x80)) |
| 895 | goto error; |
| 896 | *len = 4; |
| 897 | /* 4-byte code */ |
| 898 | c = (c & 0x7) << 18; |
| 899 | c |= (utf[1] & 0x3f) << 12; |
| 900 | c |= (utf[2] & 0x3f) << 6; |
| 901 | c |= utf[3] & 0x3f; |
| 902 | if ((c < 0x10000) || (c >= 0x110000)) |
| 903 | goto error; |
| 904 | } |
| 905 | } |
| 906 | } |
| 907 | return(c); |
| 908 | |
| 909 | error: |
| 910 | if (len != NULL) |
| 911 | *len = 0; |
| 912 | return(-1); |
| 913 | } |
| 914 |
no outgoing calls
no test coverage detected