string.c: add mrb_utf8_to_buf() to consolidate UTF-8 encoding

Extract duplicated UTF-8 codepoint-to-bytes encoding into a shared
function in src/string.c. Update all gems to use it:

- mruby-sprintf: %c specifier
- mruby-io: putc
- mruby-string-ext: Integer#chr
- mruby-pack: pack("U")
- mruby-compiler: Unicode escapes in parser

Also use existing mrb_utf8len() in io.c for character length detection.

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Yukihiro "Matz" Matsumoto
2025-12-18 16:30:03 +09:00
parent 53fce124e6
commit 7e28e68dca
8 changed files with 50 additions and 142 deletions
+2 -22
View File
@@ -520,28 +520,8 @@ retry:
/* Integer: encode directly to stack buffer (no allocation) */
mrb_int code = mrb_integer(val);
#ifdef MRB_UTF8_STRING
if (code < 0x80) {
cbuf[0] = (char)code;
clen = 1;
}
else if (code < 0x800) {
cbuf[0] = (char)(0xC0 | (code >> 6));
cbuf[1] = (char)(0x80 | (code & 0x3F));
clen = 2;
}
else if (code < 0x10000) {
cbuf[0] = (char)(0xE0 | (code >> 12));
cbuf[1] = (char)(0x80 | ((code >> 6) & 0x3F));
cbuf[2] = (char)(0x80 | (code & 0x3F));
clen = 3;
}
else {
cbuf[0] = (char)(0xF0 | (code >> 18));
cbuf[1] = (char)(0x80 | ((code >> 12) & 0x3F));
cbuf[2] = (char)(0x80 | ((code >> 6) & 0x3F));
cbuf[3] = (char)(0x80 | (code & 0x3F));
clen = 4;
}
clen = (int)mrb_utf8_to_buf(cbuf, (uint32_t)code);
if (clen == 0) clen = 1; /* invalid codepoint: write single byte */
#else
cbuf[0] = (char)(code & 0xff);
clen = 1;