| 164 | } |
| 165 | |
| 166 | static int text_decode_utf8(const unsigned char *text, size_t remaining, uint32_t *codepoint, |
| 167 | size_t *byte_count) { |
| 168 | if (!text || !codepoint || !byte_count || remaining == 0U) { |
| 169 | return TEXT_ERROR; |
| 170 | } |
| 171 | unsigned char first = text[0]; |
| 172 | if (first <= 0x7fU) { |
| 173 | *codepoint = first; |
| 174 | *byte_count = 1U; |
| 175 | return TEXT_OK; |
| 176 | } |
| 177 | |
| 178 | size_t count; |
| 179 | uint32_t value; |
| 180 | uint32_t minimum; |
| 181 | if (first >= 0xc2U && first <= 0xdfU) { |
| 182 | count = 2U; |
| 183 | value = first & 0x1fU; |
| 184 | minimum = 0x80U; |
| 185 | } else if (first >= 0xe0U && first <= 0xefU) { |
| 186 | count = 3U; |
| 187 | value = first & 0x0fU; |
| 188 | minimum = 0x800U; |
| 189 | } else if (first >= 0xf0U && first <= 0xf4U) { |
| 190 | count = 4U; |
| 191 | value = first & 0x07U; |
| 192 | minimum = 0x10000U; |
| 193 | } else { |
| 194 | return TEXT_ERROR; |
| 195 | } |
| 196 | if (count > remaining) { |
| 197 | return TEXT_ERROR; |
| 198 | } |
| 199 | for (size_t i = 1U; i < count; i++) { |
| 200 | unsigned char next = text[i]; |
| 201 | if ((next & 0xc0U) != 0x80U) { |
| 202 | return TEXT_ERROR; |
| 203 | } |
| 204 | value = (value << 6U) | (uint32_t)(next & 0x3fU); |
| 205 | } |
| 206 | if (value < minimum || value > 0x10ffffU || (value >= 0xd800U && value <= 0xdfffU)) { |
| 207 | return TEXT_ERROR; |
| 208 | } |
| 209 | *codepoint = value; |
| 210 | *byte_count = count; |
| 211 | return TEXT_OK; |
| 212 | } |
| 213 | |
| 214 | static int text_validate_bytes(const char *data, size_t len, int allow_initial_bom) { |
| 215 | if (!data && len != 0U) { |
no outgoing calls
no test coverage detected