diff options
| author | Mattias Andrée <m@maandree.se> | 2026-01-25 21:03:48 +0100 |
|---|---|---|
| committer | Mattias Andrée <m@maandree.se> | 2026-01-25 21:03:48 +0100 |
| commit | b710c7eb580d8f291bee9bc760d806ec305f26b2 (patch) | |
| tree | 30f50ee2832a80d37a4a9615ccec543bdfd6a79b /libcharconv_control_character_representations.c | |
| parent | latin: do not covert LF and SP to text (diff) | |
| download | charconv-b710c7eb580d8f291bee9bc760d806ec305f26b2.tar.gz charconv-b710c7eb580d8f291bee9bc760d806ec305f26b2.tar.bz2 charconv-b710c7eb580d8f291bee9bc760d806ec305f26b2.tar.xz | |
Add control character representations
Signed-off-by: Mattias Andrée <m@maandree.se>
Diffstat (limited to 'libcharconv_control_character_representations.c')
| -rw-r--r-- | libcharconv_control_character_representations.c | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/libcharconv_control_character_representations.c b/libcharconv_control_character_representations.c new file mode 100644 index 0000000..57c1c93 --- /dev/null +++ b/libcharconv_control_character_representations.c @@ -0,0 +1,65 @@ +/* See LICENSE file for copyright and license details. */ +#include "lib-common.h" +#include <string.h> + + +static const char *texts[] = { + "NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL", + "BS", "HT", "LF", " VT", "FF", "CR", "SS", "SI", + "DLE", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB", + "CAN", "EM", "SUB", "ESC", "FS", "GS", "RS", "US", + "SP", "DEL" +}; + + +enum libcharconv_result +libcharconv_control_character_representations(const char *s, size_t slen, size_t *n, uint_least32_t *cp, size_t *ncp) +{ + size_t i, len, found, found_len; + int indeterminate; + *n = 0; + for (; slen; s++, slen--, ++*n) { + if (*(const unsigned char *)s <= ' ') { + found = *(const unsigned char *)s; + goto conv_byte; + } else if (*(const unsigned char *)s == 0x7Fu) { + found = 0x21u; + goto conv_byte; + } + indeterminate = 0; + found = SIZE_MAX; + found_len = 0u; + for (i = 0u; i < sizeof(texts) / sizeof(*texts); i++) { + len = strlen(texts[i]); + if (strncmp(s, texts[i], len < slen ? len : slen)) + continue; + if (slen < len) { + indeterminate = 1; + continue; + } + if (len > found_len) { + found = i; + found_len = len; + } + } + if (found_len) + goto conv; + if (*n) + goto no_conv; + if (indeterminate) + return LIBCHARCONV_INDETERMINATE; + } +no_conv: + return LIBCHARCONV_NO_CONVERT; + +conv_byte: + found_len = 1u; +conv: + if (*n) + goto no_conv; + if (*ncp) + *cp = (uint_least32_t)UINT32_C(0x2400) | (uint_least32_t)found; + *n += found_len; + *ncp = 1u; + return indeterminate ? LIBCHARCONV_CONVERT_IF_END : LIBCHARCONV_CONVERTED; +} |
