Encode a single character to string representation. * * Encode a single character to string representation (i.e. UTF-8) and store * it into a buffer at @a offset. Encoding starts at @a offset and this offset * is moved to the position where the next character can be written to. * * @param ch Input character. * @param str Output buffer. * @param offset Byte offset where to start writ
| 215 | * code was invalid. |
| 216 | */ |
| 217 | errno_t chr_encode(const char32_t ch, char *str, size_t *offset, size_t size) |
| 218 | { |
| 219 | if (*offset >= size) |
| 220 | return EOVERFLOW; |
| 221 | |
| 222 | if (!chr_check(ch)) |
| 223 | return EINVAL; |
| 224 | |
| 225 | /* |
| 226 | * Unsigned version of ch (bit operations should only be done |
| 227 | * on unsigned types). |
| 228 | */ |
| 229 | uint32_t cc = (uint32_t) ch; |
| 230 | |
| 231 | /* Determine how many continuation bytes are needed */ |
| 232 | |
| 233 | unsigned int b0_bits; /* Data bits in first byte */ |
| 234 | unsigned int cbytes; /* Number of continuation bytes */ |
| 235 | |
| 236 | if ((cc & ~LO_MASK_32(7)) == 0) { |
| 237 | b0_bits = 7; |
| 238 | cbytes = 0; |
| 239 | } else if ((cc & ~LO_MASK_32(11)) == 0) { |
| 240 | b0_bits = 5; |
| 241 | cbytes = 1; |
| 242 | } else if ((cc & ~LO_MASK_32(16)) == 0) { |
| 243 | b0_bits = 4; |
| 244 | cbytes = 2; |
| 245 | } else if ((cc & ~LO_MASK_32(21)) == 0) { |
| 246 | b0_bits = 3; |
| 247 | cbytes = 3; |
| 248 | } else { |
| 249 | /* Codes longer than 21 bits are not supported */ |
| 250 | return EINVAL; |
| 251 | } |
| 252 | |
| 253 | /* Check for available space in buffer */ |
| 254 | if (*offset + cbytes >= size) |
| 255 | return EOVERFLOW; |
| 256 | |
| 257 | /* Encode continuation bytes */ |
| 258 | unsigned int i; |
| 259 | for (i = cbytes; i > 0; i--) { |
| 260 | str[*offset + i] = 0x80 | (cc & LO_MASK_32(CONT_BITS)); |
| 261 | cc = cc >> CONT_BITS; |
| 262 | } |
| 263 | |
| 264 | /* Encode first byte */ |
| 265 | str[*offset] = (cc & LO_MASK_32(b0_bits)) | HI_MASK_8(8 - b0_bits - 1); |
| 266 | |
| 267 | /* Advance offset */ |
| 268 | *offset += cbytes + 1; |
| 269 | |
| 270 | return EOK; |
| 271 | } |
| 272 | |
| 273 | /** Get size of string. |
| 274 | * |
no test coverage detected