Ruby 2.7.0p0(2019-12-25revision647ee6f091eafcce70ffb75ddf7e121e192ab217)

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 */
74 static 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
87 NORETURN(static void rb_gdbm_fatal(const char *msg));
88 NORETURN(static void closed_dbm(void));
89
90 static void
91 rb_gdbm_fatal(const char *msg)
92 {
93 rb_raise(rb_eGDBMFatalError, "%s", msg);
94 }
95
96 struct dbmdata {
97 int di_size;
98 GDBM_FILE di_dbm;
99 };
100
101 static void
102 closed_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
117 static void
118 free_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
126 static size_t
127 memsize_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
136 static const rb_data_type_t dbm_type = {
137 "gdbm",
138 {0, free_dbm, memsize_dbm,},
139 0, 0,
140 RUBY_TYPED_FREE_IMMEDIATELY,
141 };
142
143 /*
144 * call-seq:
145 * gdbm.close -> nil
146 *
147 * Closes the associated database file.
148 */
149 static VALUE
150 fgdbm_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 */
167 static VALUE
168 fgdbm_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
179 static VALUE
180 fgdbm_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 */
210 static VALUE
211 fgdbm_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 */
299 static VALUE
300 fgdbm_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
315 static VALUE
316 rb_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
330 static VALUE
331 rb_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
345 static VALUE
346 rb_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
355 static VALUE
356 rb_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
370 static VALUE
371 rb_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
390 static VALUE
391 fgdbm_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 */
410 static VALUE
411 fgdbm_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 */
423 static VALUE
424 fgdbm_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 */
443 static VALUE
444 fgdbm_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: */
467 static VALUE
468 fgdbm_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 */
481 static VALUE
482 fgdbm_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 */
510 static VALUE
511 fgdbm_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
523 static void
524 rb_gdbm_modify(VALUE obj)
525 {
526 if (OBJ_FROZEN(obj)) rb_error_frozen("GDBM");
527 }
528
529 static VALUE
530 rb_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 */
566 static VALUE
567 fgdbm_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 */
583 static VALUE
584 fgdbm_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 */
607 static VALUE
608 fgdbm_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 */
648 static VALUE
649 fgdbm_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 */
692 static VALUE
693 fgdbm_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 */
717 static VALUE
718 fgdbm_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
744 static VALUE
745 update_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 */
765 static VALUE
766 fgdbm_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 */
779 static VALUE
780 fgdbm_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 */
794 static VALUE
795 fgdbm_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 */
821 static VALUE
822 fgdbm_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 */
851 static VALUE
852 fgdbm_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 */
877 static VALUE
878 fgdbm_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 */
903 static VALUE
904 fgdbm_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 */
929 static VALUE
930 fgdbm_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 */
953 static VALUE
954 fgdbm_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 */
983 static VALUE
984 fgdbm_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 */
1011 static VALUE
1012 fgdbm_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 */
1041 static VALUE
1042 fgdbm_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 */
1067 static VALUE
1068 fgdbm_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 */
1090 static VALUE
1091 fgdbm_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 */
1108 static VALUE
1109 fgdbm_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 */
1133 static VALUE
1134 fgdbm_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 */
1164 static VALUE
1165 fgdbm_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 */
1193 static VALUE
1194 fgdbm_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 */
1218 static VALUE
1219 fgdbm_reject(VALUE obj)
1220 {
1221 return rb_hash_delete_if(fgdbm_to_hash(obj));
1222 }
1223
1224 void
1225 Init_gdbm(void)
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);
1230 rb_include_module(rb_cGDBM, rb_mEnumerable);
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 }
rb_define_class
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition: class.c:649
TypedData_Make_Struct
#define TypedData_Make_Struct(klass, type, data_type, sval)
Definition: ruby.h:1244
Check_Type
#define Check_Type(v, t)
Definition: ruby.h:595
rb_include_module
void rb_include_module(VALUE klass, VALUE module)
Definition: class.c:869
rb_assoc_new
VALUE rb_assoc_new(VALUE car, VALUE cdr)
Definition: array.c:896
rb_str_new2
#define rb_str_new2
Definition: intern.h:903
GetDBM2
#define GetDBM2(obj, dbmp, dbm)
Definition: gdbm.c:112
FIX2INT
#define FIX2INT(x)
Definition: ruby.h:717
rb_hash_new
VALUE rb_hash_new(void)
Definition: hash.c:1501
rb_warn
void rb_warn(const char *fmt,...)
Definition: error.c:313
rb_block_given_p
int rb_block_given_p(void)
Determines if the current method is given a block.
Definition: eval.c:897
dbmdata::di_dbm
GDBM_FILE di_dbm
Definition: gdbm.c:98
rb_scan_args
#define rb_scan_args(argc, argvp, fmt,...)
Definition: rb_mjit_min_header-2.7.0.h:6372
INT2FIX
#define INT2FIX(i)
Definition: ruby.h:263
RSTRING_PTR
#define RSTRING_PTR(str)
Definition: ruby.h:1009
VALUE
unsigned long VALUE
Definition: ruby.h:102
rb_eArgError
VALUE rb_eArgError
Definition: error.c:923
MY_FATAL_FUNC
#define MY_FATAL_FUNC
Definition: gdbm.c:85
rb_intern
#define rb_intern(str)
datum::dptr
char * dptr
Definition: sdbm.h:51
RSTRING_LENINT
#define RSTRING_LENINT(str)
Definition: ruby.h:1017
int
__inline__ int
Definition: rb_mjit_min_header-2.7.0.h:2839
rb_fd_fix_cloexec
void rb_fd_fix_cloexec(int fd)
Definition: io.c:268
rb_str_dup
VALUE rb_str_dup(VALUE)
Definition: string.c:1516
rb_eIndexError
VALUE rb_eIndexError
Definition: error.c:924
MY_BLOCK_SIZE
#define MY_BLOCK_SIZE
Definition: gdbm.c:84
rb_define_singleton_method
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
Definition: class.c:1755
rb_define_method
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1551
ptr
struct RIMemo * ptr
Definition: debug.c:74
Qfalse
#define Qfalse
Definition: ruby.h:467
FilePathValue
#define FilePathValue(v)
Definition: ruby.h:624
OBJ_FREEZE
#define OBJ_FREEZE(x)
Definition: ruby.h:1377
ExportStringValue
#define ExportStringValue(v)
Definition: ruby.h:617
RB_BLOCK_CALL_FUNC_ARGLIST
#define RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg)
Definition: ruby.h:1964
rb_protect
VALUE rb_protect(VALUE(*proc)(VALUE), VALUE data, int *pstate)
Protects a function call from potential global escapes from the function.
Definition: eval.c:1071
v
int VALUE v
Definition: rb_mjit_min_header-2.7.0.h:12332
rb_error_frozen
void rb_error_frozen(const char *what)
Definition: error.c:2974
rb_raise
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2669
obj
const VALUE VALUE obj
Definition: rb_mjit_min_header-2.7.0.h:5742
rb_ary_tmp_new
VALUE rb_ary_tmp_new(long capa)
Definition: array.c:768
i
uint32_t i
Definition: rb_mjit_min_header-2.7.0.h:5464
RUBY_GDBM_RW_BIT
#define RUBY_GDBM_RW_BIT
Definition: gdbm.c:82
rb_jump_tag
void rb_jump_tag(int tag)
Continues the exception caught by rb_protect() and rb_eval_string_protect().
Definition: eval.c:883
GetDBM
#define GetDBM(obj, dbmp)
Definition: gdbm.c:107
rb_hash_delete_if
VALUE rb_hash_delete_if(VALUE hash)
Definition: hash.c:2420
rb_ary_push
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:1195
ruby.h
rb_sys_fail
void rb_sys_fail(const char *mesg)
Definition: error.c:2793
rb_eRuntimeError
VALUE rb_eRuntimeError
Definition: error.c:920
datum
Definition: sdbm.h:50
RETURN_ENUMERATOR
#define RETURN_ENUMERATOR(obj, argc, argv)
Definition: intern.h:279
RARRAY_AREF
#define RARRAY_AREF(a, i)
Definition: ruby.h:1101
size
int size
Definition: encoding.c:58
NORETURN
NORETURN(static void rb_gdbm_fatal(const char *msg))
memcmp
int memcmp(const void *s1, const void *s2, size_t len)
Definition: memcmp.c:7
key
key
Definition: openssl_missing.h:181
EPERM
#define EPERM
Definition: _sdbm.c:92
RARRAY_CONST_PTR
#define RARRAY_CONST_PTR(a)
Definition: ruby.h:1072
rb_ary_clear
VALUE rb_ary_clear(VALUE ary)
Definition: array.c:3862
RARRAY_LEN
#define RARRAY_LEN(a)
Definition: ruby.h:1070
Init_gdbm
void Init_gdbm(void)
Definition: gdbm.c:1225
rb_cObject
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:2010
rb_ary_new2
#define rb_ary_new2
Definition: intern.h:103
n
const char size_t n
Definition: rb_mjit_min_header-2.7.0.h:5456
TypedData_Get_Struct
#define TypedData_Get_Struct(obj, type, data_type, sval)
Definition: ruby.h:1252
T_ARRAY
#define T_ARRAY
Definition: ruby.h:530
argv
char ** argv
Definition: ruby.c:223
klass
VALUE klass
Definition: rb_mjit_min_header-2.7.0.h:13254
str
char str[HTML_ESCAPE_MAX_LEN+1]
Definition: escape.c:18
datum::dsize
int dsize
Definition: sdbm.h:52
RUBY_TYPED_FREE_IMMEDIATELY
#define RUBY_TYPED_FREE_IMMEDIATELY
Definition: ruby.h:1207
rb_hash_aset
VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val)
Definition: hash.c:2779
dbmdata::di_dbm
DBM * di_dbm
Definition: dbm.c:39
ruby::backward::cxxanyargs::rb_block_call
VALUE rb_block_call(VALUE q, ID w, int e, const VALUE *r, type *t, VALUE y)
Call a method with a block.
Definition: cxxanyargs.hpp:178
NIL_P
#define NIL_P(v)
Definition: ruby.h:482
argc
int argc
Definition: ruby.c:222
rb_sys_fail_str
void rb_sys_fail_str(VALUE mesg)
Definition: error.c:2799
rb_define_const
void rb_define_const(VALUE, const char *, VALUE)
Definition: variable.c:2880
dbmdata
Definition: dbm.c:37
free
#define free(x)
Definition: dln.c:52
rb_data_type_struct
Definition: ruby.h:1148
rb_eException
VALUE rb_eException
Definition: error.c:914
xfree
#define xfree
Definition: defines.h:216
rb_str_new
#define rb_str_new(str, len)
Definition: rb_mjit_min_header-2.7.0.h:6116
Qtrue
#define Qtrue
Definition: ruby.h:468
errno
int errno
OBJ_FROZEN
#define OBJ_FROZEN(x)
Definition: ruby.h:1375
len
uint8_t len
Definition: escape.c:17
dbmdata::di_size
int di_size
Definition: gdbm.c:97
rb_yield
VALUE rb_yield(VALUE)
Definition: vm_eval.c:1237
rb_ensure
VALUE rb_ensure(VALUE(*b_proc)(VALUE), VALUE data1, VALUE(*e_proc)(VALUE), VALUE data2)
An equivalent to ensure clause.
Definition: eval.c:1114
rb_ary_new
VALUE rb_ary_new(void)
Definition: array.c:723
NUM2INT
#define NUM2INT(x)
Definition: ruby.h:715
Qnil
#define Qnil
Definition: ruby.h:469
rb_mEnumerable
VALUE rb_mEnumerable
Definition: enum.c:20
rb_eStandardError
VALUE rb_eStandardError
Definition: error.c:919
RSTRING_LEN
#define RSTRING_LEN(str)
Definition: ruby.h:1005
rb_define_alloc_func
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
RTEST
#define RTEST(v)
Definition: ruby.h:481
TOO_LONG
#define TOO_LONG(n)
Definition: gdbm.c:79