ruby-changes:40948
From: naruse <ko1@a...>
Date: Fri, 11 Dec 2015 03:57:34 +0900 (JST)
Subject: [ruby-changes:40948] naruse:r53027 (trunk): * object.c (rb_inspect): dump inspected result with rb_str_escape()
naruse 2015-12-11 03:57:08 +0900 (Fri, 11 Dec 2015) New Revision: 53027 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=53027 Log: * object.c (rb_inspect): dump inspected result with rb_str_escape() instead of raising Encoding::CompatibilityError. [Feature #11801] * string.c (rb_str_escape): added to dump given string like rb_str_inspect without quotes and always dump in US-ASCII like rb_str_dump. Modified files: trunk/ChangeLog trunk/NEWS trunk/object.c trunk/string.c trunk/test/ruby/test_m17n.rb Index: ChangeLog =================================================================== --- ChangeLog (revision 53026) +++ ChangeLog (revision 53027) @@ -1,3 +1,12 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Fri Dec 11 03:44:43 2015 NARUSE, Yui <naruse@r...> + + * object.c (rb_inspect): dump inspected result with rb_str_escape() + instead of raising Encoding::CompatibilityError. [Feature #11801] + + * string.c (rb_str_escape): added to dump given string like + rb_str_inspect without quotes and always dump in US-ASCII + like rb_str_dump. + Thu Dec 10 14:59:59 2015 Koichi Sasada <ko1@a...> * test/ruby/test_gc.rb (test_expand_heap): relax condition (1->2). Index: object.c =================================================================== --- object.c (revision 53026) +++ object.c (revision 53027) @@ -465,6 +465,7 @@ rb_any_to_s(VALUE obj) https://github.com/ruby/ruby/blob/trunk/object.c#L465 return str; } +VALUE rb_str_escape(VALUE str); /* * If the default external encoding is ASCII compatible, the encoding of * the inspected result must be compatible with it. @@ -478,11 +479,11 @@ rb_inspect(VALUE obj) https://github.com/ruby/ruby/blob/trunk/object.c#L479 rb_encoding *ext = rb_default_external_encoding(); if (!rb_enc_asciicompat(ext)) { if (!rb_enc_str_asciionly_p(str)) - rb_raise(rb_eEncCompatError, "inspected result must be ASCII only if default external encoding is ASCII incompatible"); + return rb_str_escape(str); return str; } if (rb_enc_get(str) != ext && !rb_enc_str_asciionly_p(str)) - rb_raise(rb_eEncCompatError, "inspected result must be ASCII only or use the default external encoding"); + return rb_str_escape(str); return str; } Index: string.c =================================================================== --- string.c (revision 53026) +++ string.c (revision 53027) @@ -5265,6 +5265,70 @@ rb_str_buf_cat_escaped_char(VALUE result https://github.com/ruby/ruby/blob/trunk/string.c#L5265 return l; } +VALUE +rb_str_escape(VALUE str) +{ + int encidx = ENCODING_GET(str); + rb_encoding *enc = rb_enc_from_index(encidx); + const char *p = RSTRING_PTR(str); + const char *pend = RSTRING_END(str); + const char *prev = p; + char buf[CHAR_ESC_LEN + 1]; + VALUE result = rb_str_buf_new(0); + int unicode_p = rb_enc_unicode_p(enc); + int asciicompat = rb_enc_asciicompat(enc); + + while (p < pend) { + unsigned int c, cc; + int n = rb_enc_precise_mbclen(p, pend, enc); + if (!MBCLEN_CHARFOUND_P(n)) { + if (p > prev) str_buf_cat(result, prev, p - prev); + n = rb_enc_mbminlen(enc); + if (pend < p + n) + n = (int)(pend - p); + while (n--) { + snprintf(buf, CHAR_ESC_LEN, "\\x%02X", *p & 0377); + str_buf_cat(result, buf, strlen(buf)); + prev = ++p; + } + continue; + } + n = MBCLEN_CHARFOUND_LEN(n); + c = rb_enc_mbc_to_codepoint(p, pend, enc); + p += n; + switch (c) { + case '\n': cc = 'n'; break; + case '\r': cc = 'r'; break; + case '\t': cc = 't'; break; + case '\f': cc = 'f'; break; + case '\013': cc = 'v'; break; + case '\010': cc = 'b'; break; + case '\007': cc = 'a'; break; + case 033: cc = 'e'; break; + default: cc = 0; break; + } + if (cc) { + if (p - n > prev) str_buf_cat(result, prev, p - n - prev); + buf[0] = '\\'; + buf[1] = (char)cc; + str_buf_cat(result, buf, 2); + prev = p; + } + else if (asciicompat && rb_enc_isascii(c, enc) && ISPRINT(c)) { + } + else { + if (p - n > prev) str_buf_cat(result, prev, p - n - prev); + rb_str_buf_cat_escaped_char(result, c, unicode_p); + prev = p; + } + } + if (p > prev) str_buf_cat(result, prev, p - prev); + ENCODING_CODERANGE_SET(result, rb_usascii_encindex(), ENC_CODERANGE_7BIT); + + OBJ_INFECT_RAW(result, str); + return result; +} + /* * call-seq: * str.inspect -> string Index: NEWS =================================================================== --- NEWS (revision 53026) +++ NEWS (revision 53027) @@ -152,6 +152,10 @@ with all sufficient information, see the https://github.com/ruby/ruby/blob/trunk/NEWS#L152 * Array#flatten and Array#flatten! no longer try to call #to_ary method on elements beyond the given level. [Bug #10748] + * Array#inspect doesn't raise error even if its content returns + a string which is not compatible with Encoding.default_external + as inspected result. [Feature #11801] + * Enumerable * Enumerable#chunk and Enumerable#slice_before no longer takes the initial_state argument. [Feature #10958] @@ -161,6 +165,11 @@ with all sufficient information, see the https://github.com/ruby/ruby/blob/trunk/NEWS#L165 * On Windows File::Stat#ino always returned 0, but now returns BY_HANDLE_FILE_INFORMATION.nFileIndexHigh/Low. [Feature #11216] +* Hash + * Hash#inspect doesn't raise error even if its content returns + a string which is not compatible with Encoding.default_external + as inspected result. [Feature #11801] + * IO * IO#close doesn't raise when the IO object is closed. [Feature #10718] * IO#each_codepoint raises an exception at incomplete character Index: test/ruby/test_m17n.rb =================================================================== --- test/ruby/test_m17n.rb (revision 53026) +++ test/ruby/test_m17n.rb (revision 53027) @@ -278,7 +278,7 @@ class TestM17N < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_m17n.rb#L278 o = Object.new [Encoding::UTF_16BE, Encoding::UTF_16LE, Encoding::UTF_32BE, Encoding::UTF_32LE].each do |e| o.instance_eval "undef inspect;def inspect;'abc'.encode('#{e}');end" - assert_raise(Encoding::CompatibilityError) { [o].inspect } + assert_equal '[abc]', [o].inspect end ensure Encoding.default_internal = orig_int @@ -302,13 +302,18 @@ class TestM17N < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_m17n.rb#L302 def o.inspect "abc".encode(Encoding.default_external) end - assert_raise(Encoding::CompatibilityError) { [o].inspect } + assert_equal '[abc]', [o].inspect Encoding.default_external = Encoding::US_ASCII def o.inspect "\u3042" end - assert_raise(Encoding::CompatibilityError) { [o].inspect } + assert_equal '[\u3042]', [o].inspect + + def o.inspect + "\x82\xa0".force_encoding(Encoding::Windows_31J) + end + assert_equal '[\x{82A0}]', [o].inspect ensure Encoding.default_internal = orig_int Encoding.default_external = orig_ext -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/