00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "ruby.h"
00013
00014 #ifdef HAVE_CDEFS_H
00015 # include <cdefs.h>
00016 #endif
00017 #ifdef HAVE_SYS_CDEFS_H
00018 # include <sys/cdefs.h>
00019 #endif
00020 #include DBM_HDR
00021 #include <fcntl.h>
00022 #include <errno.h>
00023
00024 #define DSIZE_TYPE TYPEOF_DATUM_DSIZE
00025 #if SIZEOF_DATUM_DSIZE > SIZEOF_INT
00026 # define RSTRING_DSIZE(s) RSTRING_LEN(s)
00027 # define TOO_LONG(n) 0
00028 #else
00029 # define RSTRING_DSIZE(s) RSTRING_LENINT(s)
00030 # define TOO_LONG(n) ((long)(+(DSIZE_TYPE)(n)) != (n))
00031 #endif
00032
00033 static VALUE rb_cDBM, rb_eDBMError;
00034
00035 #define RUBY_DBM_RW_BIT 0x20000000
00036
00037 struct dbmdata {
00038 long di_size;
00039 DBM *di_dbm;
00040 };
00041
00042 static void
00043 closed_dbm(void)
00044 {
00045 rb_raise(rb_eDBMError, "closed DBM file");
00046 }
00047
00048 #define GetDBM(obj, dbmp) {\
00049 Data_Get_Struct((obj), struct dbmdata, (dbmp));\
00050 if ((dbmp) == 0) closed_dbm();\
00051 if ((dbmp)->di_dbm == 0) closed_dbm();\
00052 }
00053
00054 #define GetDBM2(obj, data, dbm) {\
00055 GetDBM((obj), (data));\
00056 (dbm) = dbmp->di_dbm;\
00057 }
00058
00059 static void
00060 free_dbm(struct dbmdata *dbmp)
00061 {
00062 if (dbmp) {
00063 if (dbmp->di_dbm) dbm_close(dbmp->di_dbm);
00064 xfree(dbmp);
00065 }
00066 }
00067
00068
00069
00070
00071
00072
00073
00074 static VALUE
00075 fdbm_close(VALUE obj)
00076 {
00077 struct dbmdata *dbmp;
00078
00079 GetDBM(obj, dbmp);
00080 dbm_close(dbmp->di_dbm);
00081 dbmp->di_dbm = 0;
00082
00083 return Qnil;
00084 }
00085
00086
00087
00088
00089
00090
00091
00092 static VALUE
00093 fdbm_closed(VALUE obj)
00094 {
00095 struct dbmdata *dbmp;
00096
00097 Data_Get_Struct(obj, struct dbmdata, dbmp);
00098 if (dbmp == 0)
00099 return Qtrue;
00100 if (dbmp->di_dbm == 0)
00101 return Qtrue;
00102
00103 return Qfalse;
00104 }
00105
00106 static VALUE
00107 fdbm_alloc(VALUE klass)
00108 {
00109 return Data_Wrap_Struct(klass, 0, free_dbm, 0);
00110 }
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125 static VALUE
00126 fdbm_initialize(int argc, VALUE *argv, VALUE obj)
00127 {
00128 volatile VALUE file;
00129 VALUE vmode, vflags;
00130 DBM *dbm;
00131 struct dbmdata *dbmp;
00132 int mode, flags = 0;
00133
00134 if (rb_scan_args(argc, argv, "12", &file, &vmode, &vflags) == 1) {
00135 mode = 0666;
00136 }
00137 else if (NIL_P(vmode)) {
00138 mode = -1;
00139 }
00140 else {
00141 mode = NUM2INT(vmode);
00142 }
00143
00144 if (!NIL_P(vflags))
00145 flags = NUM2INT(vflags);
00146
00147 FilePathValue(file);
00148
00149
00150
00151
00152
00153 #ifndef O_CLOEXEC
00154 # define O_CLOEXEC 0
00155 #endif
00156
00157 if (flags & RUBY_DBM_RW_BIT) {
00158 flags &= ~RUBY_DBM_RW_BIT;
00159 dbm = dbm_open(RSTRING_PTR(file), flags|O_CLOEXEC, mode);
00160 }
00161 else {
00162 dbm = 0;
00163 if (mode >= 0) {
00164 dbm = dbm_open(RSTRING_PTR(file), O_RDWR|O_CREAT|O_CLOEXEC, mode);
00165 }
00166 if (!dbm) {
00167 dbm = dbm_open(RSTRING_PTR(file), O_RDWR|O_CLOEXEC, 0);
00168 }
00169 if (!dbm) {
00170 dbm = dbm_open(RSTRING_PTR(file), O_RDONLY|O_CLOEXEC, 0);
00171 }
00172 }
00173
00174 if (dbm) {
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193 #if defined(HAVE_DBM_PAGFNO)
00194 rb_fd_fix_cloexec(dbm_pagfno(dbm));
00195 #endif
00196 #if defined(HAVE_DBM_DIRFNO)
00197 rb_fd_fix_cloexec(dbm_dirfno(dbm));
00198 #endif
00199
00200 #if defined(RUBYDBM_DB_HEADER) && defined(HAVE_TYPE_DBC)
00201
00202
00203 ((DBC*)dbm)->dbp->set_errfile(((DBC*)dbm)->dbp, NULL);
00204 #endif
00205 }
00206
00207 if (!dbm) {
00208 if (mode == -1) return Qnil;
00209 rb_sys_fail_str(file);
00210 }
00211
00212 dbmp = ALLOC(struct dbmdata);
00213 DATA_PTR(obj) = dbmp;
00214 dbmp->di_dbm = dbm;
00215 dbmp->di_size = -1;
00216
00217 return obj;
00218 }
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228 static VALUE
00229 fdbm_s_open(int argc, VALUE *argv, VALUE klass)
00230 {
00231 VALUE obj = Data_Wrap_Struct(klass, 0, free_dbm, 0);
00232
00233 if (NIL_P(fdbm_initialize(argc, argv, obj))) {
00234 return Qnil;
00235 }
00236
00237 if (rb_block_given_p()) {
00238 return rb_ensure(rb_yield, obj, fdbm_close, obj);
00239 }
00240
00241 return obj;
00242 }
00243
00244 static VALUE
00245 fdbm_fetch(VALUE obj, VALUE keystr, VALUE ifnone)
00246 {
00247 datum key, value;
00248 struct dbmdata *dbmp;
00249 DBM *dbm;
00250 long len;
00251
00252 ExportStringValue(keystr);
00253 len = RSTRING_LEN(keystr);
00254 if (TOO_LONG(len)) goto not_found;
00255 key.dptr = RSTRING_PTR(keystr);
00256 key.dsize = (DSIZE_TYPE)len;
00257
00258 GetDBM2(obj, dbmp, dbm);
00259 value = dbm_fetch(dbm, key);
00260 if (value.dptr == 0) {
00261 not_found:
00262 if (ifnone == Qnil && rb_block_given_p())
00263 return rb_yield(rb_tainted_str_new(key.dptr, key.dsize));
00264 return ifnone;
00265 }
00266 return rb_tainted_str_new(value.dptr, value.dsize);
00267 }
00268
00269
00270
00271
00272
00273
00274
00275
00276 static VALUE
00277 fdbm_aref(VALUE obj, VALUE keystr)
00278 {
00279 return fdbm_fetch(obj, keystr, Qnil);
00280 }
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290 static VALUE
00291 fdbm_fetch_m(int argc, VALUE *argv, VALUE obj)
00292 {
00293 VALUE keystr, valstr, ifnone;
00294
00295 rb_scan_args(argc, argv, "11", &keystr, &ifnone);
00296 valstr = fdbm_fetch(obj, keystr, ifnone);
00297 if (argc == 1 && !rb_block_given_p() && NIL_P(valstr))
00298 rb_raise(rb_eIndexError, "key not found");
00299
00300 return valstr;
00301 }
00302
00303
00304
00305
00306
00307
00308
00309 static VALUE
00310 fdbm_key(VALUE obj, VALUE valstr)
00311 {
00312 datum key, val;
00313 struct dbmdata *dbmp;
00314 DBM *dbm;
00315 long len;
00316
00317 ExportStringValue(valstr);
00318 len = RSTRING_LEN(valstr);
00319 if (TOO_LONG(len)) return Qnil;
00320 val.dptr = RSTRING_PTR(valstr);
00321 val.dsize = (DSIZE_TYPE)len;
00322
00323 GetDBM2(obj, dbmp, dbm);
00324 for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
00325 val = dbm_fetch(dbm, key);
00326 if ((long)val.dsize == RSTRING_LEN(valstr) &&
00327 memcmp(val.dptr, RSTRING_PTR(valstr), val.dsize) == 0) {
00328 return rb_tainted_str_new(key.dptr, key.dsize);
00329 }
00330 }
00331 return Qnil;
00332 }
00333
00334
00335 static VALUE
00336 fdbm_index(VALUE hash, VALUE value)
00337 {
00338 rb_warn("DBM#index is deprecated; use DBM#key");
00339 return fdbm_key(hash, value);
00340 }
00341
00342
00343
00344
00345
00346
00347
00348
00349 static VALUE
00350 fdbm_select(VALUE obj)
00351 {
00352 VALUE new = rb_ary_new();
00353 datum key, val;
00354 DBM *dbm;
00355 struct dbmdata *dbmp;
00356
00357 GetDBM2(obj, dbmp, dbm);
00358 for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
00359 VALUE assoc, v;
00360 val = dbm_fetch(dbm, key);
00361 assoc = rb_assoc_new(rb_tainted_str_new(key.dptr, key.dsize),
00362 rb_tainted_str_new(val.dptr, val.dsize));
00363 v = rb_yield(assoc);
00364 if (RTEST(v)) {
00365 rb_ary_push(new, assoc);
00366 }
00367 GetDBM2(obj, dbmp, dbm);
00368 }
00369
00370 return new;
00371 }
00372
00373
00374
00375
00376
00377
00378
00379 static VALUE
00380 fdbm_values_at(int argc, VALUE *argv, VALUE obj)
00381 {
00382 VALUE new = rb_ary_new2(argc);
00383 int i;
00384
00385 for (i=0; i<argc; i++) {
00386 rb_ary_push(new, fdbm_fetch(obj, argv[i], Qnil));
00387 }
00388
00389 return new;
00390 }
00391
00392 static void
00393 fdbm_modify(VALUE obj)
00394 {
00395 if (OBJ_FROZEN(obj)) rb_error_frozen("DBM");
00396 }
00397
00398
00399
00400
00401
00402
00403
00404 static VALUE
00405 fdbm_delete(VALUE obj, VALUE keystr)
00406 {
00407 datum key, value;
00408 struct dbmdata *dbmp;
00409 DBM *dbm;
00410 VALUE valstr;
00411 long len;
00412
00413 fdbm_modify(obj);
00414 ExportStringValue(keystr);
00415 len = RSTRING_LEN(keystr);
00416 if (TOO_LONG(len)) goto not_found;
00417 key.dptr = RSTRING_PTR(keystr);
00418 key.dsize = (DSIZE_TYPE)len;
00419
00420 GetDBM2(obj, dbmp, dbm);
00421
00422 value = dbm_fetch(dbm, key);
00423 if (value.dptr == 0) {
00424 not_found:
00425 if (rb_block_given_p()) return rb_yield(keystr);
00426 return Qnil;
00427 }
00428
00429
00430 valstr = rb_tainted_str_new(value.dptr, value.dsize);
00431
00432 if (dbm_delete(dbm, key)) {
00433 dbmp->di_size = -1;
00434 rb_raise(rb_eDBMError, "dbm_delete failed");
00435 }
00436 else if (dbmp->di_size >= 0) {
00437 dbmp->di_size--;
00438 }
00439 return valstr;
00440 }
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450 static VALUE
00451 fdbm_shift(VALUE obj)
00452 {
00453 datum key, val;
00454 struct dbmdata *dbmp;
00455 DBM *dbm;
00456 VALUE keystr, valstr;
00457
00458 fdbm_modify(obj);
00459 GetDBM2(obj, dbmp, dbm);
00460 dbmp->di_size = -1;
00461
00462 key = dbm_firstkey(dbm);
00463 if (!key.dptr) return Qnil;
00464 val = dbm_fetch(dbm, key);
00465 keystr = rb_tainted_str_new(key.dptr, key.dsize);
00466 valstr = rb_tainted_str_new(val.dptr, val.dsize);
00467 dbm_delete(dbm, key);
00468
00469 return rb_assoc_new(keystr, valstr);
00470 }
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480 static VALUE
00481 fdbm_delete_if(VALUE obj)
00482 {
00483 datum key, val;
00484 struct dbmdata *dbmp;
00485 DBM *dbm;
00486 VALUE keystr, valstr;
00487 VALUE ret, ary = rb_ary_tmp_new(0);
00488 int i, status = 0;
00489 long n;
00490
00491 fdbm_modify(obj);
00492 GetDBM2(obj, dbmp, dbm);
00493 n = dbmp->di_size;
00494 dbmp->di_size = -1;
00495
00496 for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
00497 val = dbm_fetch(dbm, key);
00498 keystr = rb_tainted_str_new(key.dptr, key.dsize);
00499 OBJ_FREEZE(keystr);
00500 valstr = rb_tainted_str_new(val.dptr, val.dsize);
00501 ret = rb_protect(rb_yield, rb_assoc_new(rb_str_dup(keystr), valstr), &status);
00502 if (status != 0) break;
00503 if (RTEST(ret)) rb_ary_push(ary, keystr);
00504 GetDBM2(obj, dbmp, dbm);
00505 }
00506
00507 for (i = 0; i < RARRAY_LEN(ary); i++) {
00508 keystr = RARRAY_PTR(ary)[i];
00509 key.dptr = RSTRING_PTR(keystr);
00510 key.dsize = (DSIZE_TYPE)RSTRING_LEN(keystr);
00511 if (dbm_delete(dbm, key)) {
00512 rb_raise(rb_eDBMError, "dbm_delete failed");
00513 }
00514 }
00515 if (status) rb_jump_tag(status);
00516 if (n > 0) dbmp->di_size = n - RARRAY_LEN(ary);
00517 rb_ary_clear(ary);
00518
00519 return obj;
00520 }
00521
00522
00523
00524
00525
00526
00527
00528 static VALUE
00529 fdbm_clear(VALUE obj)
00530 {
00531 datum key;
00532 struct dbmdata *dbmp;
00533 DBM *dbm;
00534
00535 fdbm_modify(obj);
00536 GetDBM2(obj, dbmp, dbm);
00537 dbmp->di_size = -1;
00538 while (key = dbm_firstkey(dbm), key.dptr) {
00539 if (dbm_delete(dbm, key)) {
00540 rb_raise(rb_eDBMError, "dbm_delete failed");
00541 }
00542 }
00543 dbmp->di_size = 0;
00544
00545 return obj;
00546 }
00547
00548
00549
00550
00551
00552
00553
00554
00555 static VALUE
00556 fdbm_invert(VALUE obj)
00557 {
00558 datum key, val;
00559 struct dbmdata *dbmp;
00560 DBM *dbm;
00561 VALUE keystr, valstr;
00562 VALUE hash = rb_hash_new();
00563
00564 GetDBM2(obj, dbmp, dbm);
00565 for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
00566 val = dbm_fetch(dbm, key);
00567 keystr = rb_tainted_str_new(key.dptr, key.dsize);
00568 valstr = rb_tainted_str_new(val.dptr, val.dsize);
00569 rb_hash_aset(hash, valstr, keystr);
00570 }
00571 return hash;
00572 }
00573
00574 static VALUE fdbm_store(VALUE,VALUE,VALUE);
00575
00576 static VALUE
00577 update_i(RB_BLOCK_CALL_FUNC_ARGLIST(pair, dbm))
00578 {
00579 Check_Type(pair, T_ARRAY);
00580 if (RARRAY_LEN(pair) < 2) {
00581 rb_raise(rb_eArgError, "pair must be [key, value]");
00582 }
00583 fdbm_store(dbm, RARRAY_PTR(pair)[0], RARRAY_PTR(pair)[1]);
00584 return Qnil;
00585 }
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595 static VALUE
00596 fdbm_update(VALUE obj, VALUE other)
00597 {
00598 rb_block_call(other, rb_intern("each_pair"), 0, 0, update_i, obj);
00599 return obj;
00600 }
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610 static VALUE
00611 fdbm_replace(VALUE obj, VALUE other)
00612 {
00613 fdbm_clear(obj);
00614 rb_block_call(other, rb_intern("each_pair"), 0, 0, update_i, obj);
00615 return obj;
00616 }
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626 static VALUE
00627 fdbm_store(VALUE obj, VALUE keystr, VALUE valstr)
00628 {
00629 datum key, val;
00630 struct dbmdata *dbmp;
00631 DBM *dbm;
00632
00633 fdbm_modify(obj);
00634 keystr = rb_obj_as_string(keystr);
00635 valstr = rb_obj_as_string(valstr);
00636
00637 key.dptr = RSTRING_PTR(keystr);
00638 key.dsize = RSTRING_DSIZE(keystr);
00639
00640 val.dptr = RSTRING_PTR(valstr);
00641 val.dsize = RSTRING_DSIZE(valstr);
00642
00643 GetDBM2(obj, dbmp, dbm);
00644 dbmp->di_size = -1;
00645 if (dbm_store(dbm, key, val, DBM_REPLACE)) {
00646 dbm_clearerr(dbm);
00647 if (errno == EPERM) rb_sys_fail(0);
00648 rb_raise(rb_eDBMError, "dbm_store failed");
00649 }
00650
00651 return valstr;
00652 }
00653
00654
00655
00656
00657
00658
00659
00660
00661 static VALUE
00662 fdbm_length(VALUE obj)
00663 {
00664 datum key;
00665 struct dbmdata *dbmp;
00666 DBM *dbm;
00667 int i = 0;
00668
00669 GetDBM2(obj, dbmp, dbm);
00670 if (dbmp->di_size > 0) return INT2FIX(dbmp->di_size);
00671
00672 for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
00673 i++;
00674 }
00675 dbmp->di_size = i;
00676
00677 return INT2FIX(i);
00678 }
00679
00680
00681
00682
00683
00684
00685
00686 static VALUE
00687 fdbm_empty_p(VALUE obj)
00688 {
00689 datum key;
00690 struct dbmdata *dbmp;
00691 DBM *dbm;
00692
00693 GetDBM2(obj, dbmp, dbm);
00694 if (dbmp->di_size < 0) {
00695 dbm = dbmp->di_dbm;
00696
00697 for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
00698 return Qfalse;
00699 }
00700 }
00701 else {
00702 if (dbmp->di_size)
00703 return Qfalse;
00704 }
00705 return Qtrue;
00706 }
00707
00708
00709
00710
00711
00712
00713
00714 static VALUE
00715 fdbm_each_value(VALUE obj)
00716 {
00717 datum key, val;
00718 struct dbmdata *dbmp;
00719 DBM *dbm;
00720
00721 RETURN_ENUMERATOR(obj, 0, 0);
00722
00723 GetDBM2(obj, dbmp, dbm);
00724 for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
00725 val = dbm_fetch(dbm, key);
00726 rb_yield(rb_tainted_str_new(val.dptr, val.dsize));
00727 GetDBM2(obj, dbmp, dbm);
00728 }
00729 return obj;
00730 }
00731
00732
00733
00734
00735
00736
00737
00738 static VALUE
00739 fdbm_each_key(VALUE obj)
00740 {
00741 datum key;
00742 struct dbmdata *dbmp;
00743 DBM *dbm;
00744
00745 RETURN_ENUMERATOR(obj, 0, 0);
00746
00747 GetDBM2(obj, dbmp, dbm);
00748 for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
00749 rb_yield(rb_tainted_str_new(key.dptr, key.dsize));
00750 GetDBM2(obj, dbmp, dbm);
00751 }
00752 return obj;
00753 }
00754
00755
00756
00757
00758
00759
00760
00761
00762 static VALUE
00763 fdbm_each_pair(VALUE obj)
00764 {
00765 datum key, val;
00766 DBM *dbm;
00767 struct dbmdata *dbmp;
00768 VALUE keystr, valstr;
00769
00770 RETURN_ENUMERATOR(obj, 0, 0);
00771
00772 GetDBM2(obj, dbmp, dbm);
00773
00774 for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
00775 val = dbm_fetch(dbm, key);
00776 keystr = rb_tainted_str_new(key.dptr, key.dsize);
00777 valstr = rb_tainted_str_new(val.dptr, val.dsize);
00778 rb_yield(rb_assoc_new(keystr, valstr));
00779 GetDBM2(obj, dbmp, dbm);
00780 }
00781
00782 return obj;
00783 }
00784
00785
00786
00787
00788
00789
00790
00791 static VALUE
00792 fdbm_keys(VALUE obj)
00793 {
00794 datum key;
00795 struct dbmdata *dbmp;
00796 DBM *dbm;
00797 VALUE ary;
00798
00799 GetDBM2(obj, dbmp, dbm);
00800
00801 ary = rb_ary_new();
00802 for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
00803 rb_ary_push(ary, rb_tainted_str_new(key.dptr, key.dsize));
00804 }
00805
00806 return ary;
00807 }
00808
00809
00810
00811
00812
00813
00814
00815 static VALUE
00816 fdbm_values(VALUE obj)
00817 {
00818 datum key, val;
00819 struct dbmdata *dbmp;
00820 DBM *dbm;
00821 VALUE ary;
00822
00823 GetDBM2(obj, dbmp, dbm);
00824 ary = rb_ary_new();
00825 for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
00826 val = dbm_fetch(dbm, key);
00827 rb_ary_push(ary, rb_tainted_str_new(val.dptr, val.dsize));
00828 }
00829
00830 return ary;
00831 }
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842 static VALUE
00843 fdbm_has_key(VALUE obj, VALUE keystr)
00844 {
00845 datum key, val;
00846 struct dbmdata *dbmp;
00847 DBM *dbm;
00848 long len;
00849
00850 ExportStringValue(keystr);
00851 len = RSTRING_LEN(keystr);
00852 if (TOO_LONG(len)) return Qfalse;
00853 key.dptr = RSTRING_PTR(keystr);
00854 key.dsize = (DSIZE_TYPE)len;
00855
00856 GetDBM2(obj, dbmp, dbm);
00857 val = dbm_fetch(dbm, key);
00858 if (val.dptr) return Qtrue;
00859 return Qfalse;
00860 }
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870 static VALUE
00871 fdbm_has_value(VALUE obj, VALUE valstr)
00872 {
00873 datum key, val;
00874 struct dbmdata *dbmp;
00875 DBM *dbm;
00876 long len;
00877
00878 ExportStringValue(valstr);
00879 len = RSTRING_LEN(valstr);
00880 if (TOO_LONG(len)) return Qfalse;
00881 val.dptr = RSTRING_PTR(valstr);
00882 val.dsize = (DSIZE_TYPE)len;
00883
00884 GetDBM2(obj, dbmp, dbm);
00885 for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
00886 val = dbm_fetch(dbm, key);
00887 if ((DSIZE_TYPE)val.dsize == (DSIZE_TYPE)RSTRING_LEN(valstr) &&
00888 memcmp(val.dptr, RSTRING_PTR(valstr), val.dsize) == 0)
00889 return Qtrue;
00890 }
00891 return Qfalse;
00892 }
00893
00894
00895
00896
00897
00898
00899
00900
00901 static VALUE
00902 fdbm_to_a(VALUE obj)
00903 {
00904 datum key, val;
00905 struct dbmdata *dbmp;
00906 DBM *dbm;
00907 VALUE ary;
00908
00909 GetDBM2(obj, dbmp, dbm);
00910 ary = rb_ary_new();
00911 for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
00912 val = dbm_fetch(dbm, key);
00913 rb_ary_push(ary, rb_assoc_new(rb_tainted_str_new(key.dptr, key.dsize),
00914 rb_tainted_str_new(val.dptr, val.dsize)));
00915 }
00916
00917 return ary;
00918 }
00919
00920
00921
00922
00923
00924
00925
00926
00927 static VALUE
00928 fdbm_to_hash(VALUE obj)
00929 {
00930 datum key, val;
00931 struct dbmdata *dbmp;
00932 DBM *dbm;
00933 VALUE hash;
00934
00935 GetDBM2(obj, dbmp, dbm);
00936 hash = rb_hash_new();
00937 for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
00938 val = dbm_fetch(dbm, key);
00939 rb_hash_aset(hash, rb_tainted_str_new(key.dptr, key.dsize),
00940 rb_tainted_str_new(val.dptr, val.dsize));
00941 }
00942
00943 return hash;
00944 }
00945
00946
00947
00948
00949
00950
00951
00952
00953 static VALUE
00954 fdbm_reject(VALUE obj)
00955 {
00956 return rb_hash_delete_if(fdbm_to_hash(obj));
00957 }
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020 void
01021 Init_dbm(void)
01022 {
01023 rb_cDBM = rb_define_class("DBM", rb_cObject);
01024
01025
01026
01027 rb_eDBMError = rb_define_class("DBMError", rb_eStandardError);
01028 rb_include_module(rb_cDBM, rb_mEnumerable);
01029
01030 rb_define_alloc_func(rb_cDBM, fdbm_alloc);
01031 rb_define_singleton_method(rb_cDBM, "open", fdbm_s_open, -1);
01032
01033 rb_define_method(rb_cDBM, "initialize", fdbm_initialize, -1);
01034 rb_define_method(rb_cDBM, "close", fdbm_close, 0);
01035 rb_define_method(rb_cDBM, "closed?", fdbm_closed, 0);
01036 rb_define_method(rb_cDBM, "[]", fdbm_aref, 1);
01037 rb_define_method(rb_cDBM, "fetch", fdbm_fetch_m, -1);
01038 rb_define_method(rb_cDBM, "[]=", fdbm_store, 2);
01039 rb_define_method(rb_cDBM, "store", fdbm_store, 2);
01040 rb_define_method(rb_cDBM, "index", fdbm_index, 1);
01041 rb_define_method(rb_cDBM, "key", fdbm_key, 1);
01042 rb_define_method(rb_cDBM, "select", fdbm_select, 0);
01043 rb_define_method(rb_cDBM, "values_at", fdbm_values_at, -1);
01044 rb_define_method(rb_cDBM, "length", fdbm_length, 0);
01045 rb_define_method(rb_cDBM, "size", fdbm_length, 0);
01046 rb_define_method(rb_cDBM, "empty?", fdbm_empty_p, 0);
01047 rb_define_method(rb_cDBM, "each", fdbm_each_pair, 0);
01048 rb_define_method(rb_cDBM, "each_value", fdbm_each_value, 0);
01049 rb_define_method(rb_cDBM, "each_key", fdbm_each_key, 0);
01050 rb_define_method(rb_cDBM, "each_pair", fdbm_each_pair, 0);
01051 rb_define_method(rb_cDBM, "keys", fdbm_keys, 0);
01052 rb_define_method(rb_cDBM, "values", fdbm_values, 0);
01053 rb_define_method(rb_cDBM, "shift", fdbm_shift, 0);
01054 rb_define_method(rb_cDBM, "delete", fdbm_delete, 1);
01055 rb_define_method(rb_cDBM, "delete_if", fdbm_delete_if, 0);
01056 rb_define_method(rb_cDBM, "reject!", fdbm_delete_if, 0);
01057 rb_define_method(rb_cDBM, "reject", fdbm_reject, 0);
01058 rb_define_method(rb_cDBM, "clear", fdbm_clear, 0);
01059 rb_define_method(rb_cDBM, "invert", fdbm_invert, 0);
01060 rb_define_method(rb_cDBM, "update", fdbm_update, 1);
01061 rb_define_method(rb_cDBM, "replace", fdbm_replace, 1);
01062
01063 rb_define_method(rb_cDBM, "include?", fdbm_has_key, 1);
01064 rb_define_method(rb_cDBM, "has_key?", fdbm_has_key, 1);
01065 rb_define_method(rb_cDBM, "member?", fdbm_has_key, 1);
01066 rb_define_method(rb_cDBM, "has_value?", fdbm_has_value, 1);
01067 rb_define_method(rb_cDBM, "key?", fdbm_has_key, 1);
01068 rb_define_method(rb_cDBM, "value?", fdbm_has_value, 1);
01069
01070 rb_define_method(rb_cDBM, "to_a", fdbm_to_a, 0);
01071 rb_define_method(rb_cDBM, "to_hash", fdbm_to_hash, 0);
01072
01073
01074 rb_define_const(rb_cDBM, "READER", INT2FIX(O_RDONLY|RUBY_DBM_RW_BIT));
01075
01076
01077 rb_define_const(rb_cDBM, "WRITER", INT2FIX(O_RDWR|RUBY_DBM_RW_BIT));
01078
01079
01080
01081
01082 rb_define_const(rb_cDBM, "WRCREAT", INT2FIX(O_RDWR|O_CREAT|RUBY_DBM_RW_BIT));
01083
01084
01085
01086
01087
01088 rb_define_const(rb_cDBM, "NEWDB", INT2FIX(O_RDWR|O_CREAT|O_TRUNC|RUBY_DBM_RW_BIT));
01089
01090 {
01091 VALUE version;
01092 #if defined(_DBM_IOERR)
01093 version = rb_str_new2("ndbm (4.3BSD)");
01094 #elif defined(RUBYDBM_GDBM_HEADER)
01095 # if defined(HAVE_DECLARED_LIBVAR_GDBM_VERSION)
01096
01097 version = rb_str_new2(gdbm_version);
01098 # elif defined(HAVE_UNDECLARED_LIBVAR_GDBM_VERSION)
01099
01100
01101 RUBY_EXTERN char *gdbm_version;
01102 version = rb_str_new2(gdbm_version);
01103 # else
01104 version = rb_str_new2("GDBM (unknown)");
01105 # endif
01106 #elif defined(RUBYDBM_DB_HEADER)
01107 # if defined(HAVE_DB_VERSION)
01108
01109 version = rb_str_new2(db_version(NULL, NULL, NULL));
01110 # else
01111 version = rb_str_new2("Berkeley DB (unknown)");
01112 # endif
01113 #elif defined(_RELIC_H)
01114 # if defined(HAVE_DPVERSION)
01115 version = rb_sprintf("QDBM %s", dpversion);
01116 # else
01117 version = rb_str_new2("QDBM (unknown)");
01118 # endif
01119 #else
01120 version = rb_str_new2("ndbm (unknown)");
01121 #endif
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132
01133
01134 rb_define_const(rb_cDBM, "VERSION", version);
01135 }
01136 }
01137