/* See LICENSE file for copyright and license details. */ #include "lib-common.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; }