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 rb_secure(4);
00396 if (OBJ_FROZEN(obj)) rb_error_frozen("DBM");
00397 }
00398
00399
00400
00401
00402
00403
00404
00405 static VALUE
00406 fdbm_delete(VALUE obj, VALUE keystr)
00407 {
00408 datum key, value;
00409 struct dbmdata *dbmp;
00410 DBM *dbm;
00411 VALUE valstr;
00412 long len;
00413
00414 fdbm_modify(obj);
00415 ExportStringValue(keystr);
00416 len = RSTRING_LEN(keystr);
00417 if (TOO_LONG(len)) goto not_found;
00418 key.dptr = RSTRING_PTR(keystr);
00419 key.dsize = (DSIZE_TYPE)len;
00420
00421 GetDBM2(obj, dbmp, dbm);
00422
00423 value = dbm_fetch(dbm, key);
00424 if (value.dptr == 0) {
00425 not_found:
00426 if (rb_block_given_p()) return rb_yield(keystr);
00427 return Qnil;
00428 }
00429
00430
00431 valstr = rb_tainted_str_new(value.dptr, value.dsize);
00432
00433 if (dbm_delete(dbm, key)) {
00434 dbmp->di_size = -1;
00435 rb_raise(rb_eDBMError, "dbm_delete failed");
00436 }
00437 else if (dbmp->di_size >= 0) {
00438 dbmp->di_size--;
00439 }
00440 return valstr;
00441 }
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451 static VALUE
00452 fdbm_shift(VALUE obj)
00453 {
00454 datum key, val;
00455 struct dbmdata *dbmp;
00456 DBM *dbm;
00457 VALUE keystr, valstr;
00458
00459 fdbm_modify(obj);
00460 GetDBM2(obj, dbmp, dbm);
00461 dbmp->di_size = -1;
00462
00463 key = dbm_firstkey(dbm);
00464 if (!key.dptr) return Qnil;
00465 val = dbm_fetch(dbm, key);
00466 keystr = rb_tainted_str_new(key.dptr, key.dsize);
00467 valstr = rb_tainted_str_new(val.dptr, val.dsize);
00468 dbm_delete(dbm, key);
00469
00470 return rb_assoc_new(keystr, valstr);
00471 }
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481 static VALUE
00482 fdbm_delete_if(VALUE obj)
00483 {
00484 datum key, val;
00485 struct dbmdata *dbmp;
00486 DBM *dbm;
00487 VALUE keystr, valstr;
00488 VALUE ret, ary = rb_ary_tmp_new(0);
00489 int i, status = 0;
00490 long n;
00491
00492 fdbm_modify(obj);
00493 GetDBM2(obj, dbmp, dbm);
00494 n = dbmp->di_size;
00495 dbmp->di_size = -1;
00496
00497 for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
00498 val = dbm_fetch(dbm, key);
00499 keystr = rb_tainted_str_new(key.dptr, key.dsize);
00500 OBJ_FREEZE(keystr);
00501 valstr = rb_tainted_str_new(val.dptr, val.dsize);
00502 ret = rb_protect(rb_yield, rb_assoc_new(rb_str_dup(keystr), valstr), &status);
00503 if (status != 0) break;
00504 if (RTEST(ret)) rb_ary_push(ary, keystr);
00505 GetDBM2(obj, dbmp, dbm);
00506 }
00507
00508 for (i = 0; i < RARRAY_LEN(ary); i++) {
00509 keystr = RARRAY_PTR(ary)[i];
00510 key.dptr = RSTRING_PTR(keystr);
00511 key.dsize = (DSIZE_TYPE)RSTRING_LEN(keystr);
00512 if (dbm_delete(dbm, key)) {
00513 rb_raise(rb_eDBMError, "dbm_delete failed");
00514 }
00515 }
00516 if (status) rb_jump_tag(status);
00517 if (n > 0) dbmp->di_size = n - RARRAY_LEN(ary);
00518 rb_ary_clear(ary);
00519
00520 return obj;
00521 }
00522
00523
00524
00525
00526
00527
00528
00529 static VALUE
00530 fdbm_clear(VALUE obj)
00531 {
00532 datum key;
00533 struct dbmdata *dbmp;
00534 DBM *dbm;
00535
00536 fdbm_modify(obj);
00537 GetDBM2(obj, dbmp, dbm);
00538 dbmp->di_size = -1;
00539 while (key = dbm_firstkey(dbm), key.dptr) {
00540 if (dbm_delete(dbm, key)) {
00541 rb_raise(rb_eDBMError, "dbm_delete failed");
00542 }
00543 }
00544 dbmp->di_size = 0;
00545
00546 return obj;
00547 }
00548
00549
00550
00551
00552
00553
00554
00555
00556 static VALUE
00557 fdbm_invert(VALUE obj)
00558 {
00559 datum key, val;
00560 struct dbmdata *dbmp;
00561 DBM *dbm;
00562 VALUE keystr, valstr;
00563 VALUE hash = rb_hash_new();
00564
00565 GetDBM2(obj, dbmp, dbm);
00566 for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
00567 val = dbm_fetch(dbm, key);
00568 keystr = rb_tainted_str_new(key.dptr, key.dsize);
00569 valstr = rb_tainted_str_new(val.dptr, val.dsize);
00570 rb_hash_aset(hash, valstr, keystr);
00571 }
00572 return hash;
00573 }
00574
00575 static VALUE fdbm_store(VALUE,VALUE,VALUE);
00576
00577 static VALUE
00578 update_i(VALUE pair, VALUE dbm)
00579 {
00580 Check_Type(pair, T_ARRAY);
00581 if (RARRAY_LEN(pair) < 2) {
00582 rb_raise(rb_eArgError, "pair must be [key, value]");
00583 }
00584 fdbm_store(dbm, RARRAY_PTR(pair)[0], RARRAY_PTR(pair)[1]);
00585 return Qnil;
00586 }
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596 static VALUE
00597 fdbm_update(VALUE obj, VALUE other)
00598 {
00599 rb_block_call(other, rb_intern("each_pair"), 0, 0, update_i, obj);
00600 return obj;
00601 }
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611 static VALUE
00612 fdbm_replace(VALUE obj, VALUE other)
00613 {
00614 fdbm_clear(obj);
00615 rb_block_call(other, rb_intern("each_pair"), 0, 0, update_i, obj);
00616 return obj;
00617 }
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627 static VALUE
00628 fdbm_store(VALUE obj, VALUE keystr, VALUE valstr)
00629 {
00630 datum key, val;
00631 struct dbmdata *dbmp;
00632 DBM *dbm;
00633
00634 fdbm_modify(obj);
00635 keystr = rb_obj_as_string(keystr);
00636 valstr = rb_obj_as_string(valstr);
00637
00638 key.dptr = RSTRING_PTR(keystr);
00639 key.dsize = RSTRING_DSIZE(keystr);
00640
00641 val.dptr = RSTRING_PTR(valstr);
00642 val.dsize = RSTRING_DSIZE(valstr);
00643
00644 GetDBM2(obj, dbmp, dbm);
00645 dbmp->di_size = -1;
00646 if (dbm_store(dbm, key, val, DBM_REPLACE)) {
00647 dbm_clearerr(dbm);
00648 if (errno == EPERM) rb_sys_fail(0);
00649 rb_raise(rb_eDBMError, "dbm_store failed");
00650 }
00651
00652 return valstr;
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 static VALUE
00840 fdbm_has_key(VALUE obj, VALUE keystr)
00841 {
00842 datum key, val;
00843 struct dbmdata *dbmp;
00844 DBM *dbm;
00845 long len;
00846
00847 ExportStringValue(keystr);
00848 len = RSTRING_LEN(keystr);
00849 if (TOO_LONG(len)) return Qfalse;
00850 key.dptr = RSTRING_PTR(keystr);
00851 key.dsize = (DSIZE_TYPE)len;
00852
00853 GetDBM2(obj, dbmp, dbm);
00854 val = dbm_fetch(dbm, key);
00855 if (val.dptr) return Qtrue;
00856 return Qfalse;
00857 }
00858
00859
00860
00861
00862
00863
00864
00865
00866 static VALUE
00867 fdbm_has_value(VALUE obj, VALUE valstr)
00868 {
00869 datum key, val;
00870 struct dbmdata *dbmp;
00871 DBM *dbm;
00872 long len;
00873
00874 ExportStringValue(valstr);
00875 len = RSTRING_LEN(valstr);
00876 if (TOO_LONG(len)) return Qfalse;
00877 val.dptr = RSTRING_PTR(valstr);
00878 val.dsize = (DSIZE_TYPE)len;
00879
00880 GetDBM2(obj, dbmp, dbm);
00881 for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
00882 val = dbm_fetch(dbm, key);
00883 if ((DSIZE_TYPE)val.dsize == (DSIZE_TYPE)RSTRING_LEN(valstr) &&
00884 memcmp(val.dptr, RSTRING_PTR(valstr), val.dsize) == 0)
00885 return Qtrue;
00886 }
00887 return Qfalse;
00888 }
00889
00890
00891
00892
00893
00894
00895
00896
00897 static VALUE
00898 fdbm_to_a(VALUE obj)
00899 {
00900 datum key, val;
00901 struct dbmdata *dbmp;
00902 DBM *dbm;
00903 VALUE ary;
00904
00905 GetDBM2(obj, dbmp, dbm);
00906 ary = rb_ary_new();
00907 for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
00908 val = dbm_fetch(dbm, key);
00909 rb_ary_push(ary, rb_assoc_new(rb_tainted_str_new(key.dptr, key.dsize),
00910 rb_tainted_str_new(val.dptr, val.dsize)));
00911 }
00912
00913 return ary;
00914 }
00915
00916
00917
00918
00919
00920
00921
00922
00923 static VALUE
00924 fdbm_to_hash(VALUE obj)
00925 {
00926 datum key, val;
00927 struct dbmdata *dbmp;
00928 DBM *dbm;
00929 VALUE hash;
00930
00931 GetDBM2(obj, dbmp, dbm);
00932 hash = rb_hash_new();
00933 for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
00934 val = dbm_fetch(dbm, key);
00935 rb_hash_aset(hash, rb_tainted_str_new(key.dptr, key.dsize),
00936 rb_tainted_str_new(val.dptr, val.dsize));
00937 }
00938
00939 return hash;
00940 }
00941
00942
00943
00944
00945
00946
00947
00948
00949 static VALUE
00950 fdbm_reject(VALUE obj)
00951 {
00952 return rb_hash_delete_if(fdbm_to_hash(obj));
00953 }
00954
00955
00956
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 void
01018 Init_dbm(void)
01019 {
01020 rb_cDBM = rb_define_class("DBM", rb_cObject);
01021
01022
01023
01024 rb_eDBMError = rb_define_class("DBMError", rb_eStandardError);
01025 rb_include_module(rb_cDBM, rb_mEnumerable);
01026
01027 rb_define_alloc_func(rb_cDBM, fdbm_alloc);
01028 rb_define_singleton_method(rb_cDBM, "open", fdbm_s_open, -1);
01029
01030 rb_define_method(rb_cDBM, "initialize", fdbm_initialize, -1);
01031 rb_define_method(rb_cDBM, "close", fdbm_close, 0);
01032 rb_define_method(rb_cDBM, "closed?", fdbm_closed, 0);
01033 rb_define_method(rb_cDBM, "[]", fdbm_aref, 1);
01034 rb_define_method(rb_cDBM, "fetch", fdbm_fetch_m, -1);
01035 rb_define_method(rb_cDBM, "[]=", fdbm_store, 2);
01036 rb_define_method(rb_cDBM, "store", fdbm_store, 2);
01037 rb_define_method(rb_cDBM, "index", fdbm_index, 1);
01038 rb_define_method(rb_cDBM, "key", fdbm_key, 1);
01039 rb_define_method(rb_cDBM, "select", fdbm_select, 0);
01040 rb_define_method(rb_cDBM, "values_at", fdbm_values_at, -1);
01041 rb_define_method(rb_cDBM, "length", fdbm_length, 0);
01042 rb_define_method(rb_cDBM, "size", fdbm_length, 0);
01043 rb_define_method(rb_cDBM, "empty?", fdbm_empty_p, 0);
01044 rb_define_method(rb_cDBM, "each", fdbm_each_pair, 0);
01045 rb_define_method(rb_cDBM, "each_value", fdbm_each_value, 0);
01046 rb_define_method(rb_cDBM, "each_key", fdbm_each_key, 0);
01047 rb_define_method(rb_cDBM, "each_pair", fdbm_each_pair, 0);
01048 rb_define_method(rb_cDBM, "keys", fdbm_keys, 0);
01049 rb_define_method(rb_cDBM, "values", fdbm_values, 0);
01050 rb_define_method(rb_cDBM, "shift", fdbm_shift, 0);
01051 rb_define_method(rb_cDBM, "delete", fdbm_delete, 1);
01052 rb_define_method(rb_cDBM, "delete_if", fdbm_delete_if, 0);
01053 rb_define_method(rb_cDBM, "reject!", fdbm_delete_if, 0);
01054 rb_define_method(rb_cDBM, "reject", fdbm_reject, 0);
01055 rb_define_method(rb_cDBM, "clear", fdbm_clear, 0);
01056 rb_define_method(rb_cDBM, "invert", fdbm_invert, 0);
01057 rb_define_method(rb_cDBM, "update", fdbm_update, 1);
01058 rb_define_method(rb_cDBM, "replace", fdbm_replace, 1);
01059
01060 rb_define_method(rb_cDBM, "include?", fdbm_has_key, 1);
01061 rb_define_method(rb_cDBM, "has_key?", fdbm_has_key, 1);
01062 rb_define_method(rb_cDBM, "member?", fdbm_has_key, 1);
01063 rb_define_method(rb_cDBM, "has_value?", fdbm_has_value, 1);
01064 rb_define_method(rb_cDBM, "key?", fdbm_has_key, 1);
01065 rb_define_method(rb_cDBM, "value?", fdbm_has_value, 1);
01066
01067 rb_define_method(rb_cDBM, "to_a", fdbm_to_a, 0);
01068 rb_define_method(rb_cDBM, "to_hash", fdbm_to_hash, 0);
01069
01070
01071 rb_define_const(rb_cDBM, "READER", INT2FIX(O_RDONLY|RUBY_DBM_RW_BIT));
01072
01073
01074 rb_define_const(rb_cDBM, "WRITER", INT2FIX(O_RDWR|RUBY_DBM_RW_BIT));
01075
01076
01077
01078
01079 rb_define_const(rb_cDBM, "WRCREAT", INT2FIX(O_RDWR|O_CREAT|RUBY_DBM_RW_BIT));
01080
01081
01082
01083
01084
01085 rb_define_const(rb_cDBM, "NEWDB", INT2FIX(O_RDWR|O_CREAT|O_TRUNC|RUBY_DBM_RW_BIT));
01086
01087 {
01088 VALUE version;
01089 #if defined(_DBM_IOERR)
01090 version = rb_str_new2("ndbm (4.3BSD)");
01091 #elif defined(RUBYDBM_GDBM_HEADER)
01092 # if defined(HAVE_DECLARED_LIBVAR_GDBM_VERSION)
01093
01094 version = rb_str_new2(gdbm_version);
01095 # elif defined(HAVE_UNDECLARED_LIBVAR_GDBM_VERSION)
01096
01097
01098 RUBY_EXTERN char *gdbm_version;
01099 version = rb_str_new2(gdbm_version);
01100 # else
01101 version = rb_str_new2("GDBM (unknown)");
01102 # endif
01103 #elif defined(RUBYDBM_DB_HEADER)
01104 # if defined(HAVE_DB_VERSION)
01105
01106 version = rb_str_new2(db_version(NULL, NULL, NULL));
01107 # else
01108 version = rb_str_new2("Berkeley DB (unknown)");
01109 # endif
01110 #elif defined(_RELIC_H)
01111 # if defined(HAVE_DPVERSION)
01112 version = rb_sprintf("QDBM %s", dpversion);
01113 # else
01114 version = rb_str_new2("QDBM (unknown)");
01115 # endif
01116 #else
01117 version = rb_str_new2("ndbm (unknown)");
01118 #endif
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131 rb_define_const(rb_cDBM, "VERSION", version);
01132 }
01133 }
01134