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
+4 -25
View File
@@ -51,36 +51,15 @@ int_chr_utf8(mrb_state *mrb, mrb_value num)
char utf8[4];
mrb_int len;
mrb_value str;
uint32_t sb_flag = 0;
if (cp < 0 || 0x10FFFF < cp) {
mrb_raisef(mrb, E_RANGE_ERROR, "%v out of char range", num);
}
if (cp < 0x80) {
utf8[0] = (char)cp;
len = 1;
sb_flag = MRB_STR_SINGLE_BYTE;
}
else if (cp < 0x800) {
utf8[0] = (char)(0xC0 | (cp >> 6));
utf8[1] = (char)(0x80 | (cp & 0x3F));
len = 2;
}
else if (cp < 0x10000) {
utf8[0] = (char)(0xE0 | (cp >> 12));
utf8[1] = (char)(0x80 | ((cp >> 6) & 0x3F));
utf8[2] = (char)(0x80 | ( cp & 0x3F));
len = 3;
}
else {
utf8[0] = (char)(0xF0 | (cp >> 18));
utf8[1] = (char)(0x80 | ((cp >> 12) & 0x3F));
utf8[2] = (char)(0x80 | ((cp >> 6) & 0x3F));
utf8[3] = (char)(0x80 | ( cp & 0x3F));
len = 4;
}
len = mrb_utf8_to_buf(utf8, (uint32_t)cp);
str = mrb_str_new(mrb, utf8, len);
mrb_str_ptr(str)->flags |= sb_flag;
if (len == 1) {
RSTR_SET_ASCII_FLAG(mrb_str_ptr(str));
}
return str;
}
#endif