diff options
| author | Berke Güzel <wenekar1@gmail.com> | 2026-10-12 22:12:02 +0300 |
|---|---|---|
| committer | Berke Güzel <wenekar1@gmail.com> | 2026-10-12 22:12:02 +0300 |
| commit | 94c5e361fbb229b0cd6853e2102a7d95f1f358b3 (patch) | |
| tree | 3c0f11af9dcb84dac8067a31a6979acd6dd56fbf /src/common/utf8.c | |
| parent | 08dc9047098d6d96791024ac7d8f5837633673ef (diff) | |
better public interface and doxygen
Diffstat (limited to 'src/common/utf8.c')
| -rw-r--r-- | src/common/utf8.c | 50 |
1 files changed, 46 insertions, 4 deletions
diff --git a/src/common/utf8.c b/src/common/utf8.c index 1d4cf13..78a5d8e 100644 --- a/src/common/utf8.c +++ b/src/common/utf8.c @@ -1,3 +1,4 @@ +#include "utf8.h" #include <stdlib.h> #include <string.h> #include <stdbool.h> @@ -12,11 +13,12 @@ bool yasl_utf8_validate(const char *str, size_t len) { + if (!str) return len == 0; const unsigned char *p = (const unsigned char *)str; const unsigned char *end = p + len; while (p < end) { - while (p + 8 <= end) { + while ((size_t)(end - p) >= 8) { uint64_t v; memcpy(&v, p, 8); if (v & 0x8080808080808080ull) @@ -28,18 +30,18 @@ bool yasl_utf8_validate(const char *str, size_t len) if (likely(*p < 0x80)) { p++; } else if ((*p & 0xe0) == 0xc0) { - if (unlikely(p + 1 >= end || (p[1] & 0xc0) != 0x80 || (*p & 0x1e) == 0)) + if (unlikely(end - p < 2 || (p[1] & 0xc0) != 0x80 || (*p & 0x1e) == 0)) return false; p += 2; } else if ((*p & 0xf0) == 0xe0) { - if (unlikely(p + 2 >= end || (p[1] & 0xc0) != 0x80 || (p[2] & 0xc0) != 0x80)) + if (unlikely(end - p < 3 || (p[1] & 0xc0) != 0x80 || (p[2] & 0xc0) != 0x80)) return false; uint32_t cp = ((p[0] & 0x0f) << 12) | ((p[1] & 0x3f) << 6) | (p[2] & 0x3f); if (unlikely(cp < 0x800 || (cp >= 0xd800 && cp <= 0xdfff))) return false; p += 3; } else if ((*p & 0xf8) == 0xf0) { - if (unlikely(p + 3 >= end || (p[1] & 0xc0) != 0x80 || (p[2] & 0xc0) != 0x80 || (p[3] & 0xc0) != 0x80)) + if (unlikely(end - p < 4 || (p[1] & 0xc0) != 0x80 || (p[2] & 0xc0) != 0x80 || (p[3] & 0xc0) != 0x80)) return false; uint32_t cp = ((p[0] & 0x07) << 18) | ((p[1] & 0x3f) << 12) | ((p[2] & 0x3f) << 6) | (p[3] & 0x3f); if (unlikely(cp < 0x10000 || cp > 0x10ffff)) @@ -52,6 +54,46 @@ bool yasl_utf8_validate(const char *str, size_t len) return true; } +char *yasl_utf8_from_latin1(const char *str, size_t len, size_t *out_len) +{ + if (len > (SIZE_MAX - 1) / 2) return NULL; + char *out = malloc(len * 2 + 1); + if (!out) return NULL; + size_t n = 0; + for (size_t i = 0; i < len; i++) { + unsigned char ch = (unsigned char)str[i]; + if (ch < 0x80) out[n++] = (char)ch; + else { + out[n++] = (char)(0xc0 | (ch >> 6)); + out[n++] = (char)(0x80 | (ch & 0x3f)); + } + } + out[n] = '\0'; + *out_len = n; + return out; +} + +char *yasl_utf8_to_latin1(const char *str, size_t *out_len) +{ + char *out = malloc(strlen(str) + 1); + if (!out) return NULL; + const unsigned char *p = (const unsigned char *)str; + size_t n = 0; + while (*p) { + if (*p < 0x80) out[n++] = (char)*p++; + else if ((*p == 0xc2 || *p == 0xc3) && (p[1] & 0xc0) == 0x80) { + out[n++] = (char)(((*p & 3) << 6) | (p[1] & 0x3f)); + p += 2; + } else { + free(out); + return NULL; + } + } + out[n] = '\0'; + *out_len = n; + return out; +} + char *yasl_utf8_sanitize_dup(const char *str) { if (unlikely(!str)) return NULL; |
