Project

General

Profile

Feature #6767

Utility method to get a duplicated string whose encoding is ASCII-8BIT

Added by naruse (Yui NARUSE) over 8 years ago. Updated about 8 years ago.

Status:
Closed
Priority:
Normal
Target version:
[ruby-dev:45992]

Description

ある String を ASCII-8BIT にしたいことはしばしばあります。
それだけならばまだ force_encoding しろよという話なのですが、
#6361 の例のように、バイナリ文字列にさらにバイナリ文字列を結合していく場合、
毎行毎行 force_encoding を書いていくのにはつらいものがあります。

解決案としては、
(1) バイナリリテラルの導入
(2) dup.force_encoding(Encoding::ASCII_8BIT) する短いメソッドを追加
(3) ASCII-8BIT に他のエンコーディングの文字列を結合した場合は暗黙に force_encoding
が考えられます。

しかし、(1) は文法拡張なのでハードルが高く、(3) は方々で議論になっている通りです。
よって、(2) が妥当ではないかと思います。

名前をまつもとさん提案の String#b としたパッチを以下の通り添付します。

diff --git a/string.c b/string.c
index d038835..76cbc36 100644
--- a/string.c
+++ b/string.c
@@ -601,7 +601,7 @@ rb_str_export_to_enc(VALUE str, rb_encoding *enc)
}

static VALUE
-str_replace_shared(VALUE str2, VALUE str)
+str_replace_shared_without_enc(VALUE str2, VALUE str)
{
if (RSTRING_LEN(str) <= RSTRING_EMBED_LEN_MAX) {
STR_SET_EMBED(str2);
@@ -616,8 +616,14 @@ str_replace_shared(VALUE str2, VALUE str)
RSTRING(str2)->as.heap.aux.shared = str;
FL_SET(str2, ELTS_SHARED);
}

  • rb_enc_cr_str_exact_copy(str2, str);
  • return str2; +}

+static VALUE
+str_replace_shared(VALUE str2, VALUE str)
+{

  • str_replace_shared_without_enc(str2, str);
  • rb_enc_cr_str_exact_copy(str2, str); return str2; }

@@ -7340,6 +7346,23 @@ rb_str_force_encoding(VALUE str, VALUE enc)

/*

  • call-seq:
    • * str.b -> str
    • *
    • * Returns a copied string whose encoding is ASCII-8BIT.
    • */ + +static VALUE +rb_str_b(VALUE str) +{
    • VALUE str2 = str_alloc(rb_cString);
    • str_replace_shared_without_enc(str2, str);
    • OBJ_INFECT(str2, str);
    • ENC_CODERANGE_SET(str2, ENC_CODERANGE_VALID);
    • return str2; +} + +/*
    • * call-seq:
  • str.valid_encoding? -> true or false *
  • Returns true for a string which encoded correctly.
    @@ -7969,6 +7992,7 @@ Init_String(void)

    rb_define_method(rb_cString, "encoding", rb_obj_encoding, 0); /* in encoding.c */
    rb_define_method(rb_cString, "force_encoding", rb_str_force_encoding, 1);

    • rb_define_method(rb_cString, "b", rb_str_b, 0); rb_define_method(rb_cString, "valid_encoding?", rb_str_valid_encoding_p, 0); rb_define_method(rb_cString, "ascii_only?", rb_str_is_ascii_only_p, 0);

diff --git a/test/ruby/test_m17n.rb b/test/ruby/test_m17n.rb
index dfcaa94..3a4bca7 100644
--- a/test/ruby/test_m17n.rb
+++ b/test/ruby/test_m17n.rb
@@ -1469,4 +1469,14 @@ class TestM17N < Test::Unit::TestCase
yield(*strs)
end
end
+

  • def test_str_b
  • s = "\u3042"
  • assert_equal(a("\xE3\x81\x82"), s.b)
  • assert_equal(Encoding::ASCII_8BIT, s.b.encoding)
  • s.taint
  • assert_equal(true, s.b.tainted?)
  • s.untrust
  • assert_equal(true, s.b.untrusted?)
  • end end

Related issues

Related to Ruby master - Feature #6361: Bitwise string operationsRejected04/26/2012Actions

Also available in: Atom PDF