aboutsummaryrefslogtreecommitdiffstats
path: root/libcharconv_control_characters.c
diff options
context:
space:
mode:
Diffstat (limited to 'libcharconv_control_characters.c')
-rw-r--r--libcharconv_control_characters.c24
1 files changed, 24 insertions, 0 deletions
diff --git a/libcharconv_control_characters.c b/libcharconv_control_characters.c
index 55e4bbf..c45f03e 100644
--- a/libcharconv_control_characters.c
+++ b/libcharconv_control_characters.c
@@ -132,6 +132,21 @@ libcharconv_control_characters(const char *s, size_t slen, size_t *n, uint_least
int indeterminate;
*n = 0;
for (; slen; s++, slen--, ++*n) {
+ if (s[0] == '\xE2') {
+ if (slen == 1u)
+ return LIBCHARCONV_INDETERMINATE;
+ if (s[1] != '\x90')
+ goto search;
+ if (slen == 2u)
+ return LIBCHARCONV_INDETERMINATE;
+ i = ((const unsigned char *)s)[2];
+ if (0x80u > i || i > 0xA1u)
+ goto search;
+ i &= 0x3Fu;
+ i = i == 0x21u ? 0x7Fu : i;
+ goto conv_repr;
+ }
+ search:
indeterminate = 0;
found = SIZE_MAX;
found_len = 0u;
@@ -158,6 +173,15 @@ libcharconv_control_characters(const char *s, size_t slen, size_t *n, uint_least
no_conv:
return LIBCHARCONV_NO_CONVERT;
+conv_repr:
+ if (*n)
+ goto no_conv;
+ if (*ncp)
+ *cp = (uint_least32_t)i;
+ *n += 3u;
+ *ncp = 1u;
+ return LIBCHARCONV_CONVERTED;
+
conv:
if (*n)
goto no_conv;