summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
authormatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2001-05-01 08:45:26 +0000
committermatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2001-05-01 08:45:26 +0000
commit37f84274a23797009f4e248e02f40a9adccf1773 (patch)
tree984f0e5dc73d73125d927c16fe8ede5d53771768 /ext
parent889f039b4c594fd1e1d397fef1551af524187c58 (diff)
* eval.c (rb_eval): should preserve value of ruby_errinfo.
* eval.c (rb_thread_schedule): inifinite sleep should not cause dead lock. * array.c (rb_ary_flatten_bang): proper recursive detection. * eval.c (yield_under): need not to prohibit at safe leve 4. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_6@1353 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'ext')
-rw-r--r--ext/dbm/dbm.c119
-rw-r--r--ext/gdbm/gdbm.c547
-rw-r--r--ext/sdbm/init.c125
-rw-r--r--ext/tk/lib/tk.rb2
4 files changed, 607 insertions, 186 deletions
diff --git a/ext/dbm/dbm.c b/ext/dbm/dbm.c
index 55c60bf3b3..b3873bff6e 100644
--- a/ext/dbm/dbm.c
+++ b/ext/dbm/dbm.c
@@ -6,7 +6,7 @@
$Date$
created at: Mon Jan 24 15:59:52 JST 1994
- Copyright (C) 1995-1998 Yukihiro Matsumoto
+ Copyright (C) 1995-2001 Yukihiro Matsumoto
************************************************/
@@ -22,7 +22,7 @@
#include <fcntl.h>
#include <errno.h>
-VALUE cDBM;
+VALUE cDBM, rb_eDBMError;
struct dbmdata {
int di_size;
@@ -37,6 +37,7 @@ closed_dbm()
#define GetDBM(obj, dbmp) {\
Data_Get_Struct(obj, struct dbmdata, dbmp);\
+ if (dbmp == 0) closed_dbm();\
if (dbmp->di_dbm == 0) closed_dbm();\
}
@@ -44,21 +45,35 @@ static void
free_dbm(dbmp)
struct dbmdata *dbmp;
{
- if (dbmp->di_dbm) dbm_close(dbmp->di_dbm);
- free(dbmp);
+ if (dbmp) {
+ if (dbmp->di_dbm) dbm_close(dbmp->di_dbm);
+ free(dbmp);
+ }
}
+static VALUE fdbm_close _((VALUE));
+
static VALUE
-fdbm_s_open(argc, argv, klass)
+fdbm_s_new(argc, argv, klass)
int argc;
VALUE *argv;
VALUE klass;
{
+ VALUE obj = Data_Wrap_Struct(klass, 0, free_dbm, 0);
+ rb_obj_call_init(obj, argc, argv);
+ return obj;
+}
+
+static VALUE
+fdbm_initialize(argc, argv, obj)
+ int argc;
+ VALUE *argv;
+ VALUE obj;
+{
VALUE file, vmode;
DBM *dbm;
struct dbmdata *dbmp;
int mode;
- VALUE obj;
if (rb_scan_args(argc, argv, "11", &file, &vmode) == 1) {
mode = 0666; /* default value */
@@ -69,6 +84,7 @@ fdbm_s_open(argc, argv, klass)
else {
mode = NUM2INT(vmode);
}
+ file = rb_str_to_str(file);
Check_SafeStr(file);
dbm = 0;
@@ -87,7 +103,8 @@ fdbm_s_open(argc, argv, klass)
rb_sys_fail(RSTRING(file)->ptr);
}
- obj = Data_Make_Struct(klass,struct dbmdata,0,free_dbm,dbmp);
+ dbmp = ALLOC(struct dbmdata);
+ DATA_PTR(obj) = dbmp;
dbmp->di_dbm = dbm;
dbmp->di_size = -1;
@@ -95,6 +112,25 @@ fdbm_s_open(argc, argv, klass)
}
static VALUE
+fdbm_s_open(argc, argv, klass)
+ int argc;
+ VALUE *argv;
+ VALUE klass;
+{
+ VALUE obj = Data_Wrap_Struct(klass, 0, free_dbm, 0);
+
+ if (NIL_P(fdbm_initialize(argc, argv, obj))) {
+ return Qnil;
+ }
+
+ if (rb_block_given_p()) {
+ return rb_ensure(rb_yield, obj, fdbm_close, obj);
+ }
+
+ return obj;
+}
+
+static VALUE
fdbm_close(obj)
VALUE obj;
{
@@ -115,7 +151,7 @@ fdbm_fetch(obj, keystr, ifnone)
struct dbmdata *dbmp;
DBM *dbm;
- Check_Type(keystr, T_STRING);
+ keystr = rb_str_to_str(keystr);
key.dptr = RSTRING(keystr)->ptr;
key.dsize = RSTRING(keystr)->len;
@@ -143,10 +179,14 @@ fdbm_fetch_m(argc, argv, obj)
VALUE *argv;
VALUE obj;
{
- VALUE keystr, ifnone;
+ VALUE keystr, valstr, ifnone;
rb_scan_args(argc, argv, "11", &keystr, &ifnone);
- return fdbm_fetch(obj, keystr, ifnone);
+ valstr = fdbm_fetch(obj, keystr, ifnone);
+ if (argc == 1 && !rb_block_given_p() && NIL_P(valstr))
+ rb_raise(rb_eIndexError, "key not found");
+
+ return valstr;
}
static VALUE
@@ -157,7 +197,7 @@ fdbm_index(obj, valstr)
struct dbmdata *dbmp;
DBM *dbm;
- Check_Type(valstr, T_STRING);
+ valstr = rb_str_to_str(valstr);
val.dptr = RSTRING(valstr)->ptr;
val.dsize = RSTRING(valstr)->len;
@@ -166,8 +206,9 @@ fdbm_index(obj, valstr)
for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
val = dbm_fetch(dbm, key);
if (val.dsize == RSTRING(valstr)->len &&
- memcmp(val.dptr, RSTRING(valstr)->ptr, val.dsize) == 0)
+ memcmp(val.dptr, RSTRING(valstr)->ptr, val.dsize) == 0) {
return rb_tainted_str_new(key.dptr, key.dsize);
+ }
}
return Qnil;
}
@@ -198,7 +239,7 @@ fdbm_delete(obj, keystr)
DBM *dbm;
rb_secure(4);
- Check_Type(keystr, T_STRING);
+ keystr = rb_str_to_str(keystr);
key.dptr = RSTRING(keystr)->ptr;
key.dsize = RSTRING(keystr)->len;
@@ -213,7 +254,7 @@ fdbm_delete(obj, keystr)
if (dbm_delete(dbm, key)) {
dbmp->di_size = -1;
- rb_raise(rb_eRuntimeError, "dbm_delete failed");
+ rb_raise(rb_eDBMError, "dbm_delete failed");
}
else if (dbmp->di_size >= 0) {
dbmp->di_size--;
@@ -233,6 +274,7 @@ fdbm_shift(obj)
rb_secure(4);
GetDBM(obj, dbmp);
dbm = dbmp->di_dbm;
+ dbmp->di_size = -1;
key = dbm_firstkey(dbm);
if (!key.dptr) return Qnil;
@@ -252,20 +294,35 @@ fdbm_delete_if(obj)
struct dbmdata *dbmp;
DBM *dbm;
VALUE keystr, valstr;
+ VALUE ret, ary = rb_ary_new();
+ int i, status = 0, n;
rb_secure(4);
GetDBM(obj, dbmp);
dbm = dbmp->di_dbm;
+ n = dbmp->di_size;
+ dbmp->di_size = -1;
+
for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
val = dbm_fetch(dbm, key);
keystr = rb_tainted_str_new(key.dptr, key.dsize);
valstr = rb_tainted_str_new(val.dptr, val.dsize);
- if (RTEST(rb_yield(rb_assoc_new(keystr, valstr)))) {
- if (dbm_delete(dbm, key)) {
- rb_raise(rb_eRuntimeError, "dbm_delete failed");
- }
+ ret = rb_protect(rb_yield, rb_assoc_new(rb_str_dup(keystr), valstr), &status);
+ if (status != 0) goto delete;
+ if (RTEST(ret)) rb_ary_push(ary, keystr);
+ }
+ delete:
+ for (i = 0; i < RARRAY(ary)->len; i++) {
+ keystr = RARRAY(ary)->ptr[i];
+ key.dptr = RSTRING(keystr)->ptr;
+ key.dsize = RSTRING(keystr)->len;
+ if (dbm_delete(dbm, key)) {
+ rb_raise(rb_eDBMError, "dbm_delete failed");
}
}
+ if (status) rb_jump_tag(status);
+ if (n > 0) dbmp->di_size = n - RARRAY(ary)->len;
+
return obj;
}
@@ -281,11 +338,16 @@ fdbm_clear(obj)
GetDBM(obj, dbmp);
dbm = dbmp->di_dbm;
dbmp->di_size = -1;
- for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
- if (dbm_delete(dbm, key)) {
- rb_raise(rb_eRuntimeError, "dbm_delete failed");
- }
+ while (key = dbm_firstkey(dbm), key.dptr) {
+ do {
+ if (dbm_delete(dbm, key)) {
+ rb_raise(rb_eDBMError, "dbm_delete failed");
+ }
+ key = dbm_nextkey(dbm);
+ } while (key.dptr);
}
+ dbmp->di_size = 0;
+
return obj;
}
@@ -374,7 +436,7 @@ fdbm_store(obj, keystr, valstr)
dbm_clearerr(dbm);
#endif
if (errno == EPERM) rb_sys_fail(0);
- rb_raise(rb_eRuntimeError, "dbm_store failed");
+ rb_raise(rb_eDBMError, "dbm_store failed");
}
return valstr;
@@ -529,7 +591,7 @@ fdbm_has_key(obj, keystr)
struct dbmdata *dbmp;
DBM *dbm;
- Check_Type(keystr, T_STRING);
+ keystr = rb_str_to_str(keystr);
key.dptr = RSTRING(keystr)->ptr;
key.dsize = RSTRING(keystr)->len;
@@ -548,7 +610,7 @@ fdbm_has_value(obj, valstr)
struct dbmdata *dbmp;
DBM *dbm;
- Check_Type(valstr, T_STRING);
+ valstr = rb_str_to_str(valstr);
val.dptr = RSTRING(valstr)->ptr;
val.dsize = RSTRING(valstr)->len;
@@ -618,10 +680,13 @@ void
Init_dbm()
{
cDBM = rb_define_class("DBM", rb_cObject);
+ rb_eDBMError = rb_define_class("DBMError", rb_eStandardError);
rb_include_module(cDBM, rb_mEnumerable);
+ rb_define_singleton_method(cDBM, "new", fdbm_s_new, -1);
rb_define_singleton_method(cDBM, "open", fdbm_s_open, -1);
- rb_define_singleton_method(cDBM, "new", fdbm_s_open, -1);
+
+ rb_define_method(cDBM, "initialize", fdbm_initialize, -1);
rb_define_method(cDBM, "close", fdbm_close, 0);
rb_define_method(cDBM, "[]", fdbm_aref, 1);
rb_define_method(cDBM, "fetch", fdbm_fetch_m, -1);
@@ -639,7 +704,7 @@ Init_dbm()
rb_define_method(cDBM, "each_pair", fdbm_each_pair, 0);
rb_define_method(cDBM, "keys", fdbm_keys, 0);
rb_define_method(cDBM, "values", fdbm_values, 0);
- rb_define_method(cDBM, "shift", fdbm_shift, 1);
+ rb_define_method(cDBM, "shift", fdbm_shift, 0);
rb_define_method(cDBM, "delete", fdbm_delete, 1);
rb_define_method(cDBM, "delete_if", fdbm_delete_if, 0);
rb_define_method(cDBM, "reject!", fdbm_delete_if, 0);
diff --git a/ext/gdbm/gdbm.c b/ext/gdbm/gdbm.c
index d84c7bedd4..802e7943be 100644
--- a/ext/gdbm/gdbm.c
+++ b/ext/gdbm/gdbm.c
@@ -14,7 +14,7 @@
#include <fcntl.h>
#include <errno.h>
-VALUE cGDBM;
+static VALUE cGDBM, rb_eGDBMError;
#define MY_BLOCK_SIZE (2048)
#define MY_FATAL_FUNC (0)
@@ -32,6 +32,7 @@ closed_dbm()
#define GetDBM(obj, dbmp) {\
Data_Get_Struct(obj, struct dbmdata, dbmp);\
+ if (dbmp == 0) closed_dbm();\
if (dbmp->di_dbm == 0) closed_dbm();\
}
@@ -39,23 +40,37 @@ static void
free_dbm(dbmp)
struct dbmdata *dbmp;
{
- if (dbmp->di_dbm) gdbm_close(dbmp->di_dbm);
- free(dbmp);
+ if (dbmp) {
+ if (dbmp->di_dbm) gdbm_close(dbmp->di_dbm);
+ free(dbmp);
+ }
}
+static VALUE fgdbm_close _((VALUE));
+
static VALUE
-fgdbm_s_open(argc, argv, klass)
+fgdbm_s_new(argc, argv, klass)
int argc;
VALUE *argv;
VALUE klass;
{
- VALUE file, vmode;
+ VALUE obj = Data_Wrap_Struct(klass, 0, free_dbm, 0);
+ rb_obj_call_init(obj, argc, argv);
+ return obj;
+}
+
+static VALUE
+fgdbm_initialize(argc, argv, obj)
+ int argc;
+ VALUE *argv;
+ VALUE obj;
+{
+ VALUE file, vmode, vflags;
GDBM_FILE dbm;
struct dbmdata *dbmp;
- int mode;
- VALUE obj;
+ 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)) {
@@ -64,25 +79,37 @@ fgdbm_s_open(argc, argv, klass)
else {
mode = NUM2INT(vmode);
}
+
+ if (!NIL_P(vflags))
+ flags = NUM2INT(vflags);
+
+ file = rb_str_to_str(file);
Check_SafeStr(file);
dbm = 0;
if (mode >= 0)
dbm = gdbm_open(RSTRING(file)->ptr, MY_BLOCK_SIZE,
- O_RDWR|O_CREAT, mode, MY_FATAL_FUNC);
+ GDBM_WRCREAT|flags, mode, MY_FATAL_FUNC);
if (!dbm)
dbm = gdbm_open(RSTRING(file)->ptr, MY_BLOCK_SIZE,
- O_RDWR, 0, MY_FATAL_FUNC);
+ GDBM_WRITER|flags, 0, MY_FATAL_FUNC);
if (!dbm)
dbm = gdbm_open(RSTRING(file)->ptr, MY_BLOCK_SIZE,
- O_RDONLY, 0, MY_FATAL_FUNC);
+ GDBM_READER|flags, 0, MY_FATAL_FUNC);
if (!dbm) {
if (mode == -1) return Qnil;
- rb_sys_fail(RSTRING(file)->ptr);
+
+ if (gdbm_errno == GDBM_FILE_OPEN_ERROR ||
+ gdbm_errno == GDBM_CANT_BE_READER ||
+ gdbm_errno == GDBM_CANT_BE_WRITER)
+ rb_sys_fail(RSTRING(file)->ptr);
+ else
+ rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
}
- obj = Data_Make_Struct(klass,struct dbmdata,0,free_dbm,dbmp);
+ dbmp = ALLOC(struct dbmdata);
+ DATA_PTR(obj) = dbmp;
dbmp->di_dbm = dbm;
dbmp->di_size = -1;
@@ -90,6 +117,25 @@ fgdbm_s_open(argc, argv, klass)
}
static VALUE
+fgdbm_s_open(argc, argv, klass)
+ int argc;
+ VALUE *argv;
+ VALUE klass;
+{
+ VALUE obj = Data_Wrap_Struct(klass, 0, free_dbm, 0);
+
+ if (NIL_P(fgdbm_initialize(argc, argv, obj))) {
+ return Qnil;
+ }
+
+ if (rb_block_given_p()) {
+ return rb_ensure(rb_yield, obj, fgdbm_close, obj);
+ }
+
+ return obj;
+}
+
+static VALUE
fgdbm_close(obj)
VALUE obj;
{
@@ -103,26 +149,111 @@ fgdbm_close(obj)
}
static VALUE
+rb_gdbm_fetch(dbm, key)
+ GDBM_FILE dbm;
+ datum key;
+{
+ datum val;
+ NEWOBJ(str, struct RString);
+ OBJSETUP(str, rb_cString, T_STRING);
+
+ val = gdbm_fetch(dbm, key);
+ if (val.dptr == 0)
+ return Qnil;
+
+ str->ptr = 0;
+ str->len = val.dsize;
+ str->orig = 0;
+ str->ptr = REALLOC_N(val.dptr,char,val.dsize+1);
+ str->ptr[str->len] = '\0';
+
+ OBJ_TAINT(str);
+ return (VALUE)str;
+}
+
+static VALUE
+rb_gdbm_fetch2(dbm, keystr)
+ GDBM_FILE dbm;
+ VALUE keystr;
+{
+ datum key;
+
+ keystr = rb_str_to_str(keystr);
+ key.dptr = RSTRING(keystr)->ptr;
+ key.dsize = RSTRING(keystr)->len;
+
+ return rb_gdbm_fetch(dbm, key);
+}
+
+static VALUE
+rb_gdbm_firstkey(dbm)
+ GDBM_FILE dbm;
+{
+ datum key;
+ NEWOBJ(str, struct RString);
+ OBJSETUP(str, rb_cString, T_STRING);
+
+ key = gdbm_firstkey(dbm);
+ if (key.dptr == 0)
+ return Qnil;
+
+ str->ptr = 0;
+ str->len = key.dsize;
+ str->orig = 0;
+ str->ptr = REALLOC_N(key.dptr,char,key.dsize+1);
+ str->ptr[str->len] = '\0';
+
+ OBJ_TAINT(str);
+ return (VALUE)str;
+}
+
+static VALUE
+rb_gdbm_nextkey(dbm, keystr)
+ GDBM_FILE dbm;
+ VALUE keystr;
+{
+ datum key, key2;
+ NEWOBJ(str, struct RString);
+ OBJSETUP(str, rb_cString, T_STRING);
+
+ key.dptr = RSTRING(keystr)->ptr;
+ key.dsize = RSTRING(keystr)->len;
+ key2 = gdbm_nextkey(dbm, key);
+ if (key2.dptr == 0)
+ return Qnil;
+
+ str->ptr = 0;
+ str->len = key2.dsize;
+ str->orig = 0;
+ str->ptr = REALLOC_N(key2.dptr,char,key2.dsize+1);
+ str->ptr[str->len] = '\0';
+
+ OBJ_TAINT(str);
+ return (VALUE)str;
+}
+
+static VALUE
fgdbm_fetch(obj, keystr, ifnone)
VALUE obj, keystr, ifnone;
{
- datum key, value;
+ datum key;
struct dbmdata *dbmp;
GDBM_FILE dbm;
+ VALUE valstr;
- Check_Type(keystr, T_STRING);
+ keystr = rb_str_to_str(keystr);
key.dptr = RSTRING(keystr)->ptr;
key.dsize = RSTRING(keystr)->len;
GetDBM(obj, dbmp);
dbm = dbmp->di_dbm;
- value = gdbm_fetch(dbm, key);
- if (value.dptr == 0) {
+ valstr = rb_gdbm_fetch(dbm, key);
+ if (NIL_P(valstr)) {
if (ifnone == Qnil && rb_block_given_p())
return rb_yield(rb_tainted_str_new(key.dptr, key.dsize));
return ifnone;
}
- return rb_tainted_str_new(value.dptr, value.dsize);
+ return valstr;
}
static VALUE
@@ -138,31 +269,37 @@ fgdbm_fetch_m(argc, argv, obj)
VALUE *argv;
VALUE obj;
{
- VALUE keystr, ifnone;
+ VALUE keystr, valstr, ifnone;
rb_scan_args(argc, argv, "11", &keystr, &ifnone);
- return fgdbm_fetch(obj, keystr, ifnone);
+ valstr = fgdbm_fetch(obj, keystr, ifnone);
+ if (argc == 1 && !rb_block_given_p() && NIL_P(valstr))
+ rb_raise(rb_eIndexError, "key not found");
+
+ return valstr;
}
static VALUE
fgdbm_index(obj, valstr)
VALUE obj, valstr;
{
- datum key, val;
struct dbmdata *dbmp;
GDBM_FILE dbm;
+ VALUE keystr, valstr2;
- Check_Type(valstr, T_STRING);
- val.dptr = RSTRING(valstr)->ptr;
- val.dsize = RSTRING(valstr)->len;
-
+ valstr = rb_str_to_str(valstr);
GetDBM(obj, dbmp);
dbm = dbmp->di_dbm;
- for (key = gdbm_firstkey(dbm); key.dptr; key = gdbm_nextkey(dbm, key)) {
- val = gdbm_fetch(dbm, key);
- if (val.dsize == RSTRING(valstr)->len &&
- memcmp(val.dptr, RSTRING(valstr)->ptr, val.dsize) == 0)
- return rb_tainted_str_new(key.dptr, key.dsize);
+ for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
+ keystr = rb_gdbm_nextkey(dbm, keystr)) {
+
+ valstr2 = rb_gdbm_fetch2(dbm, keystr);
+ if (!NIL_P(valstr2) &&
+ RSTRING(valstr)->len == RSTRING(valstr2)->len &&
+ memcmp(RSTRING(valstr)->ptr, RSTRING(valstr2)->ptr,
+ RSTRING(valstr)->len) == 0) {
+ return keystr;
+ }
}
return Qnil;
}
@@ -185,30 +322,59 @@ fgdbm_indexes(argc, argv, obj)
}
static VALUE
+rb_gdbm_delete(obj, keystr)
+ VALUE obj, keystr;
+{
+ datum key;
+ struct dbmdata *dbmp;
+ GDBM_FILE dbm;
+
+ rb_secure(4);
+ keystr = rb_str_to_str(keystr);
+ key.dptr = RSTRING(keystr)->ptr;
+ key.dsize = RSTRING(keystr)->len;
+
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+
+ if (!gdbm_exists(dbm, key)) {
+ return Qnil;
+ }
+
+ if (gdbm_delete(dbm, key)) {
+ dbmp->di_size = -1;
+ rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
+ }
+ else if (dbmp->di_size >= 0) {
+ dbmp->di_size--;
+ }
+ return obj;
+}
+
+static VALUE
fgdbm_delete(obj, keystr)
VALUE obj, keystr;
{
- datum key, value;
+ datum key;
struct dbmdata *dbmp;
GDBM_FILE dbm;
rb_secure(4);
- Check_Type(keystr, T_STRING);
+ keystr = rb_str_to_str(keystr);
key.dptr = RSTRING(keystr)->ptr;
key.dsize = RSTRING(keystr)->len;
GetDBM(obj, dbmp);
dbm = dbmp->di_dbm;
- value = gdbm_fetch(dbm, key);
- if (value.dptr == 0) {
+ if (!gdbm_exists(dbm, key)) {
if (rb_block_given_p()) rb_yield(keystr);
return Qnil;
}
if (gdbm_delete(dbm, key)) {
dbmp->di_size = -1;
- rb_raise(rb_eRuntimeError, "gdbm_delete failed");
+ rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
}
else if (dbmp->di_size >= 0) {
dbmp->di_size--;
@@ -220,7 +386,6 @@ static VALUE
fgdbm_shift(obj)
VALUE obj;
{
- datum key, val;
struct dbmdata *dbmp;
GDBM_FILE dbm;
VALUE keystr, valstr;
@@ -229,13 +394,11 @@ fgdbm_shift(obj)
GetDBM(obj, dbmp);
dbm = dbmp->di_dbm;
- key = gdbm_firstkey(dbm);
- if (!key.dptr) return Qnil;
- val = gdbm_fetch(dbm, key);
- gdbm_delete(dbm, key);
+ keystr = rb_gdbm_firstkey(dbm);
+ if (NIL_P(keystr)) return Qnil;
+ valstr = rb_gdbm_fetch2(dbm, keystr);
+ rb_gdbm_delete(obj, keystr);
- keystr = rb_tainted_str_new(key.dptr, key.dsize);
- valstr = rb_tainted_str_new(val.dptr, val.dsize);
return rb_assoc_new(keystr, valstr);
}
@@ -243,24 +406,34 @@ static VALUE
fgdbm_delete_if(obj)
VALUE obj;
{
- datum key, val;
struct dbmdata *dbmp;
GDBM_FILE dbm;
VALUE keystr, valstr;
+ VALUE ret, ary = rb_ary_new();
+ int i, status = 0, n;
rb_secure(4);
GetDBM(obj, dbmp);
dbm = dbmp->di_dbm;
- for (key = gdbm_firstkey(dbm); key.dptr; key = gdbm_nextkey(dbm, key)) {
- val = gdbm_fetch(dbm, key);
- keystr = rb_tainted_str_new(key.dptr, key.dsize);
- valstr = rb_tainted_str_new(val.dptr, val.dsize);
- if (RTEST(rb_yield(rb_assoc_new(keystr, valstr)))) {
- if (gdbm_delete(dbm, key)) {
- rb_raise(rb_eRuntimeError, "gdbm_delete failed");
- }
- }
+ n = dbmp->di_size;
+ dbmp->di_size = -1;
+
+ for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
+ keystr = rb_gdbm_nextkey(dbm, keystr)) {
+
+ valstr = rb_gdbm_fetch2(dbm, keystr);
+ ret = rb_protect(rb_yield, rb_assoc_new(rb_str_dup(keystr), valstr), &status);
+ if (status != 0) goto delete;
+ if (RTEST(ret)) rb_ary_push(ary, keystr);
+ else dbmp->di_size++;
}
+
+ delete:
+ for (i = 0; i < RARRAY(ary)->len; i++)
+ rb_gdbm_delete(obj, RARRAY(ary)->ptr[i]);
+ if (status) rb_jump_tag(status);
+ if (n > 0) dbmp->di_size = n - RARRAY(ary)->len;
+
return obj;
}
@@ -276,12 +449,20 @@ fgdbm_clear(obj)
GetDBM(obj, dbmp);
dbm = dbmp->di_dbm;
dbmp->di_size = -1;
- for (key = gdbm_firstkey(dbm); key.dptr; key = nextkey) {
- nextkey = gdbm_nextkey(dbm, key);
- if (gdbm_delete(dbm, key)) {
- rb_raise(rb_eRuntimeError, "gdbm_delete failed");
- }
+
+ while (key = gdbm_firstkey(dbm), key.dptr) {
+ for (; key.dptr; key = nextkey) {
+ nextkey = gdbm_nextkey(dbm, key);
+ if (gdbm_delete(dbm, key)) {
+ free(key.dptr);
+ if (nextkey.dptr) free(nextkey.dptr);
+ rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
+ }
+ free(key.dptr);
+ }
}
+ dbmp->di_size = 0;
+
return obj;
}
@@ -289,7 +470,6 @@ static VALUE
fgdbm_invert(obj)
VALUE obj;
{
- datum key, val;
struct dbmdata *dbmp;
GDBM_FILE dbm;
VALUE keystr, valstr;
@@ -297,10 +477,10 @@ fgdbm_invert(obj)
GetDBM(obj, dbmp);
dbm = dbmp->di_dbm;
- for (key = gdbm_firstkey(dbm); key.dptr; key = gdbm_nextkey(dbm, key)) {
- val = gdbm_fetch(dbm, key);
- keystr = rb_tainted_str_new(key.dptr, key.dsize);
- valstr = rb_tainted_str_new(val.dptr, val.dsize);
+ for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
+ keystr = rb_gdbm_nextkey(dbm, keystr)) {
+ valstr = rb_gdbm_fetch2(dbm, keystr);
+
rb_hash_aset(hash, valstr, keystr);
}
return hash;
@@ -353,12 +533,11 @@ fgdbm_store(obj, keystr, valstr)
GDBM_FILE dbm;
rb_secure(4);
- keystr = rb_obj_as_string(keystr);
-
+ keystr = rb_str_to_str(keystr);
key.dptr = RSTRING(keystr)->ptr;
key.dsize = RSTRING(keystr)->len;
- valstr = rb_obj_as_string(valstr);
+ valstr = rb_str_to_str(valstr);
val.dptr = RSTRING(valstr)->ptr;
val.dsize = RSTRING(valstr)->len;
@@ -367,7 +546,7 @@ fgdbm_store(obj, keystr, valstr)
dbm = dbmp->di_dbm;
if (gdbm_store(dbm, key, val, GDBM_REPLACE)) {
if (errno == EPERM) rb_sys_fail(0);
- rb_raise(rb_eRuntimeError, "gdbm_store failed");
+ rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
}
return valstr;
@@ -377,7 +556,7 @@ static VALUE
fgdbm_length(obj)
VALUE obj;
{
- datum key;
+ datum key, nextkey;
struct dbmdata *dbmp;
GDBM_FILE dbm;
int i = 0;
@@ -386,7 +565,9 @@ fgdbm_length(obj)
if (dbmp->di_size > 0) return INT2FIX(dbmp->di_size);
dbm = dbmp->di_dbm;
- for (key = gdbm_firstkey(dbm); key.dptr; key = gdbm_nextkey(dbm, key)) {
+ for (key = gdbm_firstkey(dbm); key.dptr; key = nextkey) {
+ nextkey = gdbm_nextkey(dbm, key);
+ free(key.dptr);
i++;
}
dbmp->di_size = i;
@@ -401,20 +582,20 @@ fgdbm_empty_p(obj)
datum key;
struct dbmdata *dbmp;
GDBM_FILE dbm;
- int i = 0;
GetDBM(obj, dbmp);
if (dbmp->di_size < 0) {
dbm = dbmp->di_dbm;
- for (key = gdbm_firstkey(dbm); key.dptr; key = gdbm_nextkey(dbm, key)) {
- i++;
+ key = gdbm_firstkey(dbm);
+ if (key.dptr) {
+ free(key.dptr);
+ return Qfalse;
}
+ return Qtrue;
}
- else {
- i = dbmp->di_size;
- }
- if (i == 0) return Qtrue;
+
+ if (dbmp->di_size == 0) return Qtrue;
return Qfalse;
}
@@ -422,15 +603,17 @@ static VALUE
fgdbm_each_value(obj)
VALUE obj;
{
- datum key, val;
struct dbmdata *dbmp;
GDBM_FILE dbm;
+ VALUE keystr;
GetDBM(obj, dbmp);
dbm = dbmp->di_dbm;
- for (key = gdbm_firstkey(dbm); key.dptr; key = gdbm_nextkey(dbm, key)) {
- val = gdbm_fetch(dbm, key);
- rb_yield(rb_tainted_str_new(val.dptr, val.dsize));
+
+ for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
+ keystr = rb_gdbm_nextkey(dbm, keystr)) {
+
+ rb_yield(rb_gdbm_fetch2(dbm, keystr));
}
return obj;
}
@@ -439,14 +622,17 @@ static VALUE
fgdbm_each_key(obj)
VALUE obj;
{
- datum key;
struct dbmdata *dbmp;
GDBM_FILE dbm;
+ VALUE keystr;
GetDBM(obj, dbmp);
dbm = dbmp->di_dbm;
- for (key = gdbm_firstkey(dbm); key.dptr; key = gdbm_nextkey(dbm, key)) {
- rb_yield(rb_tainted_str_new(key.dptr, key.dsize));
+
+ for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
+ keystr = rb_gdbm_nextkey(dbm, keystr)) {
+
+ rb_yield(rb_str_dup(keystr));
}
return obj;
}
@@ -455,19 +641,18 @@ static VALUE
fgdbm_each_pair(obj)
VALUE obj;
{
- datum key, val;
GDBM_FILE dbm;
struct dbmdata *dbmp;
- VALUE keystr, valstr;
+ VALUE keystr;
GetDBM(obj, dbmp);
dbm = dbmp->di_dbm;
- for (key = gdbm_firstkey(dbm); key.dptr; key = gdbm_nextkey(dbm, key)) {
- val = gdbm_fetch(dbm, key);
- keystr = rb_tainted_str_new(key.dptr, key.dsize);
- valstr = rb_tainted_str_new(val.dptr, val.dsize);
- rb_yield(rb_assoc_new(keystr, valstr));
+ for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
+ keystr = rb_gdbm_nextkey(dbm, keystr)) {
+
+ rb_yield(rb_assoc_new(rb_str_dup(keystr),
+ rb_gdbm_fetch2(dbm, keystr)));
}
return obj;
@@ -477,17 +662,18 @@ static VALUE
fgdbm_keys(obj)
VALUE obj;
{
- datum key;
struct dbmdata *dbmp;
GDBM_FILE dbm;
- VALUE ary;
+ VALUE keystr, ary;
GetDBM(obj, dbmp);
dbm = dbmp->di_dbm;
ary = rb_ary_new();
- for (key = gdbm_firstkey(dbm); key.dptr; key = gdbm_nextkey(dbm, key)) {
- rb_ary_push(ary, rb_tainted_str_new(key.dptr, key.dsize));
+ for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
+ keystr = rb_gdbm_nextkey(dbm, keystr)) {
+
+ rb_ary_push(ary, keystr);
}
return ary;
@@ -497,18 +683,20 @@ static VALUE
fgdbm_values(obj)
VALUE obj;
{
- datum key, val;
+ datum key, nextkey;
struct dbmdata *dbmp;
GDBM_FILE dbm;
- VALUE ary;
+ VALUE valstr, ary;
GetDBM(obj, dbmp);
dbm = dbmp->di_dbm;
ary = rb_ary_new();
- for (key = gdbm_firstkey(dbm); key.dptr; key = gdbm_nextkey(dbm, key)) {
- val = gdbm_fetch(dbm, key);
- rb_ary_push(ary, rb_tainted_str_new(val.dptr, val.dsize));
+ for (key = gdbm_firstkey(dbm); key.dptr; key = nextkey) {
+ nextkey = gdbm_nextkey(dbm, key);
+ valstr = rb_gdbm_fetch(dbm, key);
+ free(key.dptr);
+ rb_ary_push(ary, valstr);
}
return ary;
@@ -518,18 +706,18 @@ static VALUE
fgdbm_has_key(obj, keystr)
VALUE obj, keystr;
{
- datum key, val;
+ datum key;
struct dbmdata *dbmp;
GDBM_FILE dbm;
- Check_Type(keystr, T_STRING);
+ keystr = rb_str_to_str(keystr);
key.dptr = RSTRING(keystr)->ptr;
key.dsize = RSTRING(keystr)->len;
GetDBM(obj, dbmp);
dbm = dbmp->di_dbm;
- val = gdbm_fetch(dbm, key);
- if (val.dptr) return Qtrue;
+ if (gdbm_exists(dbm, key))
+ return Qtrue;
return Qfalse;
}
@@ -537,21 +725,24 @@ static VALUE
fgdbm_has_value(obj, valstr)
VALUE obj, valstr;
{
- datum key, val;
struct dbmdata *dbmp;
GDBM_FILE dbm;
+ VALUE keystr, valstr2;
- Check_Type(valstr, T_STRING);
- val.dptr = RSTRING(valstr)->ptr;
- val.dsize = RSTRING(valstr)->len;
-
+ valstr = rb_str_to_str(valstr);
GetDBM(obj, dbmp);
dbm = dbmp->di_dbm;
- for (key = gdbm_firstkey(dbm); key.dptr; key = gdbm_nextkey(dbm, key)) {
- val = gdbm_fetch(dbm, key);
- if (val.dsize == RSTRING(valstr)->len &&
- memcmp(val.dptr, RSTRING(valstr)->ptr, val.dsize) == 0)
+ for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
+ keystr = rb_gdbm_nextkey(dbm, keystr)) {
+
+ valstr2 = rb_gdbm_fetch2(dbm, keystr);
+
+ if (!NIL_P(valstr2) &&
+ RSTRING(valstr)->len == RSTRING(valstr2)->len &&
+ memcmp(RSTRING(valstr)->ptr, RSTRING(valstr2)->ptr,
+ RSTRING(valstr)->len) == 0) {
return Qtrue;
+ }
}
return Qfalse;
}
@@ -560,19 +751,19 @@ static VALUE
fgdbm_to_a(obj)
VALUE obj;
{
- datum key, val;
struct dbmdata *dbmp;
GDBM_FILE dbm;
- VALUE ary;
+ VALUE keystr, ary;
GetDBM(obj, dbmp);
dbm = dbmp->di_dbm;
ary = rb_ary_new();
- for (key = gdbm_firstkey(dbm); key.dptr; key = gdbm_nextkey(dbm, key)) {
- val = gdbm_fetch(dbm, key);
- rb_ary_push(ary, rb_assoc_new(rb_tainted_str_new(key.dptr, key.dsize),
- rb_tainted_str_new(val.dptr, val.dsize)));
+ for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
+ keystr = rb_gdbm_nextkey(dbm, keystr)) {
+
+ rb_ary_push(ary, rb_assoc_new(rb_str_dup(keystr),
+ rb_gdbm_fetch2(dbm, keystr)));
}
return ary;
@@ -593,22 +784,100 @@ fgdbm_reorganize(obj)
}
static VALUE
+fgdbm_sync(obj)
+ VALUE obj;
+{
+ struct dbmdata *dbmp;
+ GDBM_FILE dbm;
+
+ rb_secure(4);
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+ gdbm_sync(dbm);
+ return obj;
+}
+
+static VALUE
+fgdbm_set_cachesize(obj, val)
+ VALUE obj, val;
+{
+ struct dbmdata *dbmp;
+ GDBM_FILE dbm;
+ int optval;
+
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+
+ optval = FIX2INT(val);
+ if (gdbm_setopt(dbm, GDBM_CACHESIZE, &optval, sizeof(optval)) == -1) {
+ rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
+ }
+ return val;
+}
+
+static VALUE
+fgdbm_set_fastmode(obj, val)
+ VALUE obj, val;
+{
+ struct dbmdata *dbmp;
+ GDBM_FILE dbm;
+ int optval;
+
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+
+ optval = 0;
+ if (RTEST(val))
+ optval = 1;
+
+ if (gdbm_setopt(dbm, GDBM_FASTMODE, &optval, sizeof(optval)) == -1) {
+ rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
+ }
+ return val;
+}
+
+static VALUE
+fgdbm_set_syncmode(obj, val)
+ VALUE obj, val;
+{
+#if !defined(GDBM_SYNCMODE)
+ fgdbm_set_fastmode(obj, RTEST(val) ? Qfalse : Qtrue);
+ return val;
+#else
+ struct dbmdata *dbmp;
+ GDBM_FILE dbm;
+ int optval;
+
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+
+ optval = 0;
+ if (RTEST(val))
+ optval = 1;
+
+ if (gdbm_setopt(dbm, GDBM_FASTMODE, &optval, sizeof(optval)) == -1) {
+ rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
+ }
+ return val;
+#endif
+}
+
+static VALUE
fgdbm_to_hash(obj)
VALUE obj;
{
- datum key, val;
struct dbmdata *dbmp;
GDBM_FILE dbm;
- VALUE hash;
+ VALUE keystr, hash;
GetDBM(obj, dbmp);
dbm = dbmp->di_dbm;
hash = rb_hash_new();
- for (key = gdbm_firstkey(dbm); key.dptr; key = gdbm_nextkey(dbm, key)) {
- val = gdbm_fetch(dbm, key);
- rb_hash_aset(hash, rb_tainted_str_new(key.dptr, key.dsize),
- rb_tainted_str_new(val.dptr, val.dsize));
+ for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
+ keystr = rb_gdbm_nextkey(dbm, keystr)) {
+
+ rb_hash_aset(hash, keystr, rb_gdbm_fetch2(dbm, keystr));
}
return hash;
@@ -625,10 +894,13 @@ void
Init_gdbm()
{
cGDBM = rb_define_class("GDBM", rb_cObject);
+ rb_eGDBMError = rb_define_class("GDBMError", rb_eStandardError);
rb_include_module(cGDBM, rb_mEnumerable);
+ rb_define_singleton_method(cGDBM, "new", fgdbm_s_new, -1);
rb_define_singleton_method(cGDBM, "open", fgdbm_s_open, -1);
- rb_define_singleton_method(cGDBM, "new", fgdbm_s_open, -1);
+
+ rb_define_method(cGDBM, "initialize", fgdbm_initialize, -1);
rb_define_method(cGDBM, "close", fgdbm_close, 0);
rb_define_method(cGDBM, "[]", fgdbm_aref, 1);
rb_define_method(cGDBM, "fetch", fgdbm_fetch_m, -1);
@@ -646,7 +918,7 @@ Init_gdbm()
rb_define_method(cGDBM, "each_pair", fgdbm_each_pair, 0);
rb_define_method(cGDBM, "keys", fgdbm_keys, 0);
rb_define_method(cGDBM, "values", fgdbm_values, 0);
- rb_define_method(cGDBM, "shift", fgdbm_shift, 1);
+ rb_define_method(cGDBM, "shift", fgdbm_shift, 0);
rb_define_method(cGDBM, "delete", fgdbm_delete, 1);
rb_define_method(cGDBM, "delete_if", fgdbm_delete_if, 0);
rb_define_method(cGDBM, "reject!", fgdbm_delete_if, 0);
@@ -656,6 +928,11 @@ Init_gdbm()
rb_define_method(cGDBM,"update", fgdbm_update, 1);
rb_define_method(cGDBM,"replace", fgdbm_replace, 1);
rb_define_method(cGDBM,"reorganize", fgdbm_reorganize, 0);
+ rb_define_method(cGDBM,"sync", fgdbm_sync, 0);
+ /* rb_define_method(cGDBM,"setopt", fgdbm_setopt, 2); */
+ rb_define_method(cGDBM,"cachesize=", fgdbm_set_cachesize, 1);
+ rb_define_method(cGDBM,"fastmode=", fgdbm_set_fastmode, 1);
+ rb_define_method(cGDBM,"syncmode=", fgdbm_set_syncmode, 1);
rb_define_method(cGDBM, "include?", fgdbm_has_key, 1);
rb_define_method(cGDBM, "has_key?", fgdbm_has_key, 1);
@@ -666,4 +943,24 @@ Init_gdbm()
rb_define_method(cGDBM, "to_a", fgdbm_to_a, 0);
rb_define_method(cGDBM, "to_hash", fgdbm_to_hash, 0);
+
+ /* flags for gdbm_opn() */
+ /*
+ rb_define_const(cGDBM, "READER", INT2FIX(GDBM_READER));
+ rb_define_const(cGDBM, "WRITER", INT2FIX(GDBM_WRITER));
+ rb_define_const(cGDBM, "WRCREAT", INT2FIX(GDBM_WRCREAT));
+ rb_define_const(cGDBM, "NEWDB", INT2FIX(GDBM_NEWDB));
+ */
+ rb_define_const(cGDBM, "FAST", INT2FIX(GDBM_FAST));
+ /* this flag is obsolete in gdbm 1.8.
+ On gdbm 1.8, fast mode is default behavior. */
+
+ /* gdbm version 1.8 specific */
+#if defined(GDBM_SYNC)
+ rb_define_const(cGDBM, "SYNC", INT2FIX(GDBM_SYNC));
+#endif
+#if defined(GDBM_NOLOCK)
+ rb_define_const(cGDBM, "NOLOCK", INT2FIX(GDBM_NOLOCK));
+#endif
+ rb_define_const(cGDBM, "VERSION", rb_str_new2(gdbm_version));
}
diff --git a/ext/sdbm/init.c b/ext/sdbm/init.c
index 87136e9bdb..458695fc2b 100644
--- a/ext/sdbm/init.c
+++ b/ext/sdbm/init.c
@@ -6,7 +6,7 @@
$Date$
created at: Fri May 7 08:34:24 JST 1999
- Copyright (C) 1995-1998 Yukihiro Matsumoto
+ Copyright (C) 1995-2001 Yukihiro Matsumoto
************************************************/
@@ -16,7 +16,7 @@
#include <fcntl.h>
#include <errno.h>
-VALUE cSDBM;
+static VALUE cSDBM;
struct dbmdata {
int di_size;
@@ -44,16 +44,28 @@ free_sdbm(dbmp)
}
static VALUE
-fsdbm_s_open(argc, argv, klass)
+fsdbm_close(obj)
+ VALUE obj;
+{
+ struct dbmdata *dbmp;
+
+ GetDBM(obj, dbmp);
+ sdbm_close(dbmp->di_dbm);
+ dbmp->di_dbm = 0;
+
+ return Qnil;
+}
+
+static VALUE
+fsdbm_initialize(argc, argv, obj)
int argc;
VALUE *argv;
- VALUE klass;
+ VALUE obj;
{
VALUE file, vmode;
DBM *dbm;
struct dbmdata *dbmp;
int mode;
- VALUE obj;
if (rb_scan_args(argc, argv, "11", &file, &vmode) == 1) {
mode = 0666; /* default value */
@@ -64,6 +76,7 @@ fsdbm_s_open(argc, argv, klass)
else {
mode = NUM2INT(vmode);
}
+ file = rb_str_to_str(file);
Check_SafeStr(file);
dbm = 0;
@@ -79,7 +92,8 @@ fsdbm_s_open(argc, argv, klass)
rb_sys_fail(RSTRING(file)->ptr);
}
- obj = Data_Make_Struct(klass,struct dbmdata,0,free_sdbm,dbmp);
+ dbmp = ALLOC(struct dbmdata);
+ DATA_PTR(obj) = dbmp;
dbmp->di_dbm = dbm;
dbmp->di_size = -1;
@@ -87,16 +101,33 @@ fsdbm_s_open(argc, argv, klass)
}
static VALUE
-fsdbm_close(obj)
- VALUE obj;
+fsdbm_s_new(argc, argv, klass)
+ int argc;
+ VALUE *argv;
+ VALUE klass;
{
- struct dbmdata *dbmp;
+ VALUE obj = Data_Wrap_Struct(klass, 0, free_sdbm, 0);
+ rb_obj_call_init(obj, argc, argv);
+ return obj;
+}
- GetDBM(obj, dbmp);
- sdbm_close(dbmp->di_dbm);
- dbmp->di_dbm = 0;
+static VALUE
+fsdbm_s_open(argc, argv, klass)
+ int argc;
+ VALUE *argv;
+ VALUE klass;
+{
+ VALUE obj = Data_Wrap_Struct(klass, 0, free_sdbm, 0);
- return Qnil;
+ if (NIL_P(fsdbm_initialize(argc, argv, obj))) {
+ return Qnil;
+ }
+
+ if (rb_block_given_p()) {
+ return rb_ensure(rb_yield, obj, fsdbm_close, obj);
+ }
+
+ return obj;
}
static VALUE
@@ -107,7 +138,7 @@ fsdbm_fetch(obj, keystr, ifnone)
struct dbmdata *dbmp;
DBM *dbm;
- Check_Type(keystr, T_STRING);
+ keystr = rb_str_to_str(keystr);
key.dptr = RSTRING(keystr)->ptr;
key.dsize = RSTRING(keystr)->len;
@@ -135,10 +166,14 @@ fsdbm_fetch_m(argc, argv, obj)
VALUE *argv;
VALUE obj;
{
- VALUE keystr, ifnone;
+ VALUE keystr, valstr, ifnone;
rb_scan_args(argc, argv, "11", &keystr, &ifnone);
- return fsdbm_fetch(obj, keystr, ifnone);
+ valstr = fsdbm_fetch(obj, keystr, ifnone);
+ if (argc == 1 && !rb_block_given_p() && NIL_P(valstr))
+ rb_raise(rb_eIndexError, "key not found");
+
+ return valstr;
}
static VALUE
@@ -149,7 +184,7 @@ fsdbm_index(obj, valstr)
struct dbmdata *dbmp;
DBM *dbm;
- Check_Type(valstr, T_STRING);
+ valstr = rb_str_to_str(valstr);
val.dptr = RSTRING(valstr)->ptr;
val.dsize = RSTRING(valstr)->len;
@@ -190,12 +225,13 @@ fsdbm_delete(obj, keystr)
DBM *dbm;
rb_secure(4);
- Check_Type(keystr, T_STRING);
+ keystr = rb_str_to_str(keystr);
key.dptr = RSTRING(keystr)->ptr;
key.dsize = RSTRING(keystr)->len;
GetDBM(obj, dbmp);
dbm = dbmp->di_dbm;
+ dbmp->di_size = -1;
value = sdbm_fetch(dbm, key);
if (value.dptr == 0) {
@@ -229,10 +265,13 @@ fsdbm_shift(obj)
key = sdbm_firstkey(dbm);
if (!key.dptr) return Qnil;
val = sdbm_fetch(dbm, key);
- sdbm_delete(dbm, key);
-
keystr = rb_tainted_str_new(key.dptr, key.dsize);
valstr = rb_tainted_str_new(val.dptr, val.dsize);
+ sdbm_delete(dbm, key);
+ if (dbmp->di_size >= 0) {
+ dbmp->di_size--;
+ }
+
return rb_assoc_new(keystr, valstr);
}
@@ -244,20 +283,34 @@ fsdbm_delete_if(obj)
struct dbmdata *dbmp;
DBM *dbm;
VALUE keystr, valstr;
+ VALUE ret, ary = rb_ary_new();
+ int i, status = 0, n;
rb_secure(4);
GetDBM(obj, dbmp);
dbm = dbmp->di_dbm;
+ n = dbmp->di_size;
+ dbmp->di_size = -1;
for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
val = sdbm_fetch(dbm, key);
keystr = rb_tainted_str_new(key.dptr, key.dsize);
valstr = rb_tainted_str_new(val.dptr, val.dsize);
- if (RTEST(rb_yield(rb_assoc_new(keystr, valstr)))) {
- if (sdbm_delete(dbm, key)) {
- rb_raise(rb_eRuntimeError, "sdbm_delete failed");
- }
+ ret = rb_protect(rb_yield, rb_assoc_new(rb_str_dup(keystr), valstr), &status);
+ if (status != 0) goto delete;
+ if (RTEST(ret)) rb_ary_push(ary, keystr);
+ }
+ delete:
+ for (i = 0; i < RARRAY(ary)->len; i++) {
+ keystr = RARRAY(ary)->ptr[i];
+ key.dptr = RSTRING(keystr)->ptr;
+ key.dsize = RSTRING(keystr)->len;
+ if (sdbm_delete(dbm, key)) {
+ rb_raise(rb_eRuntimeError, "sdbm_delete failed");
}
}
+ if (status) rb_jump_tag(status);
+ if (n > 0) dbmp->di_size = n - RARRAY(ary)->len;
+
return obj;
}
@@ -273,11 +326,16 @@ fsdbm_clear(obj)
GetDBM(obj, dbmp);
dbm = dbmp->di_dbm;
dbmp->di_size = -1;
- for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
- if (sdbm_delete(dbm, key)) {
- rb_raise(rb_eRuntimeError, "sdbm_delete failed");
- }
+ while (key = sdbm_firstkey(dbm), key.dptr) {
+ do {
+ if (sdbm_delete(dbm, key)) {
+ rb_raise(rb_eRuntimeError, "sdbm_delete failed");
+ }
+ key = sdbm_nextkey(dbm);
+ } while (key.dptr);
}
+ dbmp->di_size = 0;
+
return obj;
}
@@ -299,7 +357,7 @@ fsdbm_invert(obj)
valstr = rb_tainted_str_new(val.dptr, val.dsize);
rb_hash_aset(hash, valstr, keystr);
}
- return obj;
+ return hash;
}
static VALUE
@@ -528,7 +586,7 @@ fsdbm_has_key(obj, keystr)
struct dbmdata *dbmp;
DBM *dbm;
- Check_Type(keystr, T_STRING);
+ keystr = rb_str_to_str(keystr);
key.dptr = RSTRING(keystr)->ptr;
key.dsize = RSTRING(keystr)->len;
@@ -547,7 +605,7 @@ fsdbm_has_value(obj, valstr)
struct dbmdata *dbmp;
DBM *dbm;
- Check_Type(valstr, T_STRING);
+ valstr = rb_str_to_str(valstr);
val.dptr = RSTRING(valstr)->ptr;
val.dsize = RSTRING(valstr)->len;
@@ -620,7 +678,8 @@ Init_sdbm()
rb_include_module(cSDBM, rb_mEnumerable);
rb_define_singleton_method(cSDBM, "open", fsdbm_s_open, -1);
- rb_define_singleton_method(cSDBM, "new", fsdbm_s_open, -1);
+ rb_define_singleton_method(cSDBM, "new", fsdbm_s_new, -1);
+ rb_define_method(cSDBM, "initialize", fsdbm_initialize, -1);
rb_define_method(cSDBM, "close", fsdbm_close, 0);
rb_define_method(cSDBM, "[]", fsdbm_aref, 1);
rb_define_method(cSDBM, "fetch", fsdbm_fetch_m, -1);
@@ -638,7 +697,7 @@ Init_sdbm()
rb_define_method(cSDBM, "each_pair", fsdbm_each_pair, 0);
rb_define_method(cSDBM, "keys", fsdbm_keys, 0);
rb_define_method(cSDBM, "values", fsdbm_values, 0);
- rb_define_method(cSDBM, "shift", fsdbm_shift, 1);
+ rb_define_method(cSDBM, "shift", fsdbm_shift, 0);
rb_define_method(cSDBM, "delete", fsdbm_delete, 1);
rb_define_method(cSDBM, "delete_if", fsdbm_delete_if, 0);
rb_define_method(cSDBM, "reject!", fsdbm_delete_if, 0);
diff --git a/ext/tk/lib/tk.rb b/ext/tk/lib/tk.rb
index 59d78da5d2..262adec3f2 100644
--- a/ext/tk/lib/tk.rb
+++ b/ext/tk/lib/tk.rb
@@ -1,5 +1,5 @@
#
-# tk.rb - Tk interface modue using tcltklib
+# tk.rb - Tk interface module using tcltklib
# $Date$
# by Yukihiro Matsumoto <matz@netlab.co.jp>