From: Tanaka Akira Date: 2004-05-16T19:57:50+09:00 Subject: [ruby-dev:23520] DBM::READER dbm でも gdbm と同様に、読み込みのみで db を open したいと思えて来たの で、GDBM.open と同様に DBM.open に第3引数を追加し、DBM::READER, DBM::WRITER, DBM::WRCREAT, DBM::NEWDB を指定できるようにしてみました。 適用してもいいでしょうか? Index: ext/dbm/dbm.c =================================================================== RCS file: /src/ruby/ext/dbm/dbm.c,v retrieving revision 1.26 diff -u -r1.26 dbm.c --- ext/dbm/dbm.c 8 May 2004 08:11:47 -0000 1.26 +++ ext/dbm/dbm.c 16 May 2004 10:48:03 -0000 @@ -24,6 +24,8 @@ static VALUE rb_cDBM, rb_eDBMError; +#define RUBY_DBM_RW_BIT 0x20000000 + struct dbmdata { int di_size; DBM *di_dbm; @@ -78,12 +80,12 @@ VALUE *argv; VALUE obj; { - VALUE file, vmode; + VALUE file, vmode, vflags; DBM *dbm; struct dbmdata *dbmp; - int mode; + int mode, flags = 0; - if (rb_scan_args(argc, argv, "11", &file, &vmode) == 1) { + if (rb_scan_args(argc, argv, "12", &file, &vmode, &vflags) == 1) { mode = 0666; /* default value */ } else if (NIL_P(vmode)) { @@ -92,17 +94,27 @@ else { mode = NUM2INT(vmode); } + + if (!NIL_P(vflags)) + flags = NUM2INT(vflags); + SafeStringValue(file); - dbm = 0; - if (mode >= 0) { - dbm = dbm_open(RSTRING(file)->ptr, O_RDWR|O_CREAT, mode); + if (flags & RUBY_DBM_RW_BIT) { + flags &= ~RUBY_DBM_RW_BIT; + dbm = dbm_open(RSTRING(file)->ptr, flags, mode); } - if (!dbm) { - dbm = dbm_open(RSTRING(file)->ptr, O_RDWR, 0); - } - if (!dbm) { - dbm = dbm_open(RSTRING(file)->ptr, O_RDONLY, 0); + else { + dbm = 0; + if (mode >= 0) { + dbm = dbm_open(RSTRING(file)->ptr, O_RDWR|O_CREAT, mode); + } + if (!dbm) { + dbm = dbm_open(RSTRING(file)->ptr, O_RDWR, 0); + } + if (!dbm) { + dbm = dbm_open(RSTRING(file)->ptr, O_RDONLY, 0); + } } if (!dbm) { @@ -786,6 +798,12 @@ rb_define_method(rb_cDBM, "to_a", fdbm_to_a, 0); rb_define_method(rb_cDBM, "to_hash", fdbm_to_hash, 0); + + /* flags for dbm_open() */ + rb_define_const(rb_cDBM, "READER", INT2FIX(O_RDONLY|RUBY_DBM_RW_BIT)); + rb_define_const(rb_cDBM, "WRITER", INT2FIX(O_RDWR|RUBY_DBM_RW_BIT)); + rb_define_const(rb_cDBM, "WRCREAT", INT2FIX(O_RDWR|O_CREAT|RUBY_DBM_RW_BIT)); + rb_define_const(rb_cDBM, "NEWDB", INT2FIX(O_RDWR|O_CREAT|O_TRUNC|RUBY_DBM_RW_BIT)); #ifdef DB_VERSION_STRING rb_define_const(rb_cDBM, "VERSION", rb_str_new2(DB_VERSION_STRING)); Index: test/dbm/test_dbm.rb =================================================================== RCS file: /src/ruby/test/dbm/test_dbm.rb,v retrieving revision 1.1 diff -u -r1.1 test_dbm.rb --- test/dbm/test_dbm.rb 7 May 2004 09:39:11 -0000 1.1 +++ test/dbm/test_dbm.rb 16 May 2004 10:48:03 -0000 @@ -11,7 +11,7 @@ require 'fileutils' class TestDBM < Test::Unit::TestCase - TMPROOT = "#{Dir.tmpdir}/ruby-gdbm.#{$$}" + TMPROOT = "#{Dir.tmpdir}/ruby-dbm.#{$$}" def setup Dir.mkdir TMPROOT @@ -21,8 +21,29 @@ FileUtils.rm_rf TMPROOT if File.directory?(TMPROOT) end + def test_reader_open + DBM.open("#{TMPROOT}/a") {} + v = DBM.open("#{TMPROOT}/a", nil, DBM::READER) {|d| + assert_raises(DBMError, Errno::EPERM) { d["k"] = "v" } + true + } + assert(v) + end + + def test_newdb_open + DBM.open("#{TMPROOT}/a") {|dbm| + dbm["k"] = "v" + } + v = DBM.open("#{TMPROOT}/a", nil, DBM::NEWDB) {|d| + assert_equal(0, d.length) + assert_nil(d["k"]) + true + } + assert(v) + end + def test_freeze - DBM.open("#{TMPROOT}/a.dbm") {|d| + DBM.open("#{TMPROOT}/a") {|d| d.freeze assert_raises(TypeError) { d["k"] = "v" } } Index: test/gdbm/test_gdbm.rb =================================================================== RCS file: /src/ruby/test/gdbm/test_gdbm.rb,v retrieving revision 1.3 diff -u -r1.3 test_gdbm.rb --- test/gdbm/test_gdbm.rb 7 May 2004 09:39:11 -0000 1.3 +++ test/gdbm/test_gdbm.rb 16 May 2004 10:48:03 -0000 @@ -21,10 +21,22 @@ FileUtils.rm_rf TMPROOT if File.directory?(TMPROOT) end - def test_open + def test_reader_open GDBM.open("#{TMPROOT}/a.dbm") {} v = GDBM.open("#{TMPROOT}/a.dbm", nil, GDBM::READER) {|d| assert_raises(GDBMError) { d["k"] = "v" } + true + } + assert(v) + end + + def test_newdb_open + GDBM.open("#{TMPROOT}/a.dbm") {|dbm| + dbm["k"] = "v" + } + v = GDBM.open("#{TMPROOT}/a.dbm", nil, GDBM::NEWDB) {|d| + assert_equal(0, d.length) + assert_nil(d["k"]) true } assert(v) -- [田中 哲][たなか あきら][Tanaka Akira]