diff options
Diffstat (limited to 'lib/unicode/string')
-rw-r--r-- | lib/unicode/string/u8upper.c | 33 |
1 files changed, 20 insertions, 13 deletions
diff --git a/lib/unicode/string/u8upper.c b/lib/unicode/string/u8upper.c index 6d4026d..5da49ba 100644 --- a/lib/unicode/string/u8upper.c +++ b/lib/unicode/string/u8upper.c @@ -1,10 +1,13 @@ +#include <errno.h> +#include <stdckdint.h> + #include "mbstring.h" #include "unicode/prop.h" #include "unicode/string.h" -size_t -u8upper(char8_t *restrict dst, size_t dstn, struct u8view sv, - enum caseflags flags) +char8_t * +u8upper(size_t *dstn, struct u8view sv, enum caseflags flags, alloc_fn alloc, + void *alloc_ctx) { struct ucctx ctx = { .az_or_tr = flags & CF_LANG_AZ, @@ -12,19 +15,22 @@ u8upper(char8_t *restrict dst, size_t dstn, struct u8view sv, .ẞ = flags & CF_ẞ, }; + size_t bufsz; + if (ckd_mul(&bufsz, sv.len, (size_t)U8UPPER_SCALE)) { + errno = EOVERFLOW; + return nullptr; + } + + char8_t *dst = alloc(alloc_ctx, nullptr, 0, bufsz, alignof(char8_t)); + if (dst == nullptr) + return nullptr; + rune ch; size_t n = 0; - while (u8next(&ch, &sv)) { struct rview rv = uprop_get_uc(ch, ctx); - for (size_t i = 0; i < rv.len; i++) { - if (n >= dstn) { - char8_t buf[U8_LEN_MAX]; - n += rtou8(buf, sizeof(buf), rv.p[i]); - } else - n += rtou8(dst + n, dstn - n, rv.p[i]); - } - + for (size_t i = 0; i < rv.len; i++) + n += rtou8(dst + n, bufsz - n, rv.p[i]); if (ctx.lt) { enum uprop_ccc ccc; if (uprop_is_sd(ch)) @@ -34,5 +40,6 @@ u8upper(char8_t *restrict dst, size_t dstn, struct u8view sv, } } - return n; + *dstn = n; + return alloc(alloc_ctx, dst, bufsz, n, alignof(char8_t)); } |