Ruby 1.9.3p327(2012-11-10revision37606)
|
00001 /************************************************ 00002 00003 dbm.c - 00004 00005 $Author: naruse $ 00006 created at: Mon Jan 24 15:59:52 JST 1994 00007 00008 Copyright (C) 1995-2001 Yukihiro Matsumoto 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 static VALUE rb_cDBM, rb_eDBMError; 00025 00026 #define RUBY_DBM_RW_BIT 0x20000000 00027 00028 struct dbmdata { 00029 long di_size; 00030 DBM *di_dbm; 00031 }; 00032 00033 static void 00034 closed_dbm(void) 00035 { 00036 rb_raise(rb_eDBMError, "closed DBM file"); 00037 } 00038 00039 #define GetDBM(obj, dbmp) {\ 00040 Data_Get_Struct((obj), struct dbmdata, (dbmp));\ 00041 if ((dbmp) == 0) closed_dbm();\ 00042 if ((dbmp)->di_dbm == 0) closed_dbm();\ 00043 } 00044 00045 #define GetDBM2(obj, data, dbm) {\ 00046 GetDBM((obj), (data));\ 00047 (dbm) = dbmp->di_dbm;\ 00048 } 00049 00050 static void 00051 free_dbm(struct dbmdata *dbmp) 00052 { 00053 if (dbmp) { 00054 if (dbmp->di_dbm) dbm_close(dbmp->di_dbm); 00055 xfree(dbmp); 00056 } 00057 } 00058 00059 /* 00060 * call-seq: 00061 * dbm.close 00062 * 00063 * Closes the database. 00064 */ 00065 static VALUE 00066 fdbm_close(VALUE obj) 00067 { 00068 struct dbmdata *dbmp; 00069 00070 GetDBM(obj, dbmp); 00071 dbm_close(dbmp->di_dbm); 00072 dbmp->di_dbm = 0; 00073 00074 return Qnil; 00075 } 00076 00077 /* 00078 * call-seq: 00079 * dbm.closed? -> true or false 00080 * 00081 * Returns true if the database is closed, false otherwise. 00082 */ 00083 static VALUE 00084 fdbm_closed(VALUE obj) 00085 { 00086 struct dbmdata *dbmp; 00087 00088 Data_Get_Struct(obj, struct dbmdata, dbmp); 00089 if (dbmp == 0) 00090 return Qtrue; 00091 if (dbmp->di_dbm == 0) 00092 return Qtrue; 00093 00094 return Qfalse; 00095 } 00096 00097 static VALUE 00098 fdbm_alloc(VALUE klass) 00099 { 00100 return Data_Wrap_Struct(klass, 0, free_dbm, 0); 00101 } 00102 00103 /* 00104 * call-seq: 00105 * DBM.new(filename[, mode[, flags]]) -> dbm 00106 * 00107 * Open a dbm database with the specified name, which can include a directory 00108 * path. Any file extensions needed will be supplied automatically by the dbm 00109 * library. For example, Berkeley DB appends '.db', and GNU gdbm uses two 00110 * physical files with extensions '.dir' and '.pag'. 00111 * 00112 * The mode should be an integer, as for Unix chmod. 00113 * 00114 * Flags should be one of READER, WRITER, WRCREAT or NEWDB. 00115 */ 00116 static VALUE 00117 fdbm_initialize(int argc, VALUE *argv, VALUE obj) 00118 { 00119 volatile VALUE file; 00120 VALUE vmode, vflags; 00121 DBM *dbm; 00122 struct dbmdata *dbmp; 00123 int mode, flags = 0; 00124 00125 if (rb_scan_args(argc, argv, "12", &file, &vmode, &vflags) == 1) { 00126 mode = 0666; /* default value */ 00127 } 00128 else if (NIL_P(vmode)) { 00129 mode = -1; /* return nil if DB not exist */ 00130 } 00131 else { 00132 mode = NUM2INT(vmode); 00133 } 00134 00135 if (!NIL_P(vflags)) 00136 flags = NUM2INT(vflags); 00137 00138 FilePathValue(file); 00139 00140 if (flags & RUBY_DBM_RW_BIT) { 00141 flags &= ~RUBY_DBM_RW_BIT; 00142 dbm = dbm_open(RSTRING_PTR(file), flags, mode); 00143 } 00144 else { 00145 dbm = 0; 00146 if (mode >= 0) { 00147 dbm = dbm_open(RSTRING_PTR(file), O_RDWR|O_CREAT, mode); 00148 } 00149 if (!dbm) { 00150 dbm = dbm_open(RSTRING_PTR(file), O_RDWR, 0); 00151 } 00152 if (!dbm) { 00153 dbm = dbm_open(RSTRING_PTR(file), O_RDONLY, 0); 00154 } 00155 } 00156 00157 if (!dbm) { 00158 if (mode == -1) return Qnil; 00159 rb_sys_fail(RSTRING_PTR(file)); 00160 } 00161 00162 dbmp = ALLOC(struct dbmdata); 00163 DATA_PTR(obj) = dbmp; 00164 dbmp->di_dbm = dbm; 00165 dbmp->di_size = -1; 00166 00167 return obj; 00168 } 00169 00170 /* 00171 * call-seq: 00172 * DBM.open(filename[, mode[, flags]]) -> dbm 00173 * DBM.open(filename[, mode[, flags]]) {|dbm| block} 00174 * 00175 * Open a dbm database and yields it if a block is given. See also 00176 * <code>DBM.new</code>. 00177 */ 00178 static VALUE 00179 fdbm_s_open(int argc, VALUE *argv, VALUE klass) 00180 { 00181 VALUE obj = Data_Wrap_Struct(klass, 0, free_dbm, 0); 00182 00183 if (NIL_P(fdbm_initialize(argc, argv, obj))) { 00184 return Qnil; 00185 } 00186 00187 if (rb_block_given_p()) { 00188 return rb_ensure(rb_yield, obj, fdbm_close, obj); 00189 } 00190 00191 return obj; 00192 } 00193 00194 static VALUE 00195 fdbm_fetch(VALUE obj, VALUE keystr, VALUE ifnone) 00196 { 00197 datum key, value; 00198 struct dbmdata *dbmp; 00199 DBM *dbm; 00200 00201 ExportStringValue(keystr); 00202 key.dptr = RSTRING_PTR(keystr); 00203 key.dsize = (int)RSTRING_LEN(keystr); 00204 00205 GetDBM2(obj, dbmp, dbm); 00206 value = dbm_fetch(dbm, key); 00207 if (value.dptr == 0) { 00208 if (ifnone == Qnil && rb_block_given_p()) 00209 return rb_yield(rb_tainted_str_new(key.dptr, key.dsize)); 00210 return ifnone; 00211 } 00212 return rb_tainted_str_new(value.dptr, value.dsize); 00213 } 00214 00215 /* 00216 * call-seq: 00217 * dbm[key] -> string value or nil 00218 * 00219 * Return a value from the database by locating the key string 00220 * provided. If the key is not found, returns nil. 00221 */ 00222 static VALUE 00223 fdbm_aref(VALUE obj, VALUE keystr) 00224 { 00225 return fdbm_fetch(obj, keystr, Qnil); 00226 } 00227 00228 /* 00229 * call-seq: 00230 * dbm.fetch(key[, ifnone]) -> value 00231 * 00232 * Return a value from the database by locating the key string 00233 * provided. If the key is not found, returns +ifnone+. If +ifnone+ 00234 * is not given, raises IndexError. 00235 */ 00236 static VALUE 00237 fdbm_fetch_m(int argc, VALUE *argv, VALUE obj) 00238 { 00239 VALUE keystr, valstr, ifnone; 00240 00241 rb_scan_args(argc, argv, "11", &keystr, &ifnone); 00242 valstr = fdbm_fetch(obj, keystr, ifnone); 00243 if (argc == 1 && !rb_block_given_p() && NIL_P(valstr)) 00244 rb_raise(rb_eIndexError, "key not found"); 00245 00246 return valstr; 00247 } 00248 00249 /* 00250 * call-seq: 00251 * dbm.key(value) -> string 00252 * 00253 * Returns the key for the specified value. 00254 */ 00255 static VALUE 00256 fdbm_key(VALUE obj, VALUE valstr) 00257 { 00258 datum key, val; 00259 struct dbmdata *dbmp; 00260 DBM *dbm; 00261 00262 ExportStringValue(valstr); 00263 val.dptr = RSTRING_PTR(valstr); 00264 val.dsize = (int)RSTRING_LEN(valstr); 00265 00266 GetDBM2(obj, dbmp, dbm); 00267 for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { 00268 val = dbm_fetch(dbm, key); 00269 if ((long)val.dsize == (int)RSTRING_LEN(valstr) && 00270 memcmp(val.dptr, RSTRING_PTR(valstr), val.dsize) == 0) { 00271 return rb_tainted_str_new(key.dptr, key.dsize); 00272 } 00273 } 00274 return Qnil; 00275 } 00276 00277 /* :nodoc: */ 00278 static VALUE 00279 fdbm_index(VALUE hash, VALUE value) 00280 { 00281 rb_warn("DBM#index is deprecated; use DBM#key"); 00282 return fdbm_key(hash, value); 00283 } 00284 00285 /* 00286 * call-seq: 00287 * dbm.select {|key, value| block} -> array 00288 * 00289 * Returns a new array consisting of the [key, value] pairs for which the code 00290 * block returns true. 00291 */ 00292 static VALUE 00293 fdbm_select(VALUE obj) 00294 { 00295 VALUE new = rb_ary_new(); 00296 datum key, val; 00297 DBM *dbm; 00298 struct dbmdata *dbmp; 00299 00300 GetDBM2(obj, dbmp, dbm); 00301 for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { 00302 VALUE assoc, v; 00303 val = dbm_fetch(dbm, key); 00304 assoc = rb_assoc_new(rb_tainted_str_new(key.dptr, key.dsize), 00305 rb_tainted_str_new(val.dptr, val.dsize)); 00306 v = rb_yield(assoc); 00307 if (RTEST(v)) { 00308 rb_ary_push(new, assoc); 00309 } 00310 GetDBM2(obj, dbmp, dbm); 00311 } 00312 00313 return new; 00314 } 00315 00316 /* 00317 * call-seq: 00318 * dbm.values_at(key, ...) -> Array 00319 * 00320 * Returns an array containing the values associated with the given keys. 00321 */ 00322 static VALUE 00323 fdbm_values_at(int argc, VALUE *argv, VALUE obj) 00324 { 00325 VALUE new = rb_ary_new2(argc); 00326 int i; 00327 00328 for (i=0; i<argc; i++) { 00329 rb_ary_push(new, fdbm_fetch(obj, argv[i], Qnil)); 00330 } 00331 00332 return new; 00333 } 00334 00335 static void 00336 fdbm_modify(VALUE obj) 00337 { 00338 rb_secure(4); 00339 if (OBJ_FROZEN(obj)) rb_error_frozen("DBM"); 00340 } 00341 00342 /* 00343 * call-seq: 00344 * dbm.delete(key) 00345 * 00346 * Deletes an entry from the database. 00347 */ 00348 static VALUE 00349 fdbm_delete(VALUE obj, VALUE keystr) 00350 { 00351 datum key, value; 00352 struct dbmdata *dbmp; 00353 DBM *dbm; 00354 VALUE valstr; 00355 00356 fdbm_modify(obj); 00357 ExportStringValue(keystr); 00358 key.dptr = RSTRING_PTR(keystr); 00359 key.dsize = (int)RSTRING_LEN(keystr); 00360 00361 GetDBM2(obj, dbmp, dbm); 00362 00363 value = dbm_fetch(dbm, key); 00364 if (value.dptr == 0) { 00365 if (rb_block_given_p()) return rb_yield(keystr); 00366 return Qnil; 00367 } 00368 00369 /* need to save value before dbm_delete() */ 00370 valstr = rb_tainted_str_new(value.dptr, value.dsize); 00371 00372 if (dbm_delete(dbm, key)) { 00373 dbmp->di_size = -1; 00374 rb_raise(rb_eDBMError, "dbm_delete failed"); 00375 } 00376 else if (dbmp->di_size >= 0) { 00377 dbmp->di_size--; 00378 } 00379 return valstr; 00380 } 00381 00382 /* 00383 * call-seq: 00384 * dbm.shift() -> [key, value] 00385 * 00386 * Removes a [key, value] pair from the database, and returns it. 00387 * If the database is empty, returns nil. 00388 * The order in which values are removed/returned is not guaranteed. 00389 */ 00390 static VALUE 00391 fdbm_shift(VALUE obj) 00392 { 00393 datum key, val; 00394 struct dbmdata *dbmp; 00395 DBM *dbm; 00396 VALUE keystr, valstr; 00397 00398 fdbm_modify(obj); 00399 GetDBM2(obj, dbmp, dbm); 00400 dbmp->di_size = -1; 00401 00402 key = dbm_firstkey(dbm); 00403 if (!key.dptr) return Qnil; 00404 val = dbm_fetch(dbm, key); 00405 keystr = rb_tainted_str_new(key.dptr, key.dsize); 00406 valstr = rb_tainted_str_new(val.dptr, val.dsize); 00407 dbm_delete(dbm, key); 00408 00409 return rb_assoc_new(keystr, valstr); 00410 } 00411 00412 /* 00413 * call-seq: 00414 * dbm.reject! {|key, value| block} -> self 00415 * dbm.delete_if {|key, value| block} -> self 00416 * 00417 * Deletes all entries for which the code block returns true. 00418 * Returns self. 00419 */ 00420 static VALUE 00421 fdbm_delete_if(VALUE obj) 00422 { 00423 datum key, val; 00424 struct dbmdata *dbmp; 00425 DBM *dbm; 00426 VALUE keystr, valstr; 00427 VALUE ret, ary = rb_ary_new(); 00428 int i, status = 0; 00429 long n; 00430 00431 fdbm_modify(obj); 00432 GetDBM2(obj, dbmp, dbm); 00433 n = dbmp->di_size; 00434 dbmp->di_size = -1; 00435 00436 for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { 00437 val = dbm_fetch(dbm, key); 00438 keystr = rb_tainted_str_new(key.dptr, key.dsize); 00439 valstr = rb_tainted_str_new(val.dptr, val.dsize); 00440 ret = rb_protect(rb_yield, rb_assoc_new(rb_str_dup(keystr), valstr), &status); 00441 if (status != 0) break; 00442 if (RTEST(ret)) rb_ary_push(ary, keystr); 00443 GetDBM2(obj, dbmp, dbm); 00444 } 00445 00446 for (i = 0; i < RARRAY_LEN(ary); i++) { 00447 keystr = RARRAY_PTR(ary)[i]; 00448 ExportStringValue(keystr); 00449 key.dptr = RSTRING_PTR(keystr); 00450 key.dsize = (int)RSTRING_LEN(keystr); 00451 if (dbm_delete(dbm, key)) { 00452 rb_raise(rb_eDBMError, "dbm_delete failed"); 00453 } 00454 } 00455 if (status) rb_jump_tag(status); 00456 if (n > 0) dbmp->di_size = n - RARRAY_LEN(ary); 00457 00458 return obj; 00459 } 00460 00461 /* 00462 * call-seq: 00463 * dbm.clear 00464 * 00465 * Deletes all data from the database. 00466 */ 00467 static VALUE 00468 fdbm_clear(VALUE obj) 00469 { 00470 datum key; 00471 struct dbmdata *dbmp; 00472 DBM *dbm; 00473 00474 fdbm_modify(obj); 00475 GetDBM2(obj, dbmp, dbm); 00476 dbmp->di_size = -1; 00477 while (key = dbm_firstkey(dbm), key.dptr) { 00478 if (dbm_delete(dbm, key)) { 00479 rb_raise(rb_eDBMError, "dbm_delete failed"); 00480 } 00481 } 00482 dbmp->di_size = 0; 00483 00484 return obj; 00485 } 00486 00487 /* 00488 * call-seq: 00489 * dbm.invert -> hash 00490 * 00491 * Returns a Hash (not a DBM database) created by using each value in the 00492 * database as a key, with the corresponding key as its value. 00493 */ 00494 static VALUE 00495 fdbm_invert(VALUE obj) 00496 { 00497 datum key, val; 00498 struct dbmdata *dbmp; 00499 DBM *dbm; 00500 VALUE keystr, valstr; 00501 VALUE hash = rb_hash_new(); 00502 00503 GetDBM2(obj, dbmp, dbm); 00504 for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { 00505 val = dbm_fetch(dbm, key); 00506 keystr = rb_tainted_str_new(key.dptr, key.dsize); 00507 valstr = rb_tainted_str_new(val.dptr, val.dsize); 00508 rb_hash_aset(hash, valstr, keystr); 00509 } 00510 return hash; 00511 } 00512 00513 static VALUE fdbm_store(VALUE,VALUE,VALUE); 00514 00515 static VALUE 00516 update_i(VALUE pair, VALUE dbm) 00517 { 00518 Check_Type(pair, T_ARRAY); 00519 if (RARRAY_LEN(pair) < 2) { 00520 rb_raise(rb_eArgError, "pair must be [key, value]"); 00521 } 00522 fdbm_store(dbm, RARRAY_PTR(pair)[0], RARRAY_PTR(pair)[1]); 00523 return Qnil; 00524 } 00525 00526 /* 00527 * call-seq: 00528 * dbm.update(obj) 00529 * 00530 * Updates the database with multiple values from the specified object. 00531 * Takes any object which implements the each_pair method, including 00532 * Hash and DBM objects. 00533 */ 00534 static VALUE 00535 fdbm_update(VALUE obj, VALUE other) 00536 { 00537 rb_block_call(other, rb_intern("each_pair"), 0, 0, update_i, obj); 00538 return obj; 00539 } 00540 00541 /* 00542 * call-seq: 00543 * dbm.replace(obj) 00544 * 00545 * Replaces the contents of the database with the contents of the specified 00546 * object. Takes any object which implements the each_pair method, including 00547 * Hash and DBM objects. 00548 */ 00549 static VALUE 00550 fdbm_replace(VALUE obj, VALUE other) 00551 { 00552 fdbm_clear(obj); 00553 rb_block_call(other, rb_intern("each_pair"), 0, 0, update_i, obj); 00554 return obj; 00555 } 00556 00557 /* 00558 * call-seq: 00559 * dbm.store(key, value) -> value 00560 * dbm[key] = value 00561 * 00562 * Stores the specified string value in the database, indexed via the 00563 * string key provided. 00564 */ 00565 static VALUE 00566 fdbm_store(VALUE obj, VALUE keystr, VALUE valstr) 00567 { 00568 datum key, val; 00569 struct dbmdata *dbmp; 00570 DBM *dbm; 00571 00572 fdbm_modify(obj); 00573 keystr = rb_obj_as_string(keystr); 00574 valstr = rb_obj_as_string(valstr); 00575 00576 key.dptr = RSTRING_PTR(keystr); 00577 key.dsize = (int)RSTRING_LEN(keystr); 00578 00579 val.dptr = RSTRING_PTR(valstr); 00580 val.dsize = (int)RSTRING_LEN(valstr); 00581 00582 GetDBM2(obj, dbmp, dbm); 00583 dbmp->di_size = -1; 00584 if (dbm_store(dbm, key, val, DBM_REPLACE)) { 00585 #ifdef HAVE_DBM_CLEARERR 00586 dbm_clearerr(dbm); 00587 #endif 00588 if (errno == EPERM) rb_sys_fail(0); 00589 rb_raise(rb_eDBMError, "dbm_store failed"); 00590 } 00591 00592 return valstr; 00593 } 00594 00595 /* 00596 * call-seq: 00597 * dbm.length -> integer 00598 * 00599 * Returns the number of entries in the database. 00600 */ 00601 static VALUE 00602 fdbm_length(VALUE obj) 00603 { 00604 datum key; 00605 struct dbmdata *dbmp; 00606 DBM *dbm; 00607 int i = 0; 00608 00609 GetDBM2(obj, dbmp, dbm); 00610 if (dbmp->di_size > 0) return INT2FIX(dbmp->di_size); 00611 00612 for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { 00613 i++; 00614 } 00615 dbmp->di_size = i; 00616 00617 return INT2FIX(i); 00618 } 00619 00620 /* 00621 * call-seq: 00622 * dbm.empty? 00623 * 00624 * Returns true if the database is empty, false otherwise. 00625 */ 00626 static VALUE 00627 fdbm_empty_p(VALUE obj) 00628 { 00629 datum key; 00630 struct dbmdata *dbmp; 00631 DBM *dbm; 00632 int i = 0; 00633 00634 GetDBM2(obj, dbmp, dbm); 00635 if (dbmp->di_size < 0) { 00636 dbm = dbmp->di_dbm; 00637 00638 for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { 00639 i++; 00640 } 00641 } 00642 else { 00643 i = (int)dbmp->di_size; 00644 } 00645 if (i == 0) return Qtrue; 00646 return Qfalse; 00647 } 00648 00649 /* 00650 * call-seq: 00651 * dbm.each_value {|value| block} -> self 00652 * 00653 * Calls the block once for each value string in the database. Returns self. 00654 */ 00655 static VALUE 00656 fdbm_each_value(VALUE obj) 00657 { 00658 datum key, val; 00659 struct dbmdata *dbmp; 00660 DBM *dbm; 00661 00662 RETURN_ENUMERATOR(obj, 0, 0); 00663 00664 GetDBM2(obj, dbmp, dbm); 00665 for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { 00666 val = dbm_fetch(dbm, key); 00667 rb_yield(rb_tainted_str_new(val.dptr, val.dsize)); 00668 GetDBM2(obj, dbmp, dbm); 00669 } 00670 return obj; 00671 } 00672 00673 /* 00674 * call-seq: 00675 * dbm.each_key {|key| block} -> self 00676 * 00677 * Calls the block once for each key string in the database. Returns self. 00678 */ 00679 static VALUE 00680 fdbm_each_key(VALUE obj) 00681 { 00682 datum key; 00683 struct dbmdata *dbmp; 00684 DBM *dbm; 00685 00686 RETURN_ENUMERATOR(obj, 0, 0); 00687 00688 GetDBM2(obj, dbmp, dbm); 00689 for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { 00690 rb_yield(rb_tainted_str_new(key.dptr, key.dsize)); 00691 GetDBM2(obj, dbmp, dbm); 00692 } 00693 return obj; 00694 } 00695 00696 /* 00697 * call-seq: 00698 * dbm.each_pair {|key,value| block} -> self 00699 * 00700 * Calls the block once for each [key, value] pair in the database. 00701 * Returns self. 00702 */ 00703 static VALUE 00704 fdbm_each_pair(VALUE obj) 00705 { 00706 datum key, val; 00707 DBM *dbm; 00708 struct dbmdata *dbmp; 00709 VALUE keystr, valstr; 00710 00711 RETURN_ENUMERATOR(obj, 0, 0); 00712 00713 GetDBM2(obj, dbmp, dbm); 00714 00715 for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { 00716 val = dbm_fetch(dbm, key); 00717 keystr = rb_tainted_str_new(key.dptr, key.dsize); 00718 valstr = rb_tainted_str_new(val.dptr, val.dsize); 00719 rb_yield(rb_assoc_new(keystr, valstr)); 00720 GetDBM2(obj, dbmp, dbm); 00721 } 00722 00723 return obj; 00724 } 00725 00726 /* 00727 * call-seq: 00728 * dbm.keys -> array 00729 * 00730 * Returns an array of all the string keys in the database. 00731 */ 00732 static VALUE 00733 fdbm_keys(VALUE obj) 00734 { 00735 datum key; 00736 struct dbmdata *dbmp; 00737 DBM *dbm; 00738 VALUE ary; 00739 00740 GetDBM2(obj, dbmp, dbm); 00741 00742 ary = rb_ary_new(); 00743 for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { 00744 rb_ary_push(ary, rb_tainted_str_new(key.dptr, key.dsize)); 00745 } 00746 00747 return ary; 00748 } 00749 00750 /* 00751 * call-seq: 00752 * dbm.values -> array 00753 * 00754 * Returns an array of all the string values in the database. 00755 */ 00756 static VALUE 00757 fdbm_values(VALUE obj) 00758 { 00759 datum key, val; 00760 struct dbmdata *dbmp; 00761 DBM *dbm; 00762 VALUE ary; 00763 00764 GetDBM2(obj, dbmp, dbm); 00765 ary = rb_ary_new(); 00766 for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { 00767 val = dbm_fetch(dbm, key); 00768 rb_ary_push(ary, rb_tainted_str_new(val.dptr, val.dsize)); 00769 } 00770 00771 return ary; 00772 } 00773 00774 /* 00775 * call-seq: 00776 * dbm.has_key?(key) -> boolean 00777 * 00778 * Returns true if the database contains the specified key, false otherwise. 00779 */ 00780 static VALUE 00781 fdbm_has_key(VALUE obj, VALUE keystr) 00782 { 00783 datum key, val; 00784 struct dbmdata *dbmp; 00785 DBM *dbm; 00786 00787 ExportStringValue(keystr); 00788 key.dptr = RSTRING_PTR(keystr); 00789 key.dsize = (int)RSTRING_LEN(keystr); 00790 00791 GetDBM2(obj, dbmp, dbm); 00792 val = dbm_fetch(dbm, key); 00793 if (val.dptr) return Qtrue; 00794 return Qfalse; 00795 } 00796 00797 /* 00798 * call-seq: 00799 * dbm.has_value?(value) -> boolean 00800 * 00801 * Returns true if the database contains the specified string value, false 00802 * otherwise. 00803 */ 00804 static VALUE 00805 fdbm_has_value(VALUE obj, VALUE valstr) 00806 { 00807 datum key, val; 00808 struct dbmdata *dbmp; 00809 DBM *dbm; 00810 00811 ExportStringValue(valstr); 00812 val.dptr = RSTRING_PTR(valstr); 00813 val.dsize = (int)RSTRING_LEN(valstr); 00814 00815 GetDBM2(obj, dbmp, dbm); 00816 for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { 00817 val = dbm_fetch(dbm, key); 00818 if (val.dsize == (int)RSTRING_LEN(valstr) && 00819 memcmp(val.dptr, RSTRING_PTR(valstr), val.dsize) == 0) 00820 return Qtrue; 00821 } 00822 return Qfalse; 00823 } 00824 00825 /* 00826 * call-seq: 00827 * dbm.to_a -> array 00828 * 00829 * Converts the contents of the database to an array of [key, value] arrays, 00830 * and returns it. 00831 */ 00832 static VALUE 00833 fdbm_to_a(VALUE obj) 00834 { 00835 datum key, val; 00836 struct dbmdata *dbmp; 00837 DBM *dbm; 00838 VALUE ary; 00839 00840 GetDBM2(obj, dbmp, dbm); 00841 ary = rb_ary_new(); 00842 for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { 00843 val = dbm_fetch(dbm, key); 00844 rb_ary_push(ary, rb_assoc_new(rb_tainted_str_new(key.dptr, key.dsize), 00845 rb_tainted_str_new(val.dptr, val.dsize))); 00846 } 00847 00848 return ary; 00849 } 00850 00851 /* 00852 * call-seq: 00853 * dbm.to_hash -> hash 00854 * 00855 * Converts the contents of the database to an in-memory Hash object, and 00856 * returns it. 00857 */ 00858 static VALUE 00859 fdbm_to_hash(VALUE obj) 00860 { 00861 datum key, val; 00862 struct dbmdata *dbmp; 00863 DBM *dbm; 00864 VALUE hash; 00865 00866 GetDBM2(obj, dbmp, dbm); 00867 hash = rb_hash_new(); 00868 for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { 00869 val = dbm_fetch(dbm, key); 00870 rb_hash_aset(hash, rb_tainted_str_new(key.dptr, key.dsize), 00871 rb_tainted_str_new(val.dptr, val.dsize)); 00872 } 00873 00874 return hash; 00875 } 00876 00877 /* 00878 * call-seq: 00879 * dbm.reject {|key,value| block} -> Hash 00880 * 00881 * Converts the contents of the database to an in-memory Hash, then calls 00882 * Hash#reject with the specified code block, returning a new Hash. 00883 */ 00884 static VALUE 00885 fdbm_reject(VALUE obj) 00886 { 00887 return rb_hash_delete_if(fdbm_to_hash(obj)); 00888 } 00889 00890 /* 00891 * Documented by mathew meta@pobox.com. 00892 * = Introduction 00893 * 00894 * The DBM class provides a wrapper to a Unix-style 00895 * {dbm}[http://en.wikipedia.org/wiki/Dbm] or Database Manager library. 00896 * 00897 * Dbm databases do not have tables or columns; they are simple key-value 00898 * data stores, like a Ruby Hash except not resident in RAM. Keys and values 00899 * must be strings. 00900 * 00901 * The exact library used depends on how Ruby was compiled. It could be any 00902 * of the following: 00903 * 00904 * - The original ndbm library is released in 4.3BSD. 00905 * It is based on dbm library in Unix Version 7 but has different API to 00906 * support multiple databases in a process. 00907 * - {Berkeley DB}[http://en.wikipedia.org/wiki/Berkeley_DB] versions 00908 * 1 thru 5, also known as BDB and Sleepycat DB, now owned by Oracle 00909 * Corporation. 00910 * - Berkeley DB 1.x, still found in FreeBSD and OpenBSD. 00911 * - {gdbm}[http://www.gnu.org/software/gdbm/], the GNU implementation of dbm. 00912 * - {qdbm}[http://fallabs.com/qdbm/index.html], another open source 00913 * reimplementation of dbm. 00914 * 00915 * All of these dbm implementations have their own Ruby interfaces 00916 * available, which provide richer (but varying) APIs. 00917 * 00918 * = Cautions 00919 * 00920 * Before you decide to use DBM, there are some issues you should consider: 00921 * 00922 * - Each implementation of dbm has its own file format. Generally, dbm 00923 * libraries will not read each other's files. This makes dbm files 00924 * a bad choice for data exchange. 00925 * 00926 * - Even running the same OS and the same dbm implementation, the database 00927 * file format may depend on the CPU architecture. For example, files may 00928 * not be portable between PowerPC and 386, or between 32 and 64 bit Linux. 00929 * 00930 * - Different versions of Berkeley DB use different file formats. A change to 00931 * the OS may therefore break DBM access to existing files. 00932 * 00933 * - Data size limits vary between implementations. Original Berkeley DB was 00934 * limited to 2GB of data. Dbm libraries also sometimes limit the total 00935 * size of a key/value pair, and the total size of all the keys that hash 00936 * to the same value. These limits can be as little as 512 bytes. That said, 00937 * gdbm and recent versions of Berkeley DB do away with these limits. 00938 * 00939 * Given the above cautions, DBM is not a good choice for long term storage of 00940 * important data. It is probably best used as a fast and easy alternative 00941 * to a Hash for processing large amounts of data. 00942 * 00943 * = Example 00944 * 00945 * require 'dbm' 00946 * db = DBM.open('rfcs', 666, DBM::CREATRW) 00947 * db['822'] = 'Standard for the Format of ARPA Internet Text Messages' 00948 * db['1123'] = 'Requirements for Internet Hosts - Application and Support' 00949 * db['3068'] = 'An Anycast Prefix for 6to4 Relay Routers' 00950 * puts db['822'] 00951 */ 00952 void 00953 Init_dbm(void) 00954 { 00955 rb_cDBM = rb_define_class("DBM", rb_cObject); 00956 /* Document-class: DBMError 00957 * Exception class used to return errors from the dbm library. 00958 */ 00959 rb_eDBMError = rb_define_class("DBMError", rb_eStandardError); 00960 rb_include_module(rb_cDBM, rb_mEnumerable); 00961 00962 rb_define_alloc_func(rb_cDBM, fdbm_alloc); 00963 rb_define_singleton_method(rb_cDBM, "open", fdbm_s_open, -1); 00964 00965 rb_define_method(rb_cDBM, "initialize", fdbm_initialize, -1); 00966 rb_define_method(rb_cDBM, "close", fdbm_close, 0); 00967 rb_define_method(rb_cDBM, "closed?", fdbm_closed, 0); 00968 rb_define_method(rb_cDBM, "[]", fdbm_aref, 1); 00969 rb_define_method(rb_cDBM, "fetch", fdbm_fetch_m, -1); 00970 rb_define_method(rb_cDBM, "[]=", fdbm_store, 2); 00971 rb_define_method(rb_cDBM, "store", fdbm_store, 2); 00972 rb_define_method(rb_cDBM, "index", fdbm_index, 1); 00973 rb_define_method(rb_cDBM, "key", fdbm_key, 1); 00974 rb_define_method(rb_cDBM, "select", fdbm_select, 0); 00975 rb_define_method(rb_cDBM, "values_at", fdbm_values_at, -1); 00976 rb_define_method(rb_cDBM, "length", fdbm_length, 0); 00977 rb_define_method(rb_cDBM, "size", fdbm_length, 0); 00978 rb_define_method(rb_cDBM, "empty?", fdbm_empty_p, 0); 00979 rb_define_method(rb_cDBM, "each", fdbm_each_pair, 0); 00980 rb_define_method(rb_cDBM, "each_value", fdbm_each_value, 0); 00981 rb_define_method(rb_cDBM, "each_key", fdbm_each_key, 0); 00982 rb_define_method(rb_cDBM, "each_pair", fdbm_each_pair, 0); 00983 rb_define_method(rb_cDBM, "keys", fdbm_keys, 0); 00984 rb_define_method(rb_cDBM, "values", fdbm_values, 0); 00985 rb_define_method(rb_cDBM, "shift", fdbm_shift, 0); 00986 rb_define_method(rb_cDBM, "delete", fdbm_delete, 1); 00987 rb_define_method(rb_cDBM, "delete_if", fdbm_delete_if, 0); 00988 rb_define_method(rb_cDBM, "reject!", fdbm_delete_if, 0); 00989 rb_define_method(rb_cDBM, "reject", fdbm_reject, 0); 00990 rb_define_method(rb_cDBM, "clear", fdbm_clear, 0); 00991 rb_define_method(rb_cDBM,"invert", fdbm_invert, 0); 00992 rb_define_method(rb_cDBM,"update", fdbm_update, 1); 00993 rb_define_method(rb_cDBM,"replace", fdbm_replace, 1); 00994 00995 rb_define_method(rb_cDBM, "include?", fdbm_has_key, 1); 00996 rb_define_method(rb_cDBM, "has_key?", fdbm_has_key, 1); 00997 rb_define_method(rb_cDBM, "member?", fdbm_has_key, 1); 00998 rb_define_method(rb_cDBM, "has_value?", fdbm_has_value, 1); 00999 rb_define_method(rb_cDBM, "key?", fdbm_has_key, 1); 01000 rb_define_method(rb_cDBM, "value?", fdbm_has_value, 1); 01001 01002 rb_define_method(rb_cDBM, "to_a", fdbm_to_a, 0); 01003 rb_define_method(rb_cDBM, "to_hash", fdbm_to_hash, 0); 01004 01005 /* Indicates that dbm_open() should open the database in read-only mode */ 01006 rb_define_const(rb_cDBM, "READER", INT2FIX(O_RDONLY|RUBY_DBM_RW_BIT)); 01007 01008 /* Indicates that dbm_open() should open the database in read/write mode */ 01009 rb_define_const(rb_cDBM, "WRITER", INT2FIX(O_RDWR|RUBY_DBM_RW_BIT)); 01010 01011 /* Indicates that dbm_open() should open the database in read/write mode, 01012 * and create it if it does not already exist 01013 */ 01014 rb_define_const(rb_cDBM, "WRCREAT", INT2FIX(O_RDWR|O_CREAT|RUBY_DBM_RW_BIT)); 01015 01016 /* Indicates that dbm_open() should open the database in read/write mode, 01017 * create it if it does not already exist, and delete all contents if it 01018 * does already exist. 01019 */ 01020 rb_define_const(rb_cDBM, "NEWDB", INT2FIX(O_RDWR|O_CREAT|O_TRUNC|RUBY_DBM_RW_BIT)); 01021 01022 #if defined(HAVE_DB_VERSION) 01023 /* The version of the dbm library, if using Berkeley DB */ 01024 rb_define_const(rb_cDBM, "VERSION", rb_str_new2(db_version(NULL, NULL, NULL))); 01025 #elif defined(HAVE_GDBM_VERSION) 01026 /* since gdbm 1.9 */ 01027 rb_define_const(rb_cDBM, "VERSION", rb_str_new2(gdbm_version)); 01028 #elif defined(HAVE_LIBVAR_GDBM_VERSION) 01029 /* ndbm.h doesn't declare gdbm_version until gdbm 1.8.3. 01030 * See extconf.rb for more information. */ 01031 { 01032 RUBY_EXTERN char *gdbm_version; 01033 rb_define_const(rb_cDBM, "VERSION", rb_str_new2(gdbm_version)); 01034 } 01035 #elif defined(HAVE_DPVERSION) 01036 rb_define_const(rb_cDBM, "VERSION", rb_sprintf("QDBM %s", dpversion)); 01037 #elif defined(_DB_H_) 01038 rb_define_const(rb_cDBM, "VERSION", rb_str_new2("Berkeley DB (unknown)")); 01039 #else 01040 rb_define_const(rb_cDBM, "VERSION", rb_str_new2("unknown")); 01041 #endif 01042 } 01043