This commit is contained in:
tompng 2024-06-07 02:05:22 +09:00 коммит произвёл Yusuke Endoh
Родитель 2c0149d330
Коммит a8a0591253
2 изменённых файлов: 75 добавлений и 3 удалений

51
hash.c
Просмотреть файл

@ -3405,20 +3405,65 @@ rb_hash_to_a(VALUE hash)
return ary;
}
static bool
symbol_key_needs_quote(VALUE str)
{
long len = RSTRING_LEN(str);
if (len == 0 || !rb_str_symname_p(str)) return true;
const char *s = RSTRING_PTR(str);
char first = s[0];
if (first == '@' || first == '$' || first == '!') return true;
if (!at_char_boundary(s, s + len - 1, RSTRING_END(str), rb_enc_get(str))) return false;
switch (s[len - 1]) {
case '+':
case '-':
case '*':
case '/':
case '`':
case '%':
case '^':
case '&':
case '|':
case ']':
case '<':
case '=':
case '>':
case '~':
case '@':
return true;
default:
return false;
}
}
static int
inspect_i(VALUE key, VALUE value, VALUE str)
{
VALUE str2;
str2 = rb_inspect(key);
bool is_symbol = SYMBOL_P(key);
bool quote = false;
if (is_symbol) {
str2 = rb_sym2str(key);
quote = symbol_key_needs_quote(str2);
}
else {
str2 = rb_inspect(key);
}
if (RSTRING_LEN(str) > 1) {
rb_str_buf_cat_ascii(str, ", ");
}
else {
rb_enc_copy(str, str2);
}
rb_str_buf_append(str, str2);
rb_str_buf_cat_ascii(str, "=>");
if (quote) {
rb_str_buf_append(str, rb_str_inspect(str2));
}
else {
rb_str_buf_append(str, str2);
}
rb_str_buf_cat_ascii(str, is_symbol ? ": " : " => ");
str2 = rb_inspect(value);
rb_str_buf_append(str, str2);

Просмотреть файл

@ -869,6 +869,33 @@ class TestHash < Test::Unit::TestCase
$, = nil
end
def test_inspect
no_quote = '{a: 1, a!: 1, a?: 1}'
quote0 = '{"": 1}'
quote1 = '{"0": 1, "!": 1, "%": 1, "&": 1, "*": 1, "+": 1, "-": 1, "/": 1, "<": 1, ">": 1, "^": 1, "`": 1, "|": 1, "~": 1}'
quote2 = '{"@a": 1, "$a": 1, "+@": 1, "a=": 1, "[]": 1}'
quote3 = '{"a\"b": 1, "@@a": 1, "<=>": 1, "===": 1, "[]=": 1}'
assert_equal(no_quote, eval(no_quote).inspect)
assert_equal(quote0, eval(quote0).inspect)
assert_equal(quote1, eval(quote1).inspect)
assert_equal(quote2, eval(quote2).inspect)
assert_equal(quote3, eval(quote3).inspect)
begin
enc = Encoding.default_external
Encoding.default_external = Encoding::ASCII
utf8_ascii_hash = '{"\\u3042": 1}'
assert_equal(eval(utf8_ascii_hash).inspect, utf8_ascii_hash)
Encoding.default_external = Encoding::UTF_8
utf8_hash = "{\u3042: 1}"
assert_equal(eval(utf8_hash).inspect, utf8_hash)
Encoding.default_external = Encoding::Windows_31J
sjis_hash = "{\x87]: 1}".force_encoding('sjis')
assert_equal(eval(sjis_hash).inspect, sjis_hash)
ensure
Encoding.default_external = enc
end
end
def test_update
h1 = @cls[ 1 => 2, 2 => 3, 3 => 4 ]
h2 = @cls[ 2 => 'two', 4 => 'four' ]