summaryrefslogtreecommitdiff
path: root/ext/dbm
diff options
context:
space:
mode:
authormatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2002-02-27 04:52:21 +0000
committermatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2002-02-27 04:52:21 +0000
commit3fc04d9361549d5bb15f869c22d7ce9591a0ac8c (patch)
treeb160a4f2ed1605c1a4ef62d6c568ff807fda24c5 /ext/dbm
parent2fcd221fecabe3e6acaa21c54ae6d1ccbe8c0204 (diff)
* ext/dbm/dbm.c (fdbm_select): 1.7 behavior.
* ext/gdbm/gdbm.c (fgdbm_select): ditto. * ext/sdbm/sdbm.c (fsdbm_select): ditto. * ext/dbm/dbm.c (fdbm_delete): adopt Hash#delete behavior. * ext/sdbm/sdbm.c (fsdbm_delete): ditto. * ext/gdbm/gdbm.c: need not to dup key to the block. * ext/sdbm/sdbm.c : replace RuntimeError with SDBMError. * eval.c (rb_f_missing): NoMethod error messages for true, false, nil must respond visibility like for other objects. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2145 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'ext/dbm')
-rw-r--r--ext/dbm/dbm.c76
-rw-r--r--ext/dbm/testdbm.rb28
2 files changed, 83 insertions, 21 deletions
diff --git a/ext/dbm/dbm.c b/ext/dbm/dbm.c
index 55e207c49a..f81f7efcb1 100644
--- a/ext/dbm/dbm.c
+++ b/ext/dbm/dbm.c
@@ -32,7 +32,7 @@ struct dbmdata {
static void
closed_dbm()
{
- rb_raise(rb_eRuntimeError, "closed DBM file");
+ rb_raise(rb_eDBMError, "closed DBM file");
}
#define GetDBM(obj, dbmp) {\
@@ -51,7 +51,18 @@ free_dbm(dbmp)
}
}
-static VALUE fdbm_close _((VALUE));
+static VALUE
+fdbm_close(obj)
+ VALUE obj;
+{
+ struct dbmdata *dbmp;
+
+ GetDBM(obj, dbmp);
+ dbm_close(dbmp->di_dbm);
+ dbmp->di_dbm = 0;
+
+ return Qnil;
+}
static VALUE
fdbm_s_new(argc, argv, klass)
@@ -130,19 +141,6 @@ fdbm_s_open(argc, argv, klass)
}
static VALUE
-fdbm_close(obj)
- VALUE obj;
-{
- struct dbmdata *dbmp;
-
- GetDBM(obj, dbmp);
- dbm_close(dbmp->di_dbm);
- dbmp->di_dbm = 0;
-
- return Qnil;
-}
-
-static VALUE
fdbm_fetch(obj, keystr, ifnone)
VALUE obj, keystr, ifnone;
{
@@ -230,12 +228,52 @@ fdbm_indexes(argc, argv, obj)
}
static VALUE
+fdbm_select(argc, argv, obj)
+ int argc;
+ VALUE *argv;
+ VALUE obj;
+{
+ VALUE new = rb_ary_new2(argc);
+ int i;
+
+ if (rb_block_given_p()) {
+ datum key, val;
+ DBM *dbm;
+ struct dbmdata *dbmp;
+ VALUE keystr, valstr;
+
+ if (argc > 0) {
+ rb_raise(rb_eArgError, "wrong number arguments(%d for 0)", argc);
+ }
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+
+ for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
+ VALUE assoc;
+ val = dbm_fetch(dbm, key);
+ assoc = rb_assoc_new(rb_tainted_str_new(key.dptr, key.dsize),
+ rb_tainted_str_new(val.dptr, val.dsize));
+ if (RTEST(rb_yield(assoc)))
+ rb_ary_push(new, assoc);
+ }
+ }
+ else {
+ for (i=0; i<argc; i++) {
+ rb_ary_push(new, fdbm_fetch(obj, argv[i]));
+ }
+ }
+
+ return new;
+}
+
+static VALUE
fdbm_delete(obj, keystr)
VALUE obj, keystr;
{
datum key, value;
struct dbmdata *dbmp;
DBM *dbm;
+ VALUE valstr;
rb_secure(4);
StringValue(keystr);
@@ -247,10 +285,13 @@ fdbm_delete(obj, keystr)
value = dbm_fetch(dbm, key);
if (value.dptr == 0) {
- if (rb_block_given_p()) rb_yield(keystr);
+ if (rb_block_given_p()) return rb_yield(keystr);
return Qnil;
}
+ /* need to save value before dbm_delete() */
+ valstr = rb_tainted_str_new(value.dptr, value.dsize);
+
if (dbm_delete(dbm, key)) {
dbmp->di_size = -1;
rb_raise(rb_eDBMError, "dbm_delete failed");
@@ -258,7 +299,7 @@ fdbm_delete(obj, keystr)
else if (dbmp->di_size >= 0) {
dbmp->di_size--;
}
- return obj;
+ return valstr;
}
static VALUE
@@ -691,6 +732,7 @@ Init_dbm()
rb_define_method(rb_cDBM, "index", fdbm_index, 1);
rb_define_method(rb_cDBM, "indexes", fdbm_indexes, -1);
rb_define_method(rb_cDBM, "indices", fdbm_indexes, -1);
+ rb_define_method(rb_cDBM, "select", fdbm_select, -1);
rb_define_method(rb_cDBM, "length", fdbm_length, 0);
rb_define_method(rb_cDBM, "size", fdbm_length, 0);
rb_define_method(rb_cDBM, "empty?", fdbm_empty_p, 0);
diff --git a/ext/dbm/testdbm.rb b/ext/dbm/testdbm.rb
index c6b26e0cdf..0be627d346 100644
--- a/ext/dbm/testdbm.rb
+++ b/ext/dbm/testdbm.rb
@@ -165,7 +165,7 @@ class TestDBM < RUNIT::TestCase
assert_nil(dbm.close)
# closed DBM file
- assert_exception(RuntimeError) { dbm.close }
+ assert_exception(DBMError) { dbm.close }
end
def test_aref
@@ -245,6 +245,25 @@ class TestDBM < RUNIT::TestCase
assert_equals(values.reverse, @dbm.indexes(*keys.reverse))
end
+ def test_select
+ keys = %w(foo bar baz)
+ values = %w(FOO BAR BAZ)
+ @dbm[keys[0]], @dbm[keys[1]], @dbm[keys[2]] = values
+ assert_equals(values.reverse, @dbm.select(*keys.reverse))
+ end
+
+ def test_select_with_block
+ keys = %w(foo bar baz)
+ values = %w(FOO BAR BAZ)
+ @dbm[keys[0]], @dbm[keys[1]], @dbm[keys[2]] = values
+ ret = @dbm.select {|k,v|
+ assert_equals(k.upcase, v)
+ k != "bar"
+ }
+ assert_equals([['baz', 'BAZ'], ['foo', 'FOO']],
+ ret.sort)
+ end
+
def test_length
num = 10
assert_equals(0, @dbm.size)
@@ -377,7 +396,7 @@ class TestDBM < RUNIT::TestCase
@dbm[keys[0]], @dbm[keys[1]], @dbm[keys[2]] = values
- assert_equals(@dbm, @dbm.delete(key))
+ assert_equals('BAR', @dbm.delete(key))
assert_nil(@dbm[key])
assert_equals(2, @dbm.size)
@@ -394,12 +413,13 @@ class TestDBM < RUNIT::TestCase
def test_delete_with_block
key = 'no called block'
@dbm[key] = 'foo'
- assert_equals(@dbm, @dbm.delete(key) {|k| k.replace 'called block'})
+ assert_equals('foo', @dbm.delete(key) {|k| k.replace 'called block'})
assert_equals('no called block', key)
assert_equals(0, @dbm.size)
key = 'no called block'
- assert_nil(@dbm.delete(key) {|k| k.replace 'called block'})
+ assert_equals(:blockval,
+ @dbm.delete(key) {|k| k.replace 'called block'; :blockval})
assert_equals('called block', key)
assert_equals(0, @dbm.size)
end