Upgrading path from 1.8 to 1.9

e$B$J$+$@$G$9!#e(B

1.9e$B$GDI2C$5$l$?5!G=$N$&$A!“e(BString#linese$B$He(BString#bytese$B$re(B1.8e$B$K$bDIe(B
e$B2C$7$F$*$$$F$O$I$&$G$7$g$&$+!#$H$j$”$($:e(Beach_linee$B$He(Beach_bytee$B$K$Oe(B
e$B<j$rF~$l$F$$$^$;$s!#e(B

e$B$b$&0l$D!"e(BRSTRING_PTR()e$B$de(BRSTRING_LEN()e$B$HF1MM!“e(Brb_str_set_len()e$B$be(B
e$B$”$C$?$[$&$,$$$$$H;W$$$^$9!#e(B

Index: string.c

— string.c (revision 14573)
+++ string.c (working copy)
@@ -672,4 +672,11 @@ rb_str_unlocktmp(str)
}

+void
+rb_str_set_len(VALUE str, long len)
+{

  • RSTRING(str)->len = len;
  • RSTRING(str)->ptr[len] = ‘\0’;
    +}

VALUE
rb_str_resize(str, len)
@@ -3756,4 +3763,95 @@ rb_str_each_byte(str)

+static VALUE str_enumerator _((VALUE, VALUE, int, VALUE *));
+static VALUE
+str_enumerator(str, sym, argc, argv)

  • VALUE str, sym;
  • int argc;
  • VALUE *argv;
    +{
  • static VALUE enumerator;
  • static ID new;
  • int nargc;
  • VALUE *nargv, result;
  • volatile VALUE args;
  • if (!enumerator) {
  • rb_require(“enumerator”);
  • enumerator = rb_path2class(“Enumerable::Enumerator”);
  • new = rb_intern(“new”);
  • }
  • args = rb_ary_new2(nargc = argc + 2);
  • RBASIC(args)->klass = 0;
  • nargv = RARRAY_PTR(args);
  • nargv[0] = str;
  • nargv[1] = sym;
  • MEMCPY(nargv + 2, argv, VALUE, argc);
  • result = rb_funcall2(enumerator, new, nargc, nargv);
  • rb_ary_clear(args);
  • return result;
    +}

+/*

    • Document-method: lines
    • call-seq:
    • str.lines(separator=$/)   => anEnumerator
      
    • str.lines(separator=$/) {|substr| block }        => str
      
    • Returns an enumerator that gives each line in the string. If a
      block is
    • given, it iterates over each line in the string.
    • "foo\nbar\n".lines.to_a   #=> ["foo\n", "bar\n"]
      
    • "foo\nb ar".lines.sort    #=> ["b ar", "foo\n"]
      
  • */

+static VALUE
+rb_str_lines(argc, argv, str)

  • int argc;
  • VALUE *argv;
  • VALUE str;
    +{
  • if (rb_block_given_p()) {
  • return rb_str_each_line(argc, argv, str);
  • }
  • else {
  • static VALUE each_line;
  • if (!each_line) each_line = ID2SYM(rb_intern(“each_line”));
  • return str_enumerator(str, each_line, argc, argv);
  • }
    +}

+/*

    • Document-method: bytes
    • call-seq:
    • str.bytes   => anEnumerator
      
    • str.bytes {|fixnum| block }    => str
      
    • Returns an enumerator that gives each byte in the string. If a
      block is
    • given, it iterates over each byte in the string.
    • "hello".bytes.to_a        #=> [104, 101, 108, 108, 111]
      
  • */

+static VALUE
+rb_str_bytes(argc, argv, str)

  • int argc;
  • VALUE *argv;
  • VALUE str;
    +{
  • if (rb_block_given_p()) {
  • return rb_str_each_byte(argc, argv, str);
  • }
  • else {
  • static VALUE each_byte;
  • if (!each_byte) each_byte = ID2SYM(rb_intern(“each_byte”));
  • return str_enumerator(str, each_byte, argc, argv);
  • }
    +}

/*

  • call-seq:
    @@ -4748,4 +4846,7 @@ Init_String()
    rb_define_method(rb_cString, “each_byte”, rb_str_each_byte, 0);
  • rb_define_method(rb_cString, “lines”, rb_str_lines, -1);
  • rb_define_method(rb_cString, “bytes”, rb_str_bytes, -1);
  • rb_define_method(rb_cString, “sum”, rb_str_sum, -1);

Index: intern.h

— intern.h (revision 14573)
+++ intern.h (working copy)
@@ -425,4 +425,5 @@ VALUE rb_str_substr _((VALUE, long, long
void rb_str_modify _((VALUE));
VALUE rb_str_freeze _((VALUE));
+void rb_str_set_len _((VALUE, long));
VALUE rb_str_resize _((VALUE, long));
VALUE rb_str_cat _((VALUE, const char*, long));

At Wed, 26 Dec 2007 15:18:06 +0900,
Nobuyoshi N. wrote:

1.9ã§è¿½åŠ ã•ã‚ŒãŸæ©Ÿèƒ½ã®ã†ã¡ã€String#linesとString#bytesã‚’1.8にも追
åŠ ã—ã¦ãŠã„ã¦ã¯ã©ã†ã§ã—ã‚‡ã†ã‹ã€‚ã¨ã‚Šã‚ãˆãšeach_lineとeach_byteには
手を入れていません。

 そうですね。IRCでつぶやいた通り、 1.9 での String#to_a 廃止に
よって String を行分割するポータブルで簡潔な手段を失ったので、
早々に lines をバックポートしたいと考えていました。commit して
ください。

 そのパッチでも自動で rb_require(“enumerator”) していますが、
1.8 でも Enumerator を組み込み化し、 RETURN_ENUMERATOR() も採用
する方向で考えています。each_line/each_byte はそのときに。

 なお、 generator (1.9 では fiber で実装)部分については、性能は
さておき実装面で折り合いが付くかどうかですね。チャレンジャー募集。

もう一つ、RSTRING_PTR()やRSTRING_LEN()と同様、rb_str_set_len()も
あったほうがいいと思います。

 こちらもお願いします。

 1.9.0 が出たので、非互換性や実装上の障害がない機能はどんどん
1.8 にバックポートしていきます。積極的に要望・提案をください。


/
/__ __ Akinori.org / MUSHA.org
/ ) ) ) ) / FreeBSD.org / Ruby-lang.org
Akinori MUSHA aka / (_ / ( (__( @ iDaemons.org / and.or.jp

“Different eyes see different things,
Different hearts beat on different strings –
But there are times for you and me when all such things agree”

e$B@>;3OB9-$G$9!#e(B

At Thu, 27 Dec 2007 06:54:54 +0900,
Akinori MUSHA wrote:

e$B!!e(B1.9.0 e$B$,=P$?$N$G!"Hs8_49@-$de$N>c32$,$J$$5!G=$O$I$s$I$se(B
1.8 e$B$K%P%C%/%]!<%H$7$F$$$-$^$9!#@Q6KE*$KMWK>!&Ds0F$r$/$@$5$$!#e(B

1.8.6e$B$KF~$j$=$&$GF~$i$J$+$C$?e(Bnet/smtp.rbe$B$He(Bnet/pop.rbe$B$Ne(BSSLe$BBP1~$re(B
e$B4uK>$7$^$9!#e(B

GC.stress, GC.stress= e$B$b4uK>$7$^$9!#e(B