diff options
Diffstat (limited to 'lib/unicode/string/u8title.c')
-rw-r--r-- | lib/unicode/string/u8title.c | 31 |
1 files changed, 20 insertions, 11 deletions
diff --git a/lib/unicode/string/u8title.c b/lib/unicode/string/u8title.c index f4d9b7e..1adf110 100644 --- a/lib/unicode/string/u8title.c +++ b/lib/unicode/string/u8title.c @@ -1,3 +1,6 @@ +#include <errno.h> +#include <stdckdint.h> + #include "_attrs.h" #include "mbstring.h" #include "unicode/prop.h" @@ -13,9 +16,9 @@ uprop_ccc_0_or_230(rune ch) return x == 0 || x == 230; } -size_t -u8title(char8_t *restrict dst, size_t dstn, struct u8view sv, - enum caseflags flags) +char8_t * +u8title(size_t *dstn, struct u8view sv, enum caseflags flags, alloc_fn alloc, + void *alloc_ctx) { struct tcctx ctx_t; struct lcctx ctx_l; @@ -39,6 +42,16 @@ u8title(char8_t *restrict dst, size_t dstn, struct u8view sv, n = before_dot_cnt = more_above_cnt = 0; + size_t bufsz; + if (ckd_mul(&bufsz, sv.len, (size_t)U8TITLE_SCALE)) { + errno = EOVERFLOW; + return nullptr; + } + + char8_t *dst = alloc(alloc_ctx, nullptr, 0, bufsz, alignof(char8_t)); + if (dst == nullptr) + return nullptr; + while (u8next(&ch, &sv)) { if (sv.p > word.p + word.len) { u8wnext(&word, &wcpy); @@ -102,13 +115,8 @@ u8title(char8_t *restrict dst, size_t dstn, struct u8view sv, } } - 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]); ctx_l.after_I = (ch == 'I') || (ctx_l.after_I && !uprop_ccc_0_or_230(ch)); @@ -123,5 +131,6 @@ u8title(char8_t *restrict dst, size_t dstn, struct u8view sv, ctx_t.after_soft_dotted = false; } - return n; + *dstn = n; + return alloc(alloc_ctx, dst, bufsz, n, alignof(char8_t)); } |