Ruby  1.9.3p392(2013-02-22revision39386)
dbm.c
Go to the documentation of this file.
1 /************************************************
2 
3  dbm.c -
4 
5  $Author: naruse $
6  created at: Mon Jan 24 15:59:52 JST 1994
7 
8  Copyright (C) 1995-2001 Yukihiro Matsumoto
9 
10 ************************************************/
11 
12 #include "ruby.h"
13 
14 #ifdef HAVE_CDEFS_H
15 # include <cdefs.h>
16 #endif
17 #ifdef HAVE_SYS_CDEFS_H
18 # include <sys/cdefs.h>
19 #endif
20 #include DBM_HDR
21 #include <fcntl.h>
22 #include <errno.h>
23 
25 
26 #define RUBY_DBM_RW_BIT 0x20000000
27 
28 struct dbmdata {
29  long di_size;
31 };
32 
33 static void
35 {
36  rb_raise(rb_eDBMError, "closed DBM file");
37 }
38 
39 #define GetDBM(obj, dbmp) {\
40  Data_Get_Struct((obj), struct dbmdata, (dbmp));\
41  if ((dbmp) == 0) closed_dbm();\
42  if ((dbmp)->di_dbm == 0) closed_dbm();\
43 }
44 
45 #define GetDBM2(obj, data, dbm) {\
46  GetDBM((obj), (data));\
47  (dbm) = dbmp->di_dbm;\
48 }
49 
50 static void
51 free_dbm(struct dbmdata *dbmp)
52 {
53  if (dbmp) {
54  if (dbmp->di_dbm) dbm_close(dbmp->di_dbm);
55  xfree(dbmp);
56  }
57 }
58 
59 /*
60  * call-seq:
61  * dbm.close
62  *
63  * Closes the database.
64  */
65 static VALUE
67 {
68  struct dbmdata *dbmp;
69 
70  GetDBM(obj, dbmp);
71  dbm_close(dbmp->di_dbm);
72  dbmp->di_dbm = 0;
73 
74  return Qnil;
75 }
76 
77 /*
78  * call-seq:
79  * dbm.closed? -> true or false
80  *
81  * Returns true if the database is closed, false otherwise.
82  */
83 static VALUE
85 {
86  struct dbmdata *dbmp;
87 
88  Data_Get_Struct(obj, struct dbmdata, dbmp);
89  if (dbmp == 0)
90  return Qtrue;
91  if (dbmp->di_dbm == 0)
92  return Qtrue;
93 
94  return Qfalse;
95 }
96 
97 static VALUE
99 {
100  return Data_Wrap_Struct(klass, 0, free_dbm, 0);
101 }
102 
103 /*
104  * call-seq:
105  * DBM.new(filename[, mode[, flags]]) -> dbm
106  *
107  * Open a dbm database with the specified name, which can include a directory
108  * path. Any file extensions needed will be supplied automatically by the dbm
109  * library. For example, Berkeley DB appends '.db', and GNU gdbm uses two
110  * physical files with extensions '.dir' and '.pag'.
111  *
112  * The mode should be an integer, as for Unix chmod.
113  *
114  * Flags should be one of READER, WRITER, WRCREAT or NEWDB.
115  */
116 static VALUE
118 {
119  volatile VALUE file;
120  VALUE vmode, vflags;
121  DBM *dbm;
122  struct dbmdata *dbmp;
123  int mode, flags = 0;
124 
125  if (rb_scan_args(argc, argv, "12", &file, &vmode, &vflags) == 1) {
126  mode = 0666; /* default value */
127  }
128  else if (NIL_P(vmode)) {
129  mode = -1; /* return nil if DB not exist */
130  }
131  else {
132  mode = NUM2INT(vmode);
133  }
134 
135  if (!NIL_P(vflags))
136  flags = NUM2INT(vflags);
137 
138  FilePathValue(file);
139 
140  if (flags & RUBY_DBM_RW_BIT) {
141  flags &= ~RUBY_DBM_RW_BIT;
142  dbm = dbm_open(RSTRING_PTR(file), flags, mode);
143  }
144  else {
145  dbm = 0;
146  if (mode >= 0) {
147  dbm = dbm_open(RSTRING_PTR(file), O_RDWR|O_CREAT, mode);
148  }
149  if (!dbm) {
150  dbm = dbm_open(RSTRING_PTR(file), O_RDWR, 0);
151  }
152  if (!dbm) {
153  dbm = dbm_open(RSTRING_PTR(file), O_RDONLY, 0);
154  }
155  }
156 
157  if (!dbm) {
158  if (mode == -1) return Qnil;
159  rb_sys_fail(RSTRING_PTR(file));
160  }
161 
162  dbmp = ALLOC(struct dbmdata);
163  DATA_PTR(obj) = dbmp;
164  dbmp->di_dbm = dbm;
165  dbmp->di_size = -1;
166 
167  return obj;
168 }
169 
170 /*
171  * call-seq:
172  * DBM.open(filename[, mode[, flags]]) -> dbm
173  * DBM.open(filename[, mode[, flags]]) {|dbm| block}
174  *
175  * Open a dbm database and yields it if a block is given. See also
176  * <code>DBM.new</code>.
177  */
178 static VALUE
180 {
181  VALUE obj = Data_Wrap_Struct(klass, 0, free_dbm, 0);
182 
183  if (NIL_P(fdbm_initialize(argc, argv, obj))) {
184  return Qnil;
185  }
186 
187  if (rb_block_given_p()) {
188  return rb_ensure(rb_yield, obj, fdbm_close, obj);
189  }
190 
191  return obj;
192 }
193 
194 static VALUE
195 fdbm_fetch(VALUE obj, VALUE keystr, VALUE ifnone)
196 {
197  datum key, value;
198  struct dbmdata *dbmp;
199  DBM *dbm;
200 
201  ExportStringValue(keystr);
202  key.dptr = RSTRING_PTR(keystr);
203  key.dsize = (int)RSTRING_LEN(keystr);
204 
205  GetDBM2(obj, dbmp, dbm);
206  value = dbm_fetch(dbm, key);
207  if (value.dptr == 0) {
208  if (ifnone == Qnil && rb_block_given_p())
209  return rb_yield(rb_tainted_str_new(key.dptr, key.dsize));
210  return ifnone;
211  }
212  return rb_tainted_str_new(value.dptr, value.dsize);
213 }
214 
215 /*
216  * call-seq:
217  * dbm[key] -> string value or nil
218  *
219  * Return a value from the database by locating the key string
220  * provided. If the key is not found, returns nil.
221  */
222 static VALUE
223 fdbm_aref(VALUE obj, VALUE keystr)
224 {
225  return fdbm_fetch(obj, keystr, Qnil);
226 }
227 
228 /*
229  * call-seq:
230  * dbm.fetch(key[, ifnone]) -> value
231  *
232  * Return a value from the database by locating the key string
233  * provided. If the key is not found, returns +ifnone+. If +ifnone+
234  * is not given, raises IndexError.
235  */
236 static VALUE
238 {
239  VALUE keystr, valstr, ifnone;
240 
241  rb_scan_args(argc, argv, "11", &keystr, &ifnone);
242  valstr = fdbm_fetch(obj, keystr, ifnone);
243  if (argc == 1 && !rb_block_given_p() && NIL_P(valstr))
244  rb_raise(rb_eIndexError, "key not found");
245 
246  return valstr;
247 }
248 
249 /*
250  * call-seq:
251  * dbm.key(value) -> string
252  *
253  * Returns the key for the specified value.
254  */
255 static VALUE
256 fdbm_key(VALUE obj, VALUE valstr)
257 {
258  datum key, val;
259  struct dbmdata *dbmp;
260  DBM *dbm;
261 
262  ExportStringValue(valstr);
263  val.dptr = RSTRING_PTR(valstr);
264  val.dsize = (int)RSTRING_LEN(valstr);
265 
266  GetDBM2(obj, dbmp, dbm);
267  for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
268  val = dbm_fetch(dbm, key);
269  if ((long)val.dsize == (int)RSTRING_LEN(valstr) &&
270  memcmp(val.dptr, RSTRING_PTR(valstr), val.dsize) == 0) {
271  return rb_tainted_str_new(key.dptr, key.dsize);
272  }
273  }
274  return Qnil;
275 }
276 
277 /* :nodoc: */
278 static VALUE
280 {
281  rb_warn("DBM#index is deprecated; use DBM#key");
282  return fdbm_key(hash, value);
283 }
284 
285 /*
286  * call-seq:
287  * dbm.select {|key, value| block} -> array
288  *
289  * Returns a new array consisting of the [key, value] pairs for which the code
290  * block returns true.
291  */
292 static VALUE
294 {
295  VALUE new = rb_ary_new();
296  datum key, val;
297  DBM *dbm;
298  struct dbmdata *dbmp;
299 
300  GetDBM2(obj, dbmp, dbm);
301  for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
302  VALUE assoc, v;
303  val = dbm_fetch(dbm, key);
304  assoc = rb_assoc_new(rb_tainted_str_new(key.dptr, key.dsize),
305  rb_tainted_str_new(val.dptr, val.dsize));
306  v = rb_yield(assoc);
307  if (RTEST(v)) {
308  rb_ary_push(new, assoc);
309  }
310  GetDBM2(obj, dbmp, dbm);
311  }
312 
313  return new;
314 }
315 
316 /*
317  * call-seq:
318  * dbm.values_at(key, ...) -> Array
319  *
320  * Returns an array containing the values associated with the given keys.
321  */
322 static VALUE
324 {
325  VALUE new = rb_ary_new2(argc);
326  int i;
327 
328  for (i=0; i<argc; i++) {
329  rb_ary_push(new, fdbm_fetch(obj, argv[i], Qnil));
330  }
331 
332  return new;
333 }
334 
335 static void
337 {
338  rb_secure(4);
339  if (OBJ_FROZEN(obj)) rb_error_frozen("DBM");
340 }
341 
342 /*
343  * call-seq:
344  * dbm.delete(key)
345  *
346  * Deletes an entry from the database.
347  */
348 static VALUE
349 fdbm_delete(VALUE obj, VALUE keystr)
350 {
351  datum key, value;
352  struct dbmdata *dbmp;
353  DBM *dbm;
354  VALUE valstr;
355 
356  fdbm_modify(obj);
357  ExportStringValue(keystr);
358  key.dptr = RSTRING_PTR(keystr);
359  key.dsize = (int)RSTRING_LEN(keystr);
360 
361  GetDBM2(obj, dbmp, dbm);
362 
363  value = dbm_fetch(dbm, key);
364  if (value.dptr == 0) {
365  if (rb_block_given_p()) return rb_yield(keystr);
366  return Qnil;
367  }
368 
369  /* need to save value before dbm_delete() */
370  valstr = rb_tainted_str_new(value.dptr, value.dsize);
371 
372  if (dbm_delete(dbm, key)) {
373  dbmp->di_size = -1;
374  rb_raise(rb_eDBMError, "dbm_delete failed");
375  }
376  else if (dbmp->di_size >= 0) {
377  dbmp->di_size--;
378  }
379  return valstr;
380 }
381 
382 /*
383  * call-seq:
384  * dbm.shift() -> [key, value]
385  *
386  * Removes a [key, value] pair from the database, and returns it.
387  * If the database is empty, returns nil.
388  * The order in which values are removed/returned is not guaranteed.
389  */
390 static VALUE
392 {
393  datum key, val;
394  struct dbmdata *dbmp;
395  DBM *dbm;
396  VALUE keystr, valstr;
397 
398  fdbm_modify(obj);
399  GetDBM2(obj, dbmp, dbm);
400  dbmp->di_size = -1;
401 
402  key = dbm_firstkey(dbm);
403  if (!key.dptr) return Qnil;
404  val = dbm_fetch(dbm, key);
405  keystr = rb_tainted_str_new(key.dptr, key.dsize);
406  valstr = rb_tainted_str_new(val.dptr, val.dsize);
407  dbm_delete(dbm, key);
408 
409  return rb_assoc_new(keystr, valstr);
410 }
411 
412 /*
413  * call-seq:
414  * dbm.reject! {|key, value| block} -> self
415  * dbm.delete_if {|key, value| block} -> self
416  *
417  * Deletes all entries for which the code block returns true.
418  * Returns self.
419  */
420 static VALUE
422 {
423  datum key, val;
424  struct dbmdata *dbmp;
425  DBM *dbm;
426  VALUE keystr, valstr;
427  VALUE ret, ary = rb_ary_new();
428  int i, status = 0;
429  long n;
430 
431  fdbm_modify(obj);
432  GetDBM2(obj, dbmp, dbm);
433  n = dbmp->di_size;
434  dbmp->di_size = -1;
435 
436  for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
437  val = dbm_fetch(dbm, key);
438  keystr = rb_tainted_str_new(key.dptr, key.dsize);
439  valstr = rb_tainted_str_new(val.dptr, val.dsize);
440  ret = rb_protect(rb_yield, rb_assoc_new(rb_str_dup(keystr), valstr), &status);
441  if (status != 0) break;
442  if (RTEST(ret)) rb_ary_push(ary, keystr);
443  GetDBM2(obj, dbmp, dbm);
444  }
445 
446  for (i = 0; i < RARRAY_LEN(ary); i++) {
447  keystr = RARRAY_PTR(ary)[i];
448  ExportStringValue(keystr);
449  key.dptr = RSTRING_PTR(keystr);
450  key.dsize = (int)RSTRING_LEN(keystr);
451  if (dbm_delete(dbm, key)) {
452  rb_raise(rb_eDBMError, "dbm_delete failed");
453  }
454  }
455  if (status) rb_jump_tag(status);
456  if (n > 0) dbmp->di_size = n - RARRAY_LEN(ary);
457 
458  return obj;
459 }
460 
461 /*
462  * call-seq:
463  * dbm.clear
464  *
465  * Deletes all data from the database.
466  */
467 static VALUE
469 {
470  datum key;
471  struct dbmdata *dbmp;
472  DBM *dbm;
473 
474  fdbm_modify(obj);
475  GetDBM2(obj, dbmp, dbm);
476  dbmp->di_size = -1;
477  while (key = dbm_firstkey(dbm), key.dptr) {
478  if (dbm_delete(dbm, key)) {
479  rb_raise(rb_eDBMError, "dbm_delete failed");
480  }
481  }
482  dbmp->di_size = 0;
483 
484  return obj;
485 }
486 
487 /*
488  * call-seq:
489  * dbm.invert -> hash
490  *
491  * Returns a Hash (not a DBM database) created by using each value in the
492  * database as a key, with the corresponding key as its value.
493  */
494 static VALUE
496 {
497  datum key, val;
498  struct dbmdata *dbmp;
499  DBM *dbm;
500  VALUE keystr, valstr;
501  VALUE hash = rb_hash_new();
502 
503  GetDBM2(obj, dbmp, dbm);
504  for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
505  val = dbm_fetch(dbm, key);
506  keystr = rb_tainted_str_new(key.dptr, key.dsize);
507  valstr = rb_tainted_str_new(val.dptr, val.dsize);
508  rb_hash_aset(hash, valstr, keystr);
509  }
510  return hash;
511 }
512 
514 
515 static VALUE
516 update_i(VALUE pair, VALUE dbm)
517 {
518  Check_Type(pair, T_ARRAY);
519  if (RARRAY_LEN(pair) < 2) {
520  rb_raise(rb_eArgError, "pair must be [key, value]");
521  }
522  fdbm_store(dbm, RARRAY_PTR(pair)[0], RARRAY_PTR(pair)[1]);
523  return Qnil;
524 }
525 
526 /*
527  * call-seq:
528  * dbm.update(obj)
529  *
530  * Updates the database with multiple values from the specified object.
531  * Takes any object which implements the each_pair method, including
532  * Hash and DBM objects.
533  */
534 static VALUE
536 {
537  rb_block_call(other, rb_intern("each_pair"), 0, 0, update_i, obj);
538  return obj;
539 }
540 
541 /*
542  * call-seq:
543  * dbm.replace(obj)
544  *
545  * Replaces the contents of the database with the contents of the specified
546  * object. Takes any object which implements the each_pair method, including
547  * Hash and DBM objects.
548  */
549 static VALUE
551 {
552  fdbm_clear(obj);
553  rb_block_call(other, rb_intern("each_pair"), 0, 0, update_i, obj);
554  return obj;
555 }
556 
557 /*
558  * call-seq:
559  * dbm.store(key, value) -> value
560  * dbm[key] = value
561  *
562  * Stores the specified string value in the database, indexed via the
563  * string key provided.
564  */
565 static VALUE
566 fdbm_store(VALUE obj, VALUE keystr, VALUE valstr)
567 {
568  datum key, val;
569  struct dbmdata *dbmp;
570  DBM *dbm;
571 
572  fdbm_modify(obj);
573  keystr = rb_obj_as_string(keystr);
574  valstr = rb_obj_as_string(valstr);
575 
576  key.dptr = RSTRING_PTR(keystr);
577  key.dsize = (int)RSTRING_LEN(keystr);
578 
579  val.dptr = RSTRING_PTR(valstr);
580  val.dsize = (int)RSTRING_LEN(valstr);
581 
582  GetDBM2(obj, dbmp, dbm);
583  dbmp->di_size = -1;
584  if (dbm_store(dbm, key, val, DBM_REPLACE)) {
585 #ifdef HAVE_DBM_CLEARERR
586  dbm_clearerr(dbm);
587 #endif
588  if (errno == EPERM) rb_sys_fail(0);
589  rb_raise(rb_eDBMError, "dbm_store failed");
590  }
591 
592  return valstr;
593 }
594 
595 /*
596  * call-seq:
597  * dbm.length -> integer
598  *
599  * Returns the number of entries in the database.
600  */
601 static VALUE
603 {
604  datum key;
605  struct dbmdata *dbmp;
606  DBM *dbm;
607  int i = 0;
608 
609  GetDBM2(obj, dbmp, dbm);
610  if (dbmp->di_size > 0) return INT2FIX(dbmp->di_size);
611 
612  for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
613  i++;
614  }
615  dbmp->di_size = i;
616 
617  return INT2FIX(i);
618 }
619 
620 /*
621  * call-seq:
622  * dbm.empty?
623  *
624  * Returns true if the database is empty, false otherwise.
625  */
626 static VALUE
628 {
629  datum key;
630  struct dbmdata *dbmp;
631  DBM *dbm;
632  int i = 0;
633 
634  GetDBM2(obj, dbmp, dbm);
635  if (dbmp->di_size < 0) {
636  dbm = dbmp->di_dbm;
637 
638  for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
639  i++;
640  }
641  }
642  else {
643  i = (int)dbmp->di_size;
644  }
645  if (i == 0) return Qtrue;
646  return Qfalse;
647 }
648 
649 /*
650  * call-seq:
651  * dbm.each_value {|value| block} -> self
652  *
653  * Calls the block once for each value string in the database. Returns self.
654  */
655 static VALUE
657 {
658  datum key, val;
659  struct dbmdata *dbmp;
660  DBM *dbm;
661 
662  RETURN_ENUMERATOR(obj, 0, 0);
663 
664  GetDBM2(obj, dbmp, dbm);
665  for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
666  val = dbm_fetch(dbm, key);
668  GetDBM2(obj, dbmp, dbm);
669  }
670  return obj;
671 }
672 
673 /*
674  * call-seq:
675  * dbm.each_key {|key| block} -> self
676  *
677  * Calls the block once for each key string in the database. Returns self.
678  */
679 static VALUE
681 {
682  datum key;
683  struct dbmdata *dbmp;
684  DBM *dbm;
685 
686  RETURN_ENUMERATOR(obj, 0, 0);
687 
688  GetDBM2(obj, dbmp, dbm);
689  for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
691  GetDBM2(obj, dbmp, dbm);
692  }
693  return obj;
694 }
695 
696 /*
697  * call-seq:
698  * dbm.each_pair {|key,value| block} -> self
699  *
700  * Calls the block once for each [key, value] pair in the database.
701  * Returns self.
702  */
703 static VALUE
705 {
706  datum key, val;
707  DBM *dbm;
708  struct dbmdata *dbmp;
709  VALUE keystr, valstr;
710 
711  RETURN_ENUMERATOR(obj, 0, 0);
712 
713  GetDBM2(obj, dbmp, dbm);
714 
715  for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
716  val = dbm_fetch(dbm, key);
717  keystr = rb_tainted_str_new(key.dptr, key.dsize);
718  valstr = rb_tainted_str_new(val.dptr, val.dsize);
719  rb_yield(rb_assoc_new(keystr, valstr));
720  GetDBM2(obj, dbmp, dbm);
721  }
722 
723  return obj;
724 }
725 
726 /*
727  * call-seq:
728  * dbm.keys -> array
729  *
730  * Returns an array of all the string keys in the database.
731  */
732 static VALUE
734 {
735  datum key;
736  struct dbmdata *dbmp;
737  DBM *dbm;
738  VALUE ary;
739 
740  GetDBM2(obj, dbmp, dbm);
741 
742  ary = rb_ary_new();
743  for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
744  rb_ary_push(ary, rb_tainted_str_new(key.dptr, key.dsize));
745  }
746 
747  return ary;
748 }
749 
750 /*
751  * call-seq:
752  * dbm.values -> array
753  *
754  * Returns an array of all the string values in the database.
755  */
756 static VALUE
758 {
759  datum key, val;
760  struct dbmdata *dbmp;
761  DBM *dbm;
762  VALUE ary;
763 
764  GetDBM2(obj, dbmp, dbm);
765  ary = rb_ary_new();
766  for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
767  val = dbm_fetch(dbm, key);
768  rb_ary_push(ary, rb_tainted_str_new(val.dptr, val.dsize));
769  }
770 
771  return ary;
772 }
773 
774 /*
775  * call-seq:
776  * dbm.has_key?(key) -> boolean
777  *
778  * Returns true if the database contains the specified key, false otherwise.
779  */
780 static VALUE
782 {
783  datum key, val;
784  struct dbmdata *dbmp;
785  DBM *dbm;
786 
787  ExportStringValue(keystr);
788  key.dptr = RSTRING_PTR(keystr);
789  key.dsize = (int)RSTRING_LEN(keystr);
790 
791  GetDBM2(obj, dbmp, dbm);
792  val = dbm_fetch(dbm, key);
793  if (val.dptr) return Qtrue;
794  return Qfalse;
795 }
796 
797 /*
798  * call-seq:
799  * dbm.has_value?(value) -> boolean
800  *
801  * Returns true if the database contains the specified string value, false
802  * otherwise.
803  */
804 static VALUE
806 {
807  datum key, val;
808  struct dbmdata *dbmp;
809  DBM *dbm;
810 
811  ExportStringValue(valstr);
812  val.dptr = RSTRING_PTR(valstr);
813  val.dsize = (int)RSTRING_LEN(valstr);
814 
815  GetDBM2(obj, dbmp, dbm);
816  for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
817  val = dbm_fetch(dbm, key);
818  if (val.dsize == (int)RSTRING_LEN(valstr) &&
819  memcmp(val.dptr, RSTRING_PTR(valstr), val.dsize) == 0)
820  return Qtrue;
821  }
822  return Qfalse;
823 }
824 
825 /*
826  * call-seq:
827  * dbm.to_a -> array
828  *
829  * Converts the contents of the database to an array of [key, value] arrays,
830  * and returns it.
831  */
832 static VALUE
834 {
835  datum key, val;
836  struct dbmdata *dbmp;
837  DBM *dbm;
838  VALUE ary;
839 
840  GetDBM2(obj, dbmp, dbm);
841  ary = rb_ary_new();
842  for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
843  val = dbm_fetch(dbm, key);
845  rb_tainted_str_new(val.dptr, val.dsize)));
846  }
847 
848  return ary;
849 }
850 
851 /*
852  * call-seq:
853  * dbm.to_hash -> hash
854  *
855  * Converts the contents of the database to an in-memory Hash object, and
856  * returns it.
857  */
858 static VALUE
860 {
861  datum key, val;
862  struct dbmdata *dbmp;
863  DBM *dbm;
864  VALUE hash;
865 
866  GetDBM2(obj, dbmp, dbm);
867  hash = rb_hash_new();
868  for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
869  val = dbm_fetch(dbm, key);
870  rb_hash_aset(hash, rb_tainted_str_new(key.dptr, key.dsize),
871  rb_tainted_str_new(val.dptr, val.dsize));
872  }
873 
874  return hash;
875 }
876 
877 /*
878  * call-seq:
879  * dbm.reject {|key,value| block} -> Hash
880  *
881  * Converts the contents of the database to an in-memory Hash, then calls
882  * Hash#reject with the specified code block, returning a new Hash.
883  */
884 static VALUE
886 {
887  return rb_hash_delete_if(fdbm_to_hash(obj));
888 }
889 
890 /*
891  * Documented by mathew meta@pobox.com.
892  * = Introduction
893  *
894  * The DBM class provides a wrapper to a Unix-style
895  * {dbm}[http://en.wikipedia.org/wiki/Dbm] or Database Manager library.
896  *
897  * Dbm databases do not have tables or columns; they are simple key-value
898  * data stores, like a Ruby Hash except not resident in RAM. Keys and values
899  * must be strings.
900  *
901  * The exact library used depends on how Ruby was compiled. It could be any
902  * of the following:
903  *
904  * - The original ndbm library is released in 4.3BSD.
905  * It is based on dbm library in Unix Version 7 but has different API to
906  * support multiple databases in a process.
907  * - {Berkeley DB}[http://en.wikipedia.org/wiki/Berkeley_DB] versions
908  * 1 thru 5, also known as BDB and Sleepycat DB, now owned by Oracle
909  * Corporation.
910  * - Berkeley DB 1.x, still found in FreeBSD and OpenBSD.
911  * - {gdbm}[http://www.gnu.org/software/gdbm/], the GNU implementation of dbm.
912  * - {qdbm}[http://fallabs.com/qdbm/index.html], another open source
913  * reimplementation of dbm.
914  *
915  * All of these dbm implementations have their own Ruby interfaces
916  * available, which provide richer (but varying) APIs.
917  *
918  * = Cautions
919  *
920  * Before you decide to use DBM, there are some issues you should consider:
921  *
922  * - Each implementation of dbm has its own file format. Generally, dbm
923  * libraries will not read each other's files. This makes dbm files
924  * a bad choice for data exchange.
925  *
926  * - Even running the same OS and the same dbm implementation, the database
927  * file format may depend on the CPU architecture. For example, files may
928  * not be portable between PowerPC and 386, or between 32 and 64 bit Linux.
929  *
930  * - Different versions of Berkeley DB use different file formats. A change to
931  * the OS may therefore break DBM access to existing files.
932  *
933  * - Data size limits vary between implementations. Original Berkeley DB was
934  * limited to 2GB of data. Dbm libraries also sometimes limit the total
935  * size of a key/value pair, and the total size of all the keys that hash
936  * to the same value. These limits can be as little as 512 bytes. That said,
937  * gdbm and recent versions of Berkeley DB do away with these limits.
938  *
939  * Given the above cautions, DBM is not a good choice for long term storage of
940  * important data. It is probably best used as a fast and easy alternative
941  * to a Hash for processing large amounts of data.
942  *
943  * = Example
944  *
945  * require 'dbm'
946  * db = DBM.open('rfcs', 666, DBM::CREATRW)
947  * db['822'] = 'Standard for the Format of ARPA Internet Text Messages'
948  * db['1123'] = 'Requirements for Internet Hosts - Application and Support'
949  * db['3068'] = 'An Anycast Prefix for 6to4 Relay Routers'
950  * puts db['822']
951  */
952 void
953 Init_dbm(void)
954 {
956  /* Document-class: DBMError
957  * Exception class used to return errors from the dbm library.
958  */
961 
964 
965  rb_define_method(rb_cDBM, "initialize", fdbm_initialize, -1);
966  rb_define_method(rb_cDBM, "close", fdbm_close, 0);
967  rb_define_method(rb_cDBM, "closed?", fdbm_closed, 0);
969  rb_define_method(rb_cDBM, "fetch", fdbm_fetch_m, -1);
970  rb_define_method(rb_cDBM, "[]=", fdbm_store, 2);
971  rb_define_method(rb_cDBM, "store", fdbm_store, 2);
972  rb_define_method(rb_cDBM, "index", fdbm_index, 1);
973  rb_define_method(rb_cDBM, "key", fdbm_key, 1);
974  rb_define_method(rb_cDBM, "select", fdbm_select, 0);
975  rb_define_method(rb_cDBM, "values_at", fdbm_values_at, -1);
976  rb_define_method(rb_cDBM, "length", fdbm_length, 0);
977  rb_define_method(rb_cDBM, "size", fdbm_length, 0);
978  rb_define_method(rb_cDBM, "empty?", fdbm_empty_p, 0);
980  rb_define_method(rb_cDBM, "each_value", fdbm_each_value, 0);
981  rb_define_method(rb_cDBM, "each_key", fdbm_each_key, 0);
982  rb_define_method(rb_cDBM, "each_pair", fdbm_each_pair, 0);
983  rb_define_method(rb_cDBM, "keys", fdbm_keys, 0);
984  rb_define_method(rb_cDBM, "values", fdbm_values, 0);
985  rb_define_method(rb_cDBM, "shift", fdbm_shift, 0);
986  rb_define_method(rb_cDBM, "delete", fdbm_delete, 1);
987  rb_define_method(rb_cDBM, "delete_if", fdbm_delete_if, 0);
988  rb_define_method(rb_cDBM, "reject!", fdbm_delete_if, 0);
989  rb_define_method(rb_cDBM, "reject", fdbm_reject, 0);
990  rb_define_method(rb_cDBM, "clear", fdbm_clear, 0);
991  rb_define_method(rb_cDBM,"invert", fdbm_invert, 0);
992  rb_define_method(rb_cDBM,"update", fdbm_update, 1);
993  rb_define_method(rb_cDBM,"replace", fdbm_replace, 1);
994 
995  rb_define_method(rb_cDBM, "include?", fdbm_has_key, 1);
996  rb_define_method(rb_cDBM, "has_key?", fdbm_has_key, 1);
997  rb_define_method(rb_cDBM, "member?", fdbm_has_key, 1);
998  rb_define_method(rb_cDBM, "has_value?", fdbm_has_value, 1);
1000  rb_define_method(rb_cDBM, "value?", fdbm_has_value, 1);
1001 
1002  rb_define_method(rb_cDBM, "to_a", fdbm_to_a, 0);
1003  rb_define_method(rb_cDBM, "to_hash", fdbm_to_hash, 0);
1004 
1005  /* Indicates that dbm_open() should open the database in read-only mode */
1006  rb_define_const(rb_cDBM, "READER", INT2FIX(O_RDONLY|RUBY_DBM_RW_BIT));
1007 
1008  /* Indicates that dbm_open() should open the database in read/write mode */
1009  rb_define_const(rb_cDBM, "WRITER", INT2FIX(O_RDWR|RUBY_DBM_RW_BIT));
1010 
1011  /* Indicates that dbm_open() should open the database in read/write mode,
1012  * and create it if it does not already exist
1013  */
1014  rb_define_const(rb_cDBM, "WRCREAT", INT2FIX(O_RDWR|O_CREAT|RUBY_DBM_RW_BIT));
1015 
1016  /* Indicates that dbm_open() should open the database in read/write mode,
1017  * create it if it does not already exist, and delete all contents if it
1018  * does already exist.
1019  */
1020  rb_define_const(rb_cDBM, "NEWDB", INT2FIX(O_RDWR|O_CREAT|O_TRUNC|RUBY_DBM_RW_BIT));
1021 
1022 #if defined(HAVE_DB_VERSION)
1023  /* The version of the dbm library, if using Berkeley DB */
1024  rb_define_const(rb_cDBM, "VERSION", rb_str_new2(db_version(NULL, NULL, NULL)));
1025 #elif defined(HAVE_GDBM_VERSION)
1026  /* since gdbm 1.9 */
1027  rb_define_const(rb_cDBM, "VERSION", rb_str_new2(gdbm_version));
1028 #elif defined(HAVE_LIBVAR_GDBM_VERSION)
1029  /* ndbm.h doesn't declare gdbm_version until gdbm 1.8.3.
1030  * See extconf.rb for more information. */
1031  {
1032  RUBY_EXTERN char *gdbm_version;
1033  rb_define_const(rb_cDBM, "VERSION", rb_str_new2(gdbm_version));
1034  }
1035 #elif defined(HAVE_DPVERSION)
1036  rb_define_const(rb_cDBM, "VERSION", rb_sprintf("QDBM %s", dpversion));
1037 #elif defined(_DB_H_)
1038  rb_define_const(rb_cDBM, "VERSION", rb_str_new2("Berkeley DB (unknown)"));
1039 #else
1040  rb_define_const(rb_cDBM, "VERSION", rb_str_new2("unknown"));
1041 #endif
1042 }
1043