From 9324c85254fbc515528cf9370b4d8564d646f043 Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Sat, 31 Jan 2026 12:31:10 +0100 Subject: Misc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- libcharconv_marchen.c | 134 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 libcharconv_marchen.c (limited to 'libcharconv_marchen.c') diff --git a/libcharconv_marchen.c b/libcharconv_marchen.c new file mode 100644 index 0000000..12fc414 --- /dev/null +++ b/libcharconv_marchen.c @@ -0,0 +1,134 @@ +/* See LICENSE file for copyright and license details. */ +#include "lib-common.h" + + +enum libcharconv_result +libcharconv_marchen(const char *s, size_t slen, size_t *n, uint_least32_t *cp, size_t *ncp) +{ + static const char *const letters = "kKgGcCjYtTdnpPbmxXDwZz-yrlSsh"; + uint_least32_t c, c2, c3; + size_t i; + *n = 0; + for (; slen--; s++) { + PLAIN_SELECT(letters, 0x11C72); + switch (s[0]) { + case 'a': c = UINT32_C(0x11C8F); goto conv1_subjoinable; + case 'A': c = UINT32_C(0x11CB0); goto conv_vowel; + case 'i': c = UINT32_C(0x11CB1); goto conv_vowel; + case 'u': c = UINT32_C(0x11CB2); goto conv_vowel; + case 'e': c = UINT32_C(0x11CB3); goto conv_vowel; + case 'o': c = UINT32_C(0x11CB4); goto conv_vowel; + case '\'': c = UINT32_C(0x11CB5); goto conv1; + case '\"': c = UINT32_C(0x11CB6); goto conv1; + case '.': c = UINT32_C(0x11C70); goto conv1; + case ':': c = UINT32_C(0x11C71); goto conv1; + case '^': + if (!slen) + return LIBCHARCONV_INDETERMINATE; + switch (s[1]) { + case 'A': c = UINT32_C(0x11CB0); goto conv2; + case 'i': c = UINT32_C(0x11CB1); goto conv2; + case 'u': c = UINT32_C(0x11CB2); goto conv2; + case 'e': c = UINT32_C(0x11CB3); goto conv2; + case 'o': c = UINT32_C(0x11CB4); goto conv2; + default: + goto no_match; + } + case '_': + if (*n) + goto no_conv; + *n += 1u; + break; + default: + no_match: + *n += 1u; + break; + } + } +no_conv: + return LIBCHARCONV_NO_CONVERT; + +conv: + if (*n == 1u && s[-1] == '_' && c != UINT32_C(0x11C88)) { + c += 0x20u; + goto conv1_prechecked; + } + if (*n) + goto no_conv; + if (!slen) + return LIBCHARCONV_INDETERMINATE; + for (i = 0u; letters[i]; i++) + if (letters[i] == s[1]) + break; + c3 = (letters[i] && letters[i] != '-') ? (uint_least32_t)(UINT32_C(0x11C92) + i) : 0u; + if (c3 && slen == 1u) + return LIBCHARCONV_INDETERMINATE; + switch (s[c3 ? 2 : 1]) { + case 'a': + if (c3) + goto conv3_prechecked; + else + goto conv2_prechecked; + case 'A': c2 = UINT32_C(0x11CB0); break; + case 'i': c2 = UINT32_C(0x11CB1); break; + case 'u': c2 = UINT32_C(0x11CB2); break; + case 'e': c2 = UINT32_C(0x11CB3); break; + case 'o': c2 = UINT32_C(0x11CB4); break; + default: + goto no_match; + } + if (*ncp >= 1u) + cp[0] = c; + if (*ncp >= 2u) + cp[1] = c2; + if (c3 && *ncp >= 3u) + cp[2] = c3; + *n += c3 ? 3u : 2u; + *ncp = c3 ? 3u : 2u; + return LIBCHARCONV_CONVERTED; + +conv1_subjoinable: + if (*n == 1u && s[-1] == '_') { + c += 0x20u; + } else { + conv1: + if (*n) + goto no_conv; + } +conv1_prechecked: + if (*ncp) + *cp = c; + *n += 1u; + *ncp = 1u; + return LIBCHARCONV_CONVERTED; + +conv2: + if (*n) + goto no_conv; +conv2_prechecked: + if (*ncp) + cp[0] = c; + *n += 2u; + *ncp = 1u; + return LIBCHARCONV_CONVERTED; + +conv_vowel: + if (*n) + goto no_conv; + if (*ncp >= 1u) + cp[0] = UINT32_C(0x11C8F) + (s[-1] == '_' ? 0x20u : 0u); + if (*ncp >= 2u) + cp[1] = c; + *n += 1u; + *ncp = 2u; + return LIBCHARCONV_CONVERTED; + +conv3_prechecked: + if (*ncp >= 1u) + cp[0] = c; + if (*ncp >= 2u) + cp[1] = c3; + *n += 3u; + *ncp = 2u; + return LIBCHARCONV_CONVERTED; +} -- cgit v1.2.3-70-g09d2