Ruby 2.7.6p219 (2022-04-12 revision c9c2245c0a25176072e02db9254f0e0c84c805cd)
gdbm.c
Go to the documentation of this file.
1/************************************************
2
3 gdbm.c -
4
5 $Author$
6 modified at: Mon Jan 24 15:59:52 JST 1994
7
8 Documentation by Peter Adolphs < futzilogik at users dot sourceforge dot net >
9
10************************************************/
11
12#include "ruby.h"
13
14#include <gdbm.h>
15#include <fcntl.h>
16#include <errno.h>
17
18/*
19 * Document-class: GDBM
20 *
21 * == Summary
22 *
23 * Ruby extension for GNU dbm (gdbm) -- a simple database engine for storing
24 * key-value pairs on disk.
25 *
26 * == Description
27 *
28 * GNU dbm is a library for simple databases. A database is a file that stores
29 * key-value pairs. Gdbm allows the user to store, retrieve, and delete data by
30 * key. It furthermore allows a non-sorted traversal of all key-value pairs.
31 * A gdbm database thus provides the same functionality as a hash. As
32 * with objects of the Hash class, elements can be accessed with <tt>[]</tt>.
33 * Furthermore, GDBM mixes in the Enumerable module, thus providing convenient
34 * methods such as #find, #collect, #map, etc.
35 *
36 * A process is allowed to open several different databases at the same time.
37 * A process can open a database as a "reader" or a "writer". Whereas a reader
38 * has only read-access to the database, a writer has read- and write-access.
39 * A database can be accessed either by any number of readers or by exactly one
40 * writer at the same time.
41 *
42 * == Examples
43 *
44 * 1. Opening/creating a database, and filling it with some entries:
45 *
46 * require 'gdbm'
47 *
48 * gdbm = GDBM.new("fruitstore.db")
49 * gdbm["ananas"] = "3"
50 * gdbm["banana"] = "8"
51 * gdbm["cranberry"] = "4909"
52 * gdbm.close
53 *
54 * 2. Reading out a database:
55 *
56 * require 'gdbm'
57 *
58 * gdbm = GDBM.new("fruitstore.db")
59 * gdbm.each_pair do |key, value|
60 * print "#{key}: #{value}\n"
61 * end
62 * gdbm.close
63 *
64 * produces
65 *
66 * banana: 8
67 * ananas: 3
68 * cranberry: 4909
69 *
70 * == Links
71 *
72 * * http://www.gnu.org/software/gdbm/
73 */
74static VALUE rb_cGDBM, rb_eGDBMError, rb_eGDBMFatalError;
75
76#if SIZEOF_LONG > SIZEOF_INT
77#define TOO_LONG(n) ((long)(+(int)(n)) != (long)(n))
78#else
79#define TOO_LONG(n) 0
80#endif
81
82#define RUBY_GDBM_RW_BIT 0x20000000
83
84#define MY_BLOCK_SIZE (2048)
85#define MY_FATAL_FUNC rb_gdbm_fatal
86
87NORETURN(static void rb_gdbm_fatal(const char *msg));
88NORETURN(static void closed_dbm(void));
89
90static void
91rb_gdbm_fatal(const char *msg)
92{
93 rb_raise(rb_eGDBMFatalError, "%s", msg);
94}
95
96struct dbmdata {
98 GDBM_FILE di_dbm;
99};
100
101static void
102closed_dbm(void)
103{
104 rb_raise(rb_eRuntimeError, "closed GDBM file");
105}
106
107#define GetDBM(obj, dbmp) do {\
108 TypedData_Get_Struct((obj), struct dbmdata, &dbm_type, (dbmp));\
109 if ((dbmp)->di_dbm == 0) closed_dbm();\
110} while (0)
111
112#define GetDBM2(obj, dbmp, dbm) do {\
113 GetDBM((obj), (dbmp));\
114 (dbm) = (dbmp)->di_dbm;\
115} while (0)
116
117static void
118free_dbm(void *ptr)
119{
120 struct dbmdata *dbmp = ptr;
121 if (dbmp->di_dbm)
122 gdbm_close(dbmp->di_dbm);
123 xfree(dbmp);
124}
125
126static size_t
127memsize_dbm(const void *ptr)
128{
129 const struct dbmdata *dbmp = ptr;
130 size_t size = sizeof(*dbmp);
131 if (dbmp->di_dbm)
132 size += DBM_SIZEOF_DBM;
133 return size;
134}
135
136static const rb_data_type_t dbm_type = {
137 "gdbm",
138 {0, free_dbm, memsize_dbm,},
139 0, 0,
141};
142
143/*
144 * call-seq:
145 * gdbm.close -> nil
146 *
147 * Closes the associated database file.
148 */
149static VALUE
150fgdbm_close(VALUE obj)
151{
152 struct dbmdata *dbmp;
153
154 GetDBM(obj, dbmp);
155 gdbm_close(dbmp->di_dbm);
156 dbmp->di_dbm = 0;
157
158 return Qnil;
159}
160
161/*
162 * call-seq:
163 * gdbm.closed? -> true or false
164 *
165 * Returns true if the associated database file has been closed.
166 */
167static VALUE
168fgdbm_closed(VALUE obj)
169{
170 struct dbmdata *dbmp;
171
172 TypedData_Get_Struct(obj, struct dbmdata, &dbm_type, dbmp);
173 if (dbmp->di_dbm == 0)
174 return Qtrue;
175
176 return Qfalse;
177}
178
179static VALUE
180fgdbm_s_alloc(VALUE klass)
181{
182 struct dbmdata *dbmp;
183
184 return TypedData_Make_Struct(klass, struct dbmdata, &dbm_type, dbmp);
185}
186
187/*
188 * call-seq:
189 * GDBM.new(filename, mode = 0666, flags = nil)
190 *
191 * Creates a new GDBM instance by opening a gdbm file named _filename_.
192 * If the file does not exist, a new file with file mode _mode_ will be
193 * created. _flags_ may be one of the following:
194 * * *READER* - open as a reader
195 * * *WRITER* - open as a writer
196 * * *WRCREAT* - open as a writer; if the database does not exist, create a new one
197 * * *NEWDB* - open as a writer; overwrite any existing databases
198 *
199 * The values *WRITER*, *WRCREAT* and *NEWDB* may be combined with the following
200 * values by bitwise or:
201 * * *SYNC* - cause all database operations to be synchronized to the disk
202 * * *NOLOCK* - do not lock the database file
203 *
204 * If no _flags_ are specified, the GDBM object will try to open the database
205 * file as a writer and will create it if it does not already exist
206 * (cf. flag <tt>WRCREAT</tt>). If this fails (for instance, if another process
207 * has already opened the database as a reader), it will try to open the
208 * database file as a reader (cf. flag <tt>READER</tt>).
209 */
210static VALUE
211fgdbm_initialize(int argc, VALUE *argv, VALUE obj)
212{
213 VALUE file, vmode, vflags;
214 GDBM_FILE dbm;
215 struct dbmdata *dbmp;
216 int mode, flags = 0;
217
218 TypedData_Get_Struct(obj, struct dbmdata, &dbm_type, dbmp);
219 if (rb_scan_args(argc, argv, "12", &file, &vmode, &vflags) == 1) {
220 mode = 0666; /* default value */
221 }
222 else if (NIL_P(vmode)) {
223 mode = -1; /* return nil if DB does not exist */
224 }
225 else {
226 mode = NUM2INT(vmode);
227 }
228
229 if (!NIL_P(vflags))
230 flags = NUM2INT(vflags);
231
232 FilePathValue(file);
233
234#ifdef GDBM_CLOEXEC
235 /* GDBM_CLOEXEC is available since gdbm 1.10. */
236 flags |= GDBM_CLOEXEC;
237#endif
238
239 if (flags & RUBY_GDBM_RW_BIT) {
240 flags &= ~RUBY_GDBM_RW_BIT;
241 dbm = gdbm_open(RSTRING_PTR(file), MY_BLOCK_SIZE,
242 flags, mode, MY_FATAL_FUNC);
243 }
244 else {
245 dbm = 0;
246 if (mode >= 0)
247 dbm = gdbm_open(RSTRING_PTR(file), MY_BLOCK_SIZE,
248 GDBM_WRCREAT|flags, mode, MY_FATAL_FUNC);
249 if (!dbm)
250 dbm = gdbm_open(RSTRING_PTR(file), MY_BLOCK_SIZE,
251 GDBM_WRITER|flags, 0, MY_FATAL_FUNC);
252 if (!dbm)
253 dbm = gdbm_open(RSTRING_PTR(file), MY_BLOCK_SIZE,
254 GDBM_READER|flags, 0, MY_FATAL_FUNC);
255 }
256
257 if (dbm) {
258 rb_fd_fix_cloexec(gdbm_fdesc(dbm));
259 }
260
261 if (!dbm) {
262 if (mode == -1) return Qnil;
263
264 if (gdbm_errno == GDBM_FILE_OPEN_ERROR ||
265 gdbm_errno == GDBM_CANT_BE_READER ||
266 gdbm_errno == GDBM_CANT_BE_WRITER)
267 rb_sys_fail_str(file);
268 else
269 rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
270 }
271
272 if (dbmp->di_dbm)
273 gdbm_close(dbmp->di_dbm);
274 dbmp->di_dbm = dbm;
275 dbmp->di_size = -1;
276
277 return obj;
278}
279
280/*
281 * call-seq:
282 * GDBM.open(filename, mode = 0666, flags = nil)
283 * GDBM.open(filename, mode = 0666, flags = nil) { |gdbm| ... }
284 *
285 * If called without a block, this is synonymous to GDBM::new.
286 * If a block is given, the new GDBM instance will be passed to the block
287 * as a parameter, and the corresponding database file will be closed
288 * after the execution of the block code has been finished.
289 *
290 * Example for an open call with a block:
291 *
292 * require 'gdbm'
293 * GDBM.open("fruitstore.db") do |gdbm|
294 * gdbm.each_pair do |key, value|
295 * print "#{key}: #{value}\n"
296 * end
297 * end
298 */
299static VALUE
300fgdbm_s_open(int argc, VALUE *argv, VALUE klass)
301{
302 VALUE obj = fgdbm_s_alloc(klass);
303
304 if (NIL_P(fgdbm_initialize(argc, argv, obj))) {
305 return Qnil;
306 }
307
308 if (rb_block_given_p()) {
309 return rb_ensure(rb_yield, obj, fgdbm_close, obj);
310 }
311
312 return obj;
313}
314
315static VALUE
316rb_gdbm_fetch(GDBM_FILE dbm, datum key)
317{
318 datum val;
319 VALUE str;
320
321 val = gdbm_fetch(dbm, key);
322 if (val.dptr == 0)
323 return Qnil;
324
325 str = rb_str_new(val.dptr, val.dsize);
326 free(val.dptr);
327 return str;
328}
329
330static VALUE
331rb_gdbm_fetch2(GDBM_FILE dbm, VALUE keystr)
332{
333 datum key;
334 long len;
335
336 ExportStringValue(keystr);
337 len = RSTRING_LEN(keystr);
338 if (TOO_LONG(len)) return Qnil;
339 key.dptr = RSTRING_PTR(keystr);
340 key.dsize = (int)len;
341
342 return rb_gdbm_fetch(dbm, key);
343}
344
345static VALUE
346rb_gdbm_fetch3(VALUE obj, VALUE keystr)
347{
348 struct dbmdata *dbmp;
349 GDBM_FILE dbm;
350
351 GetDBM2(obj, dbmp, dbm);
352 return rb_gdbm_fetch2(dbm, keystr);
353}
354
355static VALUE
356rb_gdbm_firstkey(GDBM_FILE dbm)
357{
358 datum key;
359 VALUE str;
360
361 key = gdbm_firstkey(dbm);
362 if (key.dptr == 0)
363 return Qnil;
364
365 str = rb_str_new(key.dptr, key.dsize);
366 free(key.dptr);
367 return str;
368}
369
370static VALUE
371rb_gdbm_nextkey(GDBM_FILE dbm, VALUE keystr)
372{
373 datum key, key2;
374 VALUE str;
375 long len;
376
377 len = RSTRING_LEN(keystr);
378 if (TOO_LONG(len)) return Qnil;
379 key.dptr = RSTRING_PTR(keystr);
380 key.dsize = (int)len;
381 key2 = gdbm_nextkey(dbm, key);
382 if (key2.dptr == 0)
383 return Qnil;
384
385 str = rb_str_new(key2.dptr, key2.dsize);
386 free(key2.dptr);
387 return str;
388}
389
390static VALUE
391fgdbm_fetch(VALUE obj, VALUE keystr, VALUE ifnone)
392{
393 VALUE valstr;
394
395 valstr = rb_gdbm_fetch3(obj, keystr);
396 if (NIL_P(valstr)) {
397 if (ifnone == Qnil && rb_block_given_p())
398 return rb_yield(keystr);
399 return ifnone;
400 }
401 return valstr;
402}
403
404/*
405 * call-seq:
406 * gdbm[key] -> value
407 *
408 * Retrieves the _value_ corresponding to _key_.
409 */
410static VALUE
411fgdbm_aref(VALUE obj, VALUE keystr)
412{
413 return rb_gdbm_fetch3(obj, keystr);
414}
415
416/*
417 * call-seq:
418 * gdbm.fetch(key [, default]) -> value
419 *
420 * Retrieves the _value_ corresponding to _key_. If there is no value
421 * associated with _key_, _default_ will be returned instead.
422 */
423static VALUE
424fgdbm_fetch_m(int argc, VALUE *argv, VALUE obj)
425{
426 VALUE keystr, valstr, ifnone;
427
428 rb_scan_args(argc, argv, "11", &keystr, &ifnone);
429 valstr = fgdbm_fetch(obj, keystr, ifnone);
430 if (argc == 1 && !rb_block_given_p() && NIL_P(valstr))
431 rb_raise(rb_eIndexError, "key not found");
432
433 return valstr;
434}
435
436/*
437 * call-seq:
438 * gdbm.key(value) -> key
439 *
440 * Returns the _key_ for a given _value_. If several keys may map to the
441 * same value, the key that is found first will be returned.
442 */
443static VALUE
444fgdbm_key(VALUE obj, VALUE valstr)
445{
446 struct dbmdata *dbmp;
447 GDBM_FILE dbm;
448 VALUE keystr, valstr2;
449
450 ExportStringValue(valstr);
451 GetDBM2(obj, dbmp, dbm);
452 for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
453 keystr = rb_gdbm_nextkey(dbm, keystr)) {
454
455 valstr2 = rb_gdbm_fetch2(dbm, keystr);
456 if (!NIL_P(valstr2) &&
457 (int)RSTRING_LEN(valstr) == (int)RSTRING_LEN(valstr2) &&
458 memcmp(RSTRING_PTR(valstr), RSTRING_PTR(valstr2),
459 (int)RSTRING_LEN(valstr)) == 0) {
460 return keystr;
461 }
462 }
463 return Qnil;
464}
465
466/* :nodoc: */
467static VALUE
468fgdbm_index(VALUE obj, VALUE value)
469{
470 rb_warn("GDBM#index is deprecated; use GDBM#key");
471 return fgdbm_key(obj, value);
472}
473
474/*
475 * call-seq:
476 * gdbm.select { |key, value| block } -> array
477 *
478 * Returns a new array of all key-value pairs of the database for which _block_
479 * evaluates to true.
480 */
481static VALUE
482fgdbm_select(VALUE obj)
483{
484 VALUE new = rb_ary_new();
485 GDBM_FILE dbm;
486 struct dbmdata *dbmp;
487 VALUE keystr;
488
489 GetDBM2(obj, dbmp, dbm);
490 for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
491 keystr = rb_gdbm_nextkey(dbm, keystr)) {
492 VALUE assoc = rb_assoc_new(keystr, rb_gdbm_fetch2(dbm, keystr));
493 VALUE v = rb_yield(assoc);
494
495 if (RTEST(v)) {
496 rb_ary_push(new, assoc);
497 }
498 GetDBM2(obj, dbmp, dbm);
499 }
500
501 return new;
502}
503
504/*
505 * call-seq:
506 * gdbm.values_at(key, ...) -> array
507 *
508 * Returns an array of the values associated with each specified _key_.
509 */
510static VALUE
511fgdbm_values_at(int argc, VALUE *argv, VALUE obj)
512{
513 VALUE new = rb_ary_new2(argc);
514 int i;
515
516 for (i=0; i<argc; i++) {
517 rb_ary_push(new, rb_gdbm_fetch3(obj, argv[i]));
518 }
519
520 return new;
521}
522
523static void
524rb_gdbm_modify(VALUE obj)
525{
526 if (OBJ_FROZEN(obj)) rb_error_frozen("GDBM");
527}
528
529static VALUE
530rb_gdbm_delete(VALUE obj, VALUE keystr)
531{
532 datum key;
533 struct dbmdata *dbmp;
534 GDBM_FILE dbm;
535 long len;
536
537 rb_gdbm_modify(obj);
538 ExportStringValue(keystr);
539 len = RSTRING_LEN(keystr);
540 if (TOO_LONG(len)) return Qnil;
541 key.dptr = RSTRING_PTR(keystr);
542 key.dsize = (int)len;
543
544 GetDBM2(obj, dbmp, dbm);
545 if (!gdbm_exists(dbm, key)) {
546 return Qnil;
547 }
548
549 if (gdbm_delete(dbm, key)) {
550 dbmp->di_size = -1;
551 rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
552 }
553 else if (dbmp->di_size >= 0) {
554 dbmp->di_size--;
555 }
556 return obj;
557}
558
559/*
560 * call-seq:
561 * gdbm.delete(key) -> value or nil
562 *
563 * Removes the key-value-pair with the specified _key_ from this database and
564 * returns the corresponding _value_. Returns nil if the database is empty.
565 */
566static VALUE
567fgdbm_delete(VALUE obj, VALUE keystr)
568{
569 VALUE valstr;
570
571 valstr = fgdbm_fetch(obj, keystr, Qnil);
572 rb_gdbm_delete(obj, keystr);
573 return valstr;
574}
575
576/*
577 * call-seq:
578 * gdbm.shift -> (key, value) or nil
579 *
580 * Removes a key-value-pair from this database and returns it as a
581 * two-item array [ _key_, _value_ ]. Returns nil if the database is empty.
582 */
583static VALUE
584fgdbm_shift(VALUE obj)
585{
586 struct dbmdata *dbmp;
587 GDBM_FILE dbm;
588 VALUE keystr, valstr;
589
590 rb_gdbm_modify(obj);
591 GetDBM2(obj, dbmp, dbm);
592 keystr = rb_gdbm_firstkey(dbm);
593 if (NIL_P(keystr)) return Qnil;
594 valstr = rb_gdbm_fetch2(dbm, keystr);
595 rb_gdbm_delete(obj, keystr);
596
597 return rb_assoc_new(keystr, valstr);
598}
599
600/*
601 * call-seq:
602 * gdbm.delete_if { |key, value| block } -> gdbm
603 * gdbm.reject! { |key, value| block } -> gdbm
604 *
605 * Deletes every key-value pair from _gdbm_ for which _block_ evaluates to true.
606 */
607static VALUE
608fgdbm_delete_if(VALUE obj)
609{
610 struct dbmdata *dbmp;
611 GDBM_FILE dbm;
612 VALUE keystr, valstr;
613 VALUE ret, ary = rb_ary_tmp_new(0);
614 long i;
615 int status = 0, n;
616
617 rb_gdbm_modify(obj);
618 GetDBM2(obj, dbmp, dbm);
619 n = dbmp->di_size;
620 dbmp->di_size = -1;
621
622 for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
623 keystr = rb_gdbm_nextkey(dbm, keystr)) {
624
625 OBJ_FREEZE(keystr);
626 valstr = rb_gdbm_fetch2(dbm, keystr);
627 ret = rb_protect(rb_yield, rb_assoc_new(rb_str_dup(keystr), valstr), &status);
628 if (status != 0) break;
629 if (RTEST(ret)) rb_ary_push(ary, keystr);
630 GetDBM2(obj, dbmp, dbm);
631 }
632
633 for (i = 0; i < RARRAY_LEN(ary); i++)
634 rb_gdbm_delete(obj, RARRAY_AREF(ary, i));
635 if (status) rb_jump_tag(status);
636 if (n > 0) dbmp->di_size = n - (int)RARRAY_LEN(ary);
637 rb_ary_clear(ary);
638
639 return obj;
640}
641
642/*
643 * call-seq:
644 * gdbm.clear -> gdbm
645 *
646 * Removes all the key-value pairs within _gdbm_.
647 */
648static VALUE
649fgdbm_clear(VALUE obj)
650{
651 datum key, nextkey;
652 struct dbmdata *dbmp;
653 GDBM_FILE dbm;
654
655 rb_gdbm_modify(obj);
656 GetDBM2(obj, dbmp, dbm);
657 dbmp->di_size = -1;
658
659#if 0
660 while (key = gdbm_firstkey(dbm), key.dptr) {
661 if (gdbm_delete(dbm, key)) {
662 free(key.dptr);
663 rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
664 }
665 free(key.dptr);
666 }
667#else
668 while (key = gdbm_firstkey(dbm), key.dptr) {
669 for (; key.dptr; key = nextkey) {
670 nextkey = gdbm_nextkey(dbm, key);
671 if (gdbm_delete(dbm, key)) {
672 free(key.dptr);
673 if (nextkey.dptr) free(nextkey.dptr);
674 rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
675 }
676 free(key.dptr);
677 }
678 }
679#endif
680 dbmp->di_size = 0;
681
682 return obj;
683}
684
685/*
686 * call-seq:
687 * gdbm.invert -> hash
688 *
689 * Returns a hash created by using _gdbm_'s values as keys, and the keys
690 * as values.
691 */
692static VALUE
693fgdbm_invert(VALUE obj)
694{
695 struct dbmdata *dbmp;
696 GDBM_FILE dbm;
697 VALUE keystr, valstr;
698 VALUE hash = rb_hash_new();
699
700 GetDBM2(obj, dbmp, dbm);
701 for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
702 keystr = rb_gdbm_nextkey(dbm, keystr)) {
703 valstr = rb_gdbm_fetch2(dbm, keystr);
704
705 rb_hash_aset(hash, valstr, keystr);
706 }
707 return hash;
708}
709
710/*
711 * call-seq:
712 * gdbm[key]= value -> value
713 * gdbm.store(key, value) -> value
714 *
715 * Associates the value _value_ with the specified _key_.
716 */
717static VALUE
718fgdbm_store(VALUE obj, VALUE keystr, VALUE valstr)
719{
720 datum key, val;
721 struct dbmdata *dbmp;
722 GDBM_FILE dbm;
723
724 rb_gdbm_modify(obj);
725 ExportStringValue(keystr);
726 ExportStringValue(valstr);
727
728 key.dptr = RSTRING_PTR(keystr);
729 key.dsize = RSTRING_LENINT(keystr);
730
731 val.dptr = RSTRING_PTR(valstr);
732 val.dsize = RSTRING_LENINT(valstr);
733
734 GetDBM2(obj, dbmp, dbm);
735 dbmp->di_size = -1;
736 if (gdbm_store(dbm, key, val, GDBM_REPLACE)) {
737 if (errno == EPERM) rb_sys_fail(0);
738 rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
739 }
740
741 return valstr;
742}
743
744static VALUE
745update_i(RB_BLOCK_CALL_FUNC_ARGLIST(pair, dbm))
746{
747 const VALUE *ptr;
748 Check_Type(pair, T_ARRAY);
749 if (RARRAY_LEN(pair) < 2) {
750 rb_raise(rb_eArgError, "pair must be [key, value]");
751 }
752 ptr = RARRAY_CONST_PTR(pair);
753 fgdbm_store(dbm, ptr[0], ptr[1]);
754 return Qnil;
755}
756
757/*
758 * call-seq:
759 * gdbm.update(other) -> gdbm
760 *
761 * Adds the key-value pairs of _other_ to _gdbm_, overwriting entries with
762 * duplicate keys with those from _other_. _other_ must have an each_pair
763 * method.
764 */
765static VALUE
766fgdbm_update(VALUE obj, VALUE other)
767{
768 rb_block_call(other, rb_intern("each_pair"), 0, 0, update_i, obj);
769 return obj;
770}
771
772/*
773 * call-seq:
774 * gdbm.replace(other) -> gdbm
775 *
776 * Replaces the content of _gdbm_ with the key-value pairs of _other_.
777 * _other_ must have an each_pair method.
778 */
779static VALUE
780fgdbm_replace(VALUE obj, VALUE other)
781{
782 fgdbm_clear(obj);
783 rb_block_call(other, rb_intern("each_pair"), 0, 0, update_i, obj);
784 return obj;
785}
786
787/*
788 * call-seq:
789 * gdbm.length -> fixnum
790 * gdbm.size -> fixnum
791 *
792 * Returns the number of key-value pairs in this database.
793 */
794static VALUE
795fgdbm_length(VALUE obj)
796{
797 datum key, nextkey;
798 struct dbmdata *dbmp;
799 GDBM_FILE dbm;
800 int i = 0;
801
802 GetDBM2(obj, dbmp, dbm);
803 if (dbmp->di_size > 0) return INT2FIX(dbmp->di_size);
804
805 for (key = gdbm_firstkey(dbm); key.dptr; key = nextkey) {
806 nextkey = gdbm_nextkey(dbm, key);
807 free(key.dptr);
808 i++;
809 }
810 dbmp->di_size = i;
811
812 return INT2FIX(i);
813}
814
815/*
816 * call-seq:
817 * gdbm.empty? -> true or false
818 *
819 * Returns true if the database is empty.
820 */
821static VALUE
822fgdbm_empty_p(VALUE obj)
823{
824 datum key;
825 struct dbmdata *dbmp;
826 GDBM_FILE dbm;
827
828 GetDBM(obj, dbmp);
829 if (dbmp->di_size < 0) {
830 dbm = dbmp->di_dbm;
831
832 key = gdbm_firstkey(dbm);
833 if (key.dptr) {
834 free(key.dptr);
835 return Qfalse;
836 }
837 return Qtrue;
838 }
839
840 if (dbmp->di_size == 0) return Qtrue;
841 return Qfalse;
842}
843
844/*
845 * call-seq:
846 * gdbm.each_value { |value| block } -> gdbm
847 *
848 * Executes _block_ for each key in the database, passing the corresponding
849 * _value_ as a parameter.
850 */
851static VALUE
852fgdbm_each_value(VALUE obj)
853{
854 struct dbmdata *dbmp;
855 GDBM_FILE dbm;
856 VALUE keystr;
857
858 RETURN_ENUMERATOR(obj, 0, 0);
859
860 GetDBM2(obj, dbmp, dbm);
861 for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
862 keystr = rb_gdbm_nextkey(dbm, keystr)) {
863
864 rb_yield(rb_gdbm_fetch2(dbm, keystr));
865 GetDBM2(obj, dbmp, dbm);
866 }
867 return obj;
868}
869
870/*
871 * call-seq:
872 * gdbm.each_key { |key| block } -> gdbm
873 *
874 * Executes _block_ for each key in the database, passing the
875 * _key_ as a parameter.
876 */
877static VALUE
878fgdbm_each_key(VALUE obj)
879{
880 struct dbmdata *dbmp;
881 GDBM_FILE dbm;
882 VALUE keystr;
883
884 RETURN_ENUMERATOR(obj, 0, 0);
885
886 GetDBM2(obj, dbmp, dbm);
887 for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
888 keystr = rb_gdbm_nextkey(dbm, keystr)) {
889
890 rb_yield(keystr);
891 GetDBM2(obj, dbmp, dbm);
892 }
893 return obj;
894}
895
896/*
897 * call-seq:
898 * gdbm.each_pair { |key, value| block } -> gdbm
899 *
900 * Executes _block_ for each key in the database, passing the _key_ and the
901 * corresponding _value_ as a parameter.
902 */
903static VALUE
904fgdbm_each_pair(VALUE obj)
905{
906 GDBM_FILE dbm;
907 struct dbmdata *dbmp;
908 VALUE keystr;
909
910 RETURN_ENUMERATOR(obj, 0, 0);
911
912 GetDBM2(obj, dbmp, dbm);
913 for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
914 keystr = rb_gdbm_nextkey(dbm, keystr)) {
915
916 rb_yield(rb_assoc_new(keystr, rb_gdbm_fetch2(dbm, keystr)));
917 GetDBM2(obj, dbmp, dbm);
918 }
919
920 return obj;
921}
922
923/*
924 * call-seq:
925 * gdbm.keys -> array
926 *
927 * Returns an array of all keys of this database.
928 */
929static VALUE
930fgdbm_keys(VALUE obj)
931{
932 struct dbmdata *dbmp;
933 GDBM_FILE dbm;
934 VALUE keystr, ary;
935
936 GetDBM2(obj, dbmp, dbm);
937 ary = rb_ary_new();
938 for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
939 keystr = rb_gdbm_nextkey(dbm, keystr)) {
940
941 rb_ary_push(ary, keystr);
942 }
943
944 return ary;
945}
946
947/*
948 * call-seq:
949 * gdbm.values -> array
950 *
951 * Returns an array of all values of this database.
952 */
953static VALUE
954fgdbm_values(VALUE obj)
955{
956 datum key, nextkey;
957 struct dbmdata *dbmp;
958 GDBM_FILE dbm;
959 VALUE valstr, ary;
960
961 GetDBM2(obj, dbmp, dbm);
962 ary = rb_ary_new();
963 for (key = gdbm_firstkey(dbm); key.dptr; key = nextkey) {
964 nextkey = gdbm_nextkey(dbm, key);
965 valstr = rb_gdbm_fetch(dbm, key);
966 free(key.dptr);
967 rb_ary_push(ary, valstr);
968 }
969
970 return ary;
971}
972
973/*
974 * call-seq:
975 * gdbm.include?(k) -> true or false
976 * gdbm.has_key?(k) -> true or false
977 * gdbm.member?(k) -> true or false
978 * gdbm.key?(k) -> true or false
979 *
980 * Returns true if the given key _k_ exists within the database.
981 * Returns false otherwise.
982 */
983static VALUE
984fgdbm_has_key(VALUE obj, VALUE keystr)
985{
986 datum key;
987 struct dbmdata *dbmp;
988 GDBM_FILE dbm;
989 long len;
990
991 ExportStringValue(keystr);
992 len = RSTRING_LENINT(keystr);
993 if (TOO_LONG(len)) return Qfalse;
994 key.dptr = RSTRING_PTR(keystr);
995 key.dsize = (int)len;
996
997 GetDBM2(obj, dbmp, dbm);
998 if (gdbm_exists(dbm, key))
999 return Qtrue;
1000 return Qfalse;
1001}
1002
1003/*
1004 * call-seq:
1005 * gdbm.has_value?(v) -> true or false
1006 * gdbm.value?(v) -> true or false
1007 *
1008 * Returns true if the given value _v_ exists within the database.
1009 * Returns false otherwise.
1010 */
1011static VALUE
1012fgdbm_has_value(VALUE obj, VALUE valstr)
1013{
1014 struct dbmdata *dbmp;
1015 GDBM_FILE dbm;
1016 VALUE keystr, valstr2;
1017
1018 ExportStringValue(valstr);
1019 GetDBM2(obj, dbmp, dbm);
1020 for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
1021 keystr = rb_gdbm_nextkey(dbm, keystr)) {
1022
1023 valstr2 = rb_gdbm_fetch2(dbm, keystr);
1024
1025 if (!NIL_P(valstr2) &&
1026 (int)RSTRING_LEN(valstr) == (int)RSTRING_LEN(valstr2) &&
1027 memcmp(RSTRING_PTR(valstr), RSTRING_PTR(valstr2),
1028 (int)RSTRING_LEN(valstr)) == 0) {
1029 return Qtrue;
1030 }
1031 }
1032 return Qfalse;
1033}
1034
1035/*
1036 * call-seq:
1037 * gdbm.to_a -> array
1038 *
1039 * Returns an array of all key-value pairs contained in the database.
1040 */
1041static VALUE
1042fgdbm_to_a(VALUE obj)
1043{
1044 struct dbmdata *dbmp;
1045 GDBM_FILE dbm;
1046 VALUE keystr, ary;
1047
1048 GetDBM2(obj, dbmp, dbm);
1049 ary = rb_ary_new();
1050 for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
1051 keystr = rb_gdbm_nextkey(dbm, keystr)) {
1052
1053 rb_ary_push(ary, rb_assoc_new(keystr, rb_gdbm_fetch2(dbm, keystr)));
1054 }
1055
1056 return ary;
1057}
1058
1059/*
1060 * call-seq:
1061 * gdbm.reorganize -> gdbm
1062 *
1063 * Reorganizes the database file. This operation removes reserved space of
1064 * elements that have already been deleted. It is only useful after a lot of
1065 * deletions in the database.
1066 */
1067static VALUE
1068fgdbm_reorganize(VALUE obj)
1069{
1070 struct dbmdata *dbmp;
1071 GDBM_FILE dbm;
1072
1073 rb_gdbm_modify(obj);
1074 GetDBM2(obj, dbmp, dbm);
1075 gdbm_reorganize(dbm);
1076 rb_fd_fix_cloexec(gdbm_fdesc(dbm));
1077 return obj;
1078}
1079
1080/*
1081 * call-seq:
1082 * gdbm.sync -> gdbm
1083 *
1084 * Unless the _gdbm_ object has been opened with the *SYNC* flag, it is not
1085 * guaranteed that database modification operations are immediately applied to
1086 * the database file. This method ensures that all recent modifications
1087 * to the database are written to the file. Blocks until all writing operations
1088 * to the disk have been finished.
1089 */
1090static VALUE
1091fgdbm_sync(VALUE obj)
1092{
1093 struct dbmdata *dbmp;
1094 GDBM_FILE dbm;
1095
1096 rb_gdbm_modify(obj);
1097 GetDBM2(obj, dbmp, dbm);
1098 gdbm_sync(dbm);
1099 return obj;
1100}
1101
1102/*
1103 * call-seq:
1104 * gdbm.cachesize = size -> size
1105 *
1106 * Sets the size of the internal bucket cache to _size_.
1107 */
1108static VALUE
1109fgdbm_set_cachesize(VALUE obj, VALUE val)
1110{
1111 struct dbmdata *dbmp;
1112 GDBM_FILE dbm;
1113 int optval;
1114
1115 GetDBM2(obj, dbmp, dbm);
1116 optval = FIX2INT(val);
1117 if (gdbm_setopt(dbm, GDBM_CACHESIZE, &optval, sizeof(optval)) == -1) {
1118 rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
1119 }
1120 return val;
1121}
1122
1123/*
1124 * call-seq:
1125 * gdbm.fastmode = boolean -> boolean
1126 *
1127 * Turns the database's fast mode on or off. If fast mode is turned on, gdbm
1128 * does not wait for writes to be flushed to the disk before continuing.
1129 *
1130 * This option is obsolete for gdbm >= 1.8 since fast mode is turned on by
1131 * default. See also: #syncmode=
1132 */
1133static VALUE
1134fgdbm_set_fastmode(VALUE obj, VALUE val)
1135{
1136 struct dbmdata *dbmp;
1137 GDBM_FILE dbm;
1138 int optval;
1139
1140 GetDBM2(obj, dbmp, dbm);
1141 optval = 0;
1142 if (RTEST(val))
1143 optval = 1;
1144
1145 if (gdbm_setopt(dbm, GDBM_FASTMODE, &optval, sizeof(optval)) == -1) {
1146 rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
1147 }
1148 return val;
1149}
1150
1151/*
1152 * call-seq:
1153 * gdbm.syncmode = boolean -> boolean
1154 *
1155 * Turns the database's synchronization mode on or off. If the synchronization
1156 * mode is turned on, the database's in-memory state will be synchronized to
1157 * disk after every database modification operation. If the synchronization
1158 * mode is turned off, GDBM does not wait for writes to be flushed to the disk
1159 * before continuing.
1160 *
1161 * This option is only available for gdbm >= 1.8 where syncmode is turned off
1162 * by default. See also: #fastmode=
1163 */
1164static VALUE
1165fgdbm_set_syncmode(VALUE obj, VALUE val)
1166{
1167#if !defined(GDBM_SYNCMODE)
1168 fgdbm_set_fastmode(obj, RTEST(val) ? Qfalse : Qtrue);
1169 return val;
1170#else
1171 struct dbmdata *dbmp;
1172 GDBM_FILE dbm;
1173 int optval;
1174
1175 GetDBM2(obj, dbmp, dbm);
1176 optval = 0;
1177 if (RTEST(val))
1178 optval = 1;
1179
1180 if (gdbm_setopt(dbm, GDBM_FASTMODE, &optval, sizeof(optval)) == -1) {
1181 rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
1182 }
1183 return val;
1184#endif
1185}
1186
1187/*
1188 * call-seq:
1189 * gdbm.to_hash -> hash
1190 *
1191 * Returns a hash of all key-value pairs contained in the database.
1192 */
1193static VALUE
1194fgdbm_to_hash(VALUE obj)
1195{
1196 struct dbmdata *dbmp;
1197 GDBM_FILE dbm;
1198 VALUE keystr, hash;
1199
1200 GetDBM2(obj, dbmp, dbm);
1201 hash = rb_hash_new();
1202 for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
1203 keystr = rb_gdbm_nextkey(dbm, keystr)) {
1204
1205 rb_hash_aset(hash, keystr, rb_gdbm_fetch2(dbm, keystr));
1206 }
1207
1208 return hash;
1209}
1210
1211/*
1212 * call-seq:
1213 * gdbm.reject { |key, value| block } -> hash
1214 *
1215 * Returns a hash copy of _gdbm_ where all key-value pairs from _gdbm_ for
1216 * which _block_ evaluates to true are removed. See also: #delete_if
1217 */
1218static VALUE
1219fgdbm_reject(VALUE obj)
1220{
1221 return rb_hash_delete_if(fgdbm_to_hash(obj));
1222}
1223
1224void
1226{
1227 rb_cGDBM = rb_define_class("GDBM", rb_cObject);
1228 rb_eGDBMError = rb_define_class("GDBMError", rb_eStandardError);
1229 rb_eGDBMFatalError = rb_define_class("GDBMFatalError", rb_eException);
1231
1232 rb_define_alloc_func(rb_cGDBM, fgdbm_s_alloc);
1233 rb_define_singleton_method(rb_cGDBM, "open", fgdbm_s_open, -1);
1234
1235 rb_define_method(rb_cGDBM, "initialize", fgdbm_initialize, -1);
1236 rb_define_method(rb_cGDBM, "close", fgdbm_close, 0);
1237 rb_define_method(rb_cGDBM, "closed?", fgdbm_closed, 0);
1238 rb_define_method(rb_cGDBM, "[]", fgdbm_aref, 1);
1239 rb_define_method(rb_cGDBM, "fetch", fgdbm_fetch_m, -1);
1240 rb_define_method(rb_cGDBM, "[]=", fgdbm_store, 2);
1241 rb_define_method(rb_cGDBM, "store", fgdbm_store, 2);
1242 rb_define_method(rb_cGDBM, "index", fgdbm_index, 1);
1243 rb_define_method(rb_cGDBM, "key", fgdbm_key, 1);
1244 rb_define_method(rb_cGDBM, "select", fgdbm_select, 0);
1245 rb_define_method(rb_cGDBM, "values_at", fgdbm_values_at, -1);
1246 rb_define_method(rb_cGDBM, "length", fgdbm_length, 0);
1247 rb_define_method(rb_cGDBM, "size", fgdbm_length, 0);
1248 rb_define_method(rb_cGDBM, "empty?", fgdbm_empty_p, 0);
1249 rb_define_method(rb_cGDBM, "each", fgdbm_each_pair, 0);
1250 rb_define_method(rb_cGDBM, "each_value", fgdbm_each_value, 0);
1251 rb_define_method(rb_cGDBM, "each_key", fgdbm_each_key, 0);
1252 rb_define_method(rb_cGDBM, "each_pair", fgdbm_each_pair, 0);
1253 rb_define_method(rb_cGDBM, "keys", fgdbm_keys, 0);
1254 rb_define_method(rb_cGDBM, "values", fgdbm_values, 0);
1255 rb_define_method(rb_cGDBM, "shift", fgdbm_shift, 0);
1256 rb_define_method(rb_cGDBM, "delete", fgdbm_delete, 1);
1257 rb_define_method(rb_cGDBM, "delete_if", fgdbm_delete_if, 0);
1258 rb_define_method(rb_cGDBM, "reject!", fgdbm_delete_if, 0);
1259 rb_define_method(rb_cGDBM, "reject", fgdbm_reject, 0);
1260 rb_define_method(rb_cGDBM, "clear", fgdbm_clear, 0);
1261 rb_define_method(rb_cGDBM, "invert", fgdbm_invert, 0);
1262 rb_define_method(rb_cGDBM, "update", fgdbm_update, 1);
1263 rb_define_method(rb_cGDBM, "replace", fgdbm_replace, 1);
1264 rb_define_method(rb_cGDBM, "reorganize", fgdbm_reorganize, 0);
1265 rb_define_method(rb_cGDBM, "sync", fgdbm_sync, 0);
1266 /* rb_define_method(rb_cGDBM, "setopt", fgdbm_setopt, 2); */
1267 rb_define_method(rb_cGDBM, "cachesize=", fgdbm_set_cachesize, 1);
1268 rb_define_method(rb_cGDBM, "fastmode=", fgdbm_set_fastmode, 1);
1269 rb_define_method(rb_cGDBM, "syncmode=", fgdbm_set_syncmode, 1);
1270
1271 rb_define_method(rb_cGDBM, "include?", fgdbm_has_key, 1);
1272 rb_define_method(rb_cGDBM, "has_key?", fgdbm_has_key, 1);
1273 rb_define_method(rb_cGDBM, "member?", fgdbm_has_key, 1);
1274 rb_define_method(rb_cGDBM, "has_value?", fgdbm_has_value, 1);
1275 rb_define_method(rb_cGDBM, "key?", fgdbm_has_key, 1);
1276 rb_define_method(rb_cGDBM, "value?", fgdbm_has_value, 1);
1277
1278 rb_define_method(rb_cGDBM, "to_a", fgdbm_to_a, 0);
1279 rb_define_method(rb_cGDBM, "to_hash", fgdbm_to_hash, 0);
1280
1281 /* flag for #new and #open: open database as a reader */
1282 rb_define_const(rb_cGDBM, "READER", INT2FIX(GDBM_READER|RUBY_GDBM_RW_BIT));
1283 /* flag for #new and #open: open database as a writer */
1284 rb_define_const(rb_cGDBM, "WRITER", INT2FIX(GDBM_WRITER|RUBY_GDBM_RW_BIT));
1285 /* flag for #new and #open: open database as a writer; if the database does not exist, create a new one */
1286 rb_define_const(rb_cGDBM, "WRCREAT", INT2FIX(GDBM_WRCREAT|RUBY_GDBM_RW_BIT));
1287 /* flag for #new and #open: open database as a writer; overwrite any existing databases */
1288 rb_define_const(rb_cGDBM, "NEWDB", INT2FIX(GDBM_NEWDB|RUBY_GDBM_RW_BIT));
1289
1290 /* flag for #new and #open. this flag is obsolete for gdbm >= 1.8 */
1291 rb_define_const(rb_cGDBM, "FAST", INT2FIX(GDBM_FAST));
1292 /* this flag is obsolete in gdbm 1.8.
1293 On gdbm 1.8, fast mode is default behavior. */
1294
1295 /* gdbm version 1.8 specific */
1296#if defined(GDBM_SYNC)
1297 /* flag for #new and #open. only for gdbm >= 1.8 */
1298 rb_define_const(rb_cGDBM, "SYNC", INT2FIX(GDBM_SYNC));
1299#endif
1300#if defined(GDBM_NOLOCK)
1301 /* flag for #new and #open */
1302 rb_define_const(rb_cGDBM, "NOLOCK", INT2FIX(GDBM_NOLOCK));
1303#endif
1304 /* version of the gdbm library*/
1305 rb_define_const(rb_cGDBM, "VERSION", rb_str_new2(gdbm_version));
1306}
int errno
struct RIMemo * ptr
Definition: debug.c:65
#define free(x)
Definition: dln.c:52
char str[HTML_ESCAPE_MAX_LEN+1]
Definition: escape.c:18
#define GetDBM2(obj, dbmp, dbm)
Definition: gdbm.c:112
void Init_gdbm(void)
Definition: gdbm.c:1225
NORETURN(static void rb_gdbm_fatal(const char *msg))
#define MY_FATAL_FUNC
Definition: gdbm.c:85
#define MY_BLOCK_SIZE
Definition: gdbm.c:84
#define RUBY_GDBM_RW_BIT
Definition: gdbm.c:82
#define GetDBM(obj, dbmp)
Definition: gdbm.c:107
#define TOO_LONG(n)
Definition: gdbm.c:79
void rb_include_module(VALUE, VALUE)
Definition: class.c:882
VALUE rb_define_class(const char *, VALUE)
Defines a top-level class.
Definition: class.c:662
int rb_block_given_p(void)
Determines if the current method is given a block.
Definition: eval.c:898
VALUE rb_cObject
Object class.
Definition: ruby.h:2012
VALUE rb_mEnumerable
Definition: enum.c:20
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2671
VALUE rb_eStandardError
Definition: error.c:921
void rb_error_frozen(const char *what)
Definition: error.c:2976
void rb_sys_fail_str(VALUE mesg)
Definition: error.c:2801
VALUE rb_protect(VALUE(*)(VALUE), VALUE, int *)
Protects a function call from potential global escapes from the function.
Definition: eval.c:1072
VALUE rb_eRuntimeError
Definition: error.c:922
void rb_warn(const char *fmt,...)
Definition: error.c:315
VALUE rb_eArgError
Definition: error.c:925
VALUE rb_eException
Definition: error.c:916
VALUE rb_eIndexError
Definition: error.c:926
VALUE rb_ensure(VALUE(*)(VALUE), VALUE, VALUE(*)(VALUE), VALUE)
An equivalent to ensure clause.
Definition: eval.c:1115
void rb_jump_tag(int tag)
Continues the exception caught by rb_protect() and rb_eval_string_protect().
Definition: eval.c:884
void rb_sys_fail(const char *mesg)
Definition: error.c:2795
#define RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg)
#define RARRAY_LEN(a)
#define rb_str_new2
int memcmp(const void *, const void *, size_t)
Definition: memcmp.c:7
#define RSTRING_LEN(str)
#define RTEST(v)
VALUE rb_assoc_new(VALUE, VALUE)
Definition: array.c:896
#define xfree
const VALUE VALUE obj
VALUE rb_hash_delete_if(VALUE)
Definition: hash.c:2493
#define RSTRING_PTR(str)
#define rb_str_new(str, len)
#define NIL_P(v)
#define RSTRING_LENINT(str)
const char size_t n
unsigned long VALUE
VALUE rb_ary_push(VALUE, VALUE)
Definition: array.c:1195
#define FilePathValue(v)
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
uint32_t i
__inline__ const void *__restrict__ size_t len
#define OBJ_FROZEN(x)
#define OBJ_FREEZE(x)
#define ExportStringValue(v)
void rb_define_const(VALUE, const char *, VALUE)
Definition: variable.c:2891
#define NUM2INT(x)
void rb_define_singleton_method(VALUE, const char *, VALUE(*)(), int)
#define RUBY_TYPED_FREE_IMMEDIATELY
#define TypedData_Get_Struct(obj, type, data_type, sval)
VALUE rb_ary_clear(VALUE)
Definition: array.c:3862
VALUE rb_ary_tmp_new(long)
Definition: array.c:768
#define FIX2INT(x)
int VALUE v
VALUE rb_ary_new(void)
Definition: array.c:723
#define rb_scan_args(argc, argvp, fmt,...)
#define rb_intern(str)
void rb_fd_fix_cloexec(int fd)
Definition: io.c:268
unsigned int size
#define Qtrue
#define Qnil
#define Qfalse
#define T_ARRAY
#define INT2FIX(i)
#define TypedData_Make_Struct(klass, type, data_type, sval)
const VALUE * argv
__inline__ int
#define RETURN_ENUMERATOR(obj, argc, argv)
#define Check_Type(v, t)
VALUE rb_hash_aset(VALUE, VALUE, VALUE)
Definition: hash.c:2852
VALUE rb_block_call(VALUE, ID, int, const VALUE *, rb_block_call_func_t, VALUE)
Definition: vm_eval.c:1470
#define EPERM
VALUE rb_str_dup(VALUE)
Definition: string.c:1516
VALUE rb_yield(VALUE)
Definition: vm_eval.c:1237
void rb_define_method(VALUE, const char *, VALUE(*)(), int)
#define rb_ary_new2
#define RARRAY_AREF(a, i)
VALUE rb_hash_new(void)
Definition: hash.c:1523
#define RARRAY_CONST_PTR(a)
Definition: sdbm.h:50
char * dptr
Definition: sdbm.h:51
int dsize
Definition: sdbm.h:52
Definition: dbm.c:37
GDBM_FILE di_dbm
Definition: gdbm.c:98
int di_size
Definition: gdbm.c:97
DBM * di_dbm
Definition: dbm.c:39