diff options
author | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2015-11-11 09:30:31 +0000 |
---|---|---|
committer | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2015-11-11 09:30:31 +0000 |
commit | 4d57720d1a8f8bdc492e6988bb01a716c814cbbd (patch) | |
tree | fa88b2cc3b0305c9a4808925566af5416e610482 | |
parent | 19294fbb8d2cb8ce23d45a0af927c9d5df65f60d (diff) | |
download | ruby-4d57720d1a8f8bdc492e6988bb01a716c814cbbd.tar.gz |
sprintf.c: nil value is valid
* sprintf.c (rb_str_format): look up the key, then get default
value and raise KeyError if the returned value is nil.
[ruby-dev:49338] [Ruby trunk - Bug #11677]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52537 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | hash.c | 8 | ||||
-rw-r--r-- | internal.h | 1 | ||||
-rw-r--r-- | sprintf.c | 20 | ||||
-rw-r--r-- | test/ruby/test_sprintf.rb | 5 |
5 files changed, 30 insertions, 10 deletions
@@ -1,3 +1,9 @@ +Wed Nov 11 18:30:28 2015 Nobuyoshi Nakada <nobu@ruby-lang.org> + + * sprintf.c (rb_str_format): look up the key, then get default + value and raise KeyError if the returned value is nil. + [ruby-dev:49338] [Ruby trunk - Bug #11677] + Wed Nov 11 17:38:24 2015 Nobuyoshi Nakada <nobu@ruby-lang.org> * vm_eval.c (local_var_list_add): skip internal local variable @@ -758,8 +758,8 @@ rb_hash_rehash(VALUE hash) return hash; } -static VALUE -hash_default_value(VALUE hash, VALUE key) +VALUE +rb_hash_default_value(VALUE hash, VALUE key) { if (rb_method_basic_definition_p(CLASS_OF(hash), id_default)) { VALUE ifnone = RHASH_IFNONE(hash); @@ -792,7 +792,7 @@ rb_hash_aref(VALUE hash, VALUE key) st_data_t val; if (!RHASH(hash)->ntbl || !st_lookup(RHASH(hash)->ntbl, key, &val)) { - return hash_default_value(hash, key); + return rb_hash_default_value(hash, key); } return (VALUE)val; } @@ -1184,7 +1184,7 @@ rb_hash_shift(VALUE hash) } } } - return hash_default_value(hash, Qnil); + return rb_hash_default_value(hash, Qnil); } static int diff --git a/internal.h b/internal.h index dfd02e95cc..600ad8e7d3 100644 --- a/internal.h +++ b/internal.h @@ -828,6 +828,7 @@ void rb_gc_resurrect(VALUE ptr); /* hash.c */ struct st_table *rb_hash_tbl_raw(VALUE hash); VALUE rb_hash_has_key(VALUE hash, VALUE key); +VALUE rb_hash_default_value(VALUE hash, VALUE key); VALUE rb_hash_set_default_proc(VALUE hash, VALUE proc); long rb_objid_hash(st_index_t index); st_table *rb_init_identtable(void); @@ -605,12 +605,20 @@ rb_str_format(int argc, const VALUE *argv, VALUE fmt) } CHECKNAMEARG(start, len, enc); get_hash(&hash, argc, argv); - sym = rb_cstr_intern(start + 1, - len - 2 /* without parenthesis */, - enc); - nextvalue = rb_hash_aref(hash, sym); - if (NIL_P(nextvalue) && !FL_TEST(hash, HASH_PROC_DEFAULT)) { - rb_enc_raise(enc, rb_eKeyError, "key%.*s not found", len, start); + sym = rb_check_symbol_cstr(start + 1, + len - 2 /* without parenthesis */, + enc); + if (!NIL_P(sym)) nextvalue = rb_hash_lookup2(hash, sym, Qundef); + if (nextvalue == Qundef) { + if (NIL_P(sym)) { + sym = rb_cstr_intern(start + 1, + len - 2 /* without parenthesis */, + enc); + } + nextvalue = rb_hash_default_value(hash, sym); + if (NIL_P(nextvalue)) { + rb_enc_raise(enc, rb_eKeyError, "key%.*s not found", len, start); + } } if (term == '}') goto format_s; p++; diff --git a/test/ruby/test_sprintf.rb b/test/ruby/test_sprintf.rb index 97eb4809c4..8af94a89fe 100644 --- a/test/ruby/test_sprintf.rb +++ b/test/ruby/test_sprintf.rb @@ -415,4 +415,9 @@ class TestSprintf < Test::Unit::TestCase assert_equal("hello world", "hello %{location}" % h) assert_equal("hello world", "hello %<location>s" % h) end + + def test_named_with_nil + h = { key: nil, key2: "key2_val" } + assert_equal("key is , key2 is key2_val", "key is %{key}, key2 is %{key2}" % h) + end end |