* Pick one ucs character starting from the location *start points at, * and return it, while updating the *start pointer to point at the * end of that character. When remainder_p is not NULL, the location * holds the number of bytes remaining in the string that we are allowed * to pick from. Otherwise we are allowed to pick up to the NUL that * would eventually appear in the string. *remai
| 120 | * and the return value is undefined. |
| 121 | */ |
| 122 | static ucs_char_t pick_one_utf8_char(const char **start, size_t *remainder_p) |
| 123 | { |
| 124 | unsigned char *s = (unsigned char *)*start; |
| 125 | ucs_char_t ch; |
| 126 | size_t remainder, incr; |
| 127 | |
| 128 | /* |
| 129 | * A caller that assumes NUL terminated text can choose |
| 130 | * not to bother with the remainder length. We will |
| 131 | * stop at the first NUL. |
| 132 | */ |
| 133 | remainder = (remainder_p ? *remainder_p : 999); |
| 134 | |
| 135 | if (remainder < 1) { |
| 136 | goto invalid; |
| 137 | } else if (*s < 0x80) { |
| 138 | /* 0xxxxxxx */ |
| 139 | ch = *s; |
| 140 | incr = 1; |
| 141 | } else if ((s[0] & 0xe0) == 0xc0) { |
| 142 | /* 110XXXXx 10xxxxxx */ |
| 143 | if (remainder < 2 || |
| 144 | (s[1] & 0xc0) != 0x80 || |
| 145 | (s[0] & 0xfe) == 0xc0) |
| 146 | goto invalid; |
| 147 | ch = ((s[0] & 0x1f) << 6) | (s[1] & 0x3f); |
| 148 | incr = 2; |
| 149 | } else if ((s[0] & 0xf0) == 0xe0) { |
| 150 | /* 1110XXXX 10Xxxxxx 10xxxxxx */ |
| 151 | if (remainder < 3 || |
| 152 | (s[1] & 0xc0) != 0x80 || |
| 153 | (s[2] & 0xc0) != 0x80 || |
| 154 | /* overlong? */ |
| 155 | (s[0] == 0xe0 && (s[1] & 0xe0) == 0x80) || |
| 156 | /* surrogate? */ |
| 157 | (s[0] == 0xed && (s[1] & 0xe0) == 0xa0) || |
| 158 | /* U+FFFE or U+FFFF? */ |
| 159 | (s[0] == 0xef && s[1] == 0xbf && |
| 160 | (s[2] & 0xfe) == 0xbe)) |
| 161 | goto invalid; |
| 162 | ch = ((s[0] & 0x0f) << 12) | |
| 163 | ((s[1] & 0x3f) << 6) | (s[2] & 0x3f); |
| 164 | incr = 3; |
| 165 | } else if ((s[0] & 0xf8) == 0xf0) { |
| 166 | /* 11110XXX 10XXxxxx 10xxxxxx 10xxxxxx */ |
| 167 | if (remainder < 4 || |
| 168 | (s[1] & 0xc0) != 0x80 || |
| 169 | (s[2] & 0xc0) != 0x80 || |
| 170 | (s[3] & 0xc0) != 0x80 || |
| 171 | /* overlong? */ |
| 172 | (s[0] == 0xf0 && (s[1] & 0xf0) == 0x80) || |
| 173 | /* > U+10FFFF? */ |
| 174 | (s[0] == 0xf4 && s[1] > 0x8f) || s[0] > 0xf4) |
| 175 | goto invalid; |
| 176 | ch = ((s[0] & 0x07) << 18) | ((s[1] & 0x3f) << 12) | |
| 177 | ((s[2] & 0x3f) << 6) | (s[3] & 0x3f); |
| 178 | incr = 4; |
| 179 | } else { |
no outgoing calls
no test coverage detected