/* See LICENSE file for copyright and license details. */ #include "lib-common.h" static struct { uint_least32_t a; uint_least32_t b; uint_least32_t to; } pairs[] = { {(uint_least32_t)'?', (uint_least32_t)'!', UINT32_C(0x2048)}, {(uint_least32_t)'?', (uint_least32_t)'?', UINT32_C(0x2047)}, {(uint_least32_t)'!', (uint_least32_t)'!', UINT32_C(0x203C)}, {(uint_least32_t)'!', (uint_least32_t)'?', UINT32_C(0x2049)}, {UINT32_C(0x23CB), UINT32_C(0x23BE), UINT32_C(0x23C9)}, {UINT32_C(0x23CC), UINT32_C(0x23BF), UINT32_C(0x23CA)} }; enum libcharconv_result libcharconv_joined(const char *s, size_t slen, size_t *n, uint_least32_t *cp, size_t *ncp) { uint_least32_t a, b; size_t i, alen, blen; *n = 0; while (slen) { alen = libcharconv_decode_utf8_(s, slen, &a); if (alen > slen) { if (*n) goto no_conv; return LIBCHARCONV_INDETERMINATE; } if (!alen) { *n += 1u; slen -= 1u; s = &s[1]; continue; } for (i = 0u; i < sizeof(pairs) / sizeof(*pairs); i++) { if (a != pairs[i].a) continue; if (*n) goto no_conv; if (slen == alen) return LIBCHARCONV_INDETERMINATE; blen = libcharconv_decode_utf8_(&s[alen], slen - alen, &b); if (blen > slen) return LIBCHARCONV_INDETERMINATE; if (!blen) goto no_conv; if (b == pairs[i].b) goto conv; } *n += alen; s = &s[alen]; slen -= alen; } no_conv: return LIBCHARCONV_NO_CONVERT; conv: if (*n) goto no_conv; if (*ncp) *cp = pairs[i].to; *n += alen + blen; *ncp = 1u; return LIBCHARCONV_CONVERTED; }