From: Nobuyoshi Nakada Date: 2007-09-06T13:50:59+09:00 Subject: [ruby-dev:31743] deprecating RUBY_VERSION_CODE なかだです。 [ruby-core:12068]で思い出したのですが、めんどくさいのでdevに振り ます。 At Tue, 3 Apr 2007 15:30:16 +0900, Yukihiro Matsumoto wrote in [ruby-core:10847]: > |Furthermore, I'd rather want to remove RUBY_VERSION_CODE from > |version.h, and change RUBY_VERSION object to a particular > |object from mere String. > > It is arguable. RUBY_VERSIONをRuby::VersionNumberというクラスのオブジェクトにし てみました。最初はto_strを持つだけのStructにしようかと思ったんで すが、gsubなどが使われていたので中身はそのままStringにしてしまい ました。 Index: version.c =================================================================== --- version.c (revision 13347) +++ version.c (working copy) @@ -20,15 +20,90 @@ const char ruby_platform[] = RUBY_PLATFO const int ruby_patchlevel = RUBY_PATCHLEVEL; +static VALUE +version_init(VALUE self, VALUE major, VALUE minor, VALUE teeny) +{ + char buf[(sizeof(long)*CHAR_BIT/3+(sizeof(long)*CHAR_BIT<80))*3]; + + rb_call_super(0, 0); + snprintf(buf, sizeof buf, "%u.%u.%u", NUM2UINT(major), NUM2UINT(minor), NUM2UINT(teeny)); + rb_str_cat2(self, buf); + rb_iv_set(self, "major", major); + rb_iv_set(self, "minor", minor); + rb_iv_set(self, "teeny", teeny); + OBJ_FREEZE(self); + return self; +} + +#define version_attr(n) \ +static VALUE version_##n(VALUE self) {return rb_attr_get(self, rb_intern(#n));} + +version_attr(major) +version_attr(minor) +version_attr(teeny) + +static VALUE +version_to_a(VALUE self) +{ + return rb_ary_new3(3, version_major(self), version_minor(self), version_teeny(self)); +} + +static VALUE +version_cmp(VALUE self, VALUE other) +{ + VALUE tmp = rb_check_convert_type(other, T_ARRAY, "Array", "to_a"); + long i; + + if (NIL_P(tmp)) { + VALUE sep = rb_const_get(rb_obj_class(self), rb_intern("Separator")); + tmp = rb_ary_to_ary(rb_funcall2(other, rb_intern("split"), 1, &sep)); + } + other = rb_ary_new2(RARRAY_LEN(tmp)); + for (i = 0; i < RARRAY_LEN(tmp); ++i) { + VALUE e = rb_Integer(rb_ary_entry(tmp, i)); + rb_ary_push(other, e); + } + + self = rb_convert_type(self, T_ARRAY, "Array", "to_a"); + return rb_ary_cmp(self, other); +} + +static VALUE +ruby_version_number(VALUE mRuby) +{ + VALUE cVer = rb_define_class_under(mRuby, "VersionNumber", rb_cString); + + rb_define_method(cVer, "initialize", version_init, 3); + rb_define_method(cVer, "to_ary", version_to_a, 0); + rb_define_method(cVer, "to_a", version_to_a, 0); + rb_define_method(cVer, "<=>", version_cmp, 1); + rb_define_method(cVer, "major", version_major, 0); + rb_define_method(cVer, "minor", version_minor, 0); + rb_define_method(cVer, "teeny", version_teeny, 0); + rb_define_const(cVer, "Separator", rb_reg_new(rb_str_new("\\.", 2), 0)); + + return rb_funcall(cVer, rb_intern("new"), 3, + INT2FIX(RUBY_VERSION_MAJOR), + INT2FIX(RUBY_VERSION_MINOR), + INT2FIX(RUBY_VERSION_TEENY)); +} + void Init_version(void) { - VALUE v = rb_obj_freeze(rb_str_new2(ruby_version)); +#define RUBY_CONST(name, val) do { \ + static const char varname[] = name; \ + rb_define_const(mRuby, varname + 5, val); \ + rb_define_global_const(varname, val); \ + } while (0) + + VALUE mRuby = rb_define_module("Ruby"); + VALUE v = ruby_version_number(mRuby); VALUE d = rb_obj_freeze(rb_str_new2(ruby_release_date)); VALUE p = rb_obj_freeze(rb_str_new2(ruby_platform)); - rb_define_global_const("RUBY_VERSION", v); - rb_define_global_const("RUBY_RELEASE_DATE", d); - rb_define_global_const("RUBY_PLATFORM", p); - rb_define_global_const("RUBY_PATCHLEVEL", INT2FIX(RUBY_PATCHLEVEL)); + RUBY_CONST("RUBY_VERSION", v); + RUBY_CONST("RUBY_RELEASE_DATE", d); + RUBY_CONST("RUBY_PLATFORM", p); + RUBY_CONST("RUBY_PATCHLEVEL", INT2FIX(RUBY_PATCHLEVEL)); } -- Nobu Nakada