DEFINITIONS
This source file includes following functions.
- rb_gdbm_fatal
- closed_dbm
- free_dbm
- fgdbm_close
- fgdbm_s_new
- fgdbm_initialize
- fgdbm_s_open
- rb_gdbm_fetch
- rb_gdbm_fetch2
- rb_gdbm_fetch3
- rb_gdbm_firstkey
- rb_gdbm_nextkey
- fgdbm_fetch
- fgdbm_aref
- fgdbm_fetch_m
- fgdbm_index
- fgdbm_indexes
- fgdbm_select
- rb_gdbm_delete
- fgdbm_delete
- fgdbm_shift
- fgdbm_delete_if
- fgdbm_clear
- fgdbm_invert
- each_pair
- update_i
- fgdbm_update
- fgdbm_replace
- fgdbm_store
- fgdbm_length
- fgdbm_empty_p
- fgdbm_each_value
- fgdbm_each_key
- fgdbm_each_pair
- fgdbm_keys
- fgdbm_values
- fgdbm_has_key
- fgdbm_has_value
- fgdbm_to_a
- fgdbm_reorganize
- fgdbm_sync
- fgdbm_set_cachesize
- fgdbm_set_fastmode
- fgdbm_set_syncmode
- fgdbm_to_hash
- fgdbm_reject
- Init_gdbm
1
2
3
4
5
6
7
8
9
10
11 #include "ruby.h"
12
13 #include <gdbm.h>
14 #include <fcntl.h>
15 #include <errno.h>
16
17 static VALUE rb_cGDBM, rb_eGDBMError, rb_eGDBMFatalError;
18
19 #define MY_BLOCK_SIZE (2048)
20 #define MY_FATAL_FUNC rb_gdbm_fatal
21 static void
22 rb_gdbm_fatal(msg)
23 char *msg;
24 {
25 rb_raise(rb_eGDBMFatalError, msg);
26 }
27
28 struct dbmdata {
29 int di_size;
30 GDBM_FILE di_dbm;
31 };
32
33 static void
34 closed_dbm()
35 {
36 rb_raise(rb_eRuntimeError, "closed GDBM 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 static void
46 free_dbm(dbmp)
47 struct dbmdata *dbmp;
48 {
49 if (dbmp) {
50 if (dbmp->di_dbm) gdbm_close(dbmp->di_dbm);
51 free(dbmp);
52 }
53 }
54
55 static VALUE
56 fgdbm_close(obj)
57 VALUE obj;
58 {
59 struct dbmdata *dbmp;
60
61 GetDBM(obj, dbmp);
62 gdbm_close(dbmp->di_dbm);
63 dbmp->di_dbm = 0;
64
65 return Qnil;
66 }
67
68 static VALUE
69 fgdbm_s_new(argc, argv, klass)
70 int argc;
71 VALUE *argv;
72 VALUE klass;
73 {
74 VALUE obj = Data_Wrap_Struct(klass, 0, free_dbm, 0);
75 rb_obj_call_init(obj, argc, argv);
76 return obj;
77 }
78
79 static VALUE
80 fgdbm_initialize(argc, argv, obj)
81 int argc;
82 VALUE *argv;
83 VALUE obj;
84 {
85 VALUE file, vmode, vflags;
86 GDBM_FILE dbm;
87 struct dbmdata *dbmp;
88 int mode, flags = 0;
89
90 if (rb_scan_args(argc, argv, "12", &file, &vmode, &vflags) == 1) {
91 mode = 0666;
92 }
93 else if (NIL_P(vmode)) {
94 mode = -1;
95 }
96 else {
97 mode = NUM2INT(vmode);
98 }
99
100 if (!NIL_P(vflags))
101 flags = NUM2INT(vflags);
102
103 SafeStringValue(file);
104
105 dbm = 0;
106 if (mode >= 0)
107 dbm = gdbm_open(RSTRING(file)->ptr, MY_BLOCK_SIZE,
108 GDBM_WRCREAT|flags, mode, MY_FATAL_FUNC);
109 if (!dbm)
110 dbm = gdbm_open(RSTRING(file)->ptr, MY_BLOCK_SIZE,
111 GDBM_WRITER|flags, 0, MY_FATAL_FUNC);
112 if (!dbm)
113 dbm = gdbm_open(RSTRING(file)->ptr, MY_BLOCK_SIZE,
114 GDBM_READER|flags, 0, MY_FATAL_FUNC);
115
116 if (!dbm) {
117 if (mode == -1) return Qnil;
118
119 if (gdbm_errno == GDBM_FILE_OPEN_ERROR ||
120 gdbm_errno == GDBM_CANT_BE_READER ||
121 gdbm_errno == GDBM_CANT_BE_WRITER)
122 rb_sys_fail(RSTRING(file)->ptr);
123 else
124 rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
125 }
126
127 dbmp = ALLOC(struct dbmdata);
128 DATA_PTR(obj) = dbmp;
129 dbmp->di_dbm = dbm;
130 dbmp->di_size = -1;
131
132 return obj;
133 }
134
135 static VALUE
136 fgdbm_s_open(argc, argv, klass)
137 int argc;
138 VALUE *argv;
139 VALUE klass;
140 {
141 VALUE obj = Data_Wrap_Struct(klass, 0, free_dbm, 0);
142
143 if (NIL_P(fgdbm_initialize(argc, argv, obj))) {
144 return Qnil;
145 }
146
147 if (rb_block_given_p()) {
148 return rb_ensure(rb_yield, obj, fgdbm_close, obj);
149 }
150
151 return obj;
152 }
153
154 static VALUE
155 rb_gdbm_fetch(dbm, key)
156 GDBM_FILE dbm;
157 datum key;
158 {
159 datum val;
160 VALUE str;
161
162 val = gdbm_fetch(dbm, key);
163 if (val.dptr == 0)
164 return Qnil;
165
166 str = rb_obj_alloc(rb_cString);
167 RSTRING(str)->len = val.dsize;
168 RSTRING(str)->aux.capa = val.dsize;
169 RSTRING(str)->ptr = REALLOC_N(val.dptr,char,val.dsize+1);
170 RSTRING(str)->ptr[val.dsize] = '\0';
171
172 OBJ_TAINT(str);
173 return (VALUE)str;
174 }
175
176 static VALUE
177 rb_gdbm_fetch2(dbm, keystr)
178 GDBM_FILE dbm;
179 VALUE keystr;
180 {
181 datum key;
182
183 StringValue(keystr);
184 key.dptr = RSTRING(keystr)->ptr;
185 key.dsize = RSTRING(keystr)->len;
186
187 return rb_gdbm_fetch(dbm, key);
188 }
189
190 static VALUE
191 rb_gdbm_fetch3(obj, keystr)
192 VALUE obj, keystr;
193 {
194 struct dbmdata *dbmp;
195 GDBM_FILE dbm;
196
197 GetDBM(obj, dbmp);
198 dbm = dbmp->di_dbm;
199 return rb_gdbm_fetch2(dbm, keystr);
200 }
201
202 static VALUE
203 rb_gdbm_firstkey(dbm)
204 GDBM_FILE dbm;
205 {
206 datum key;
207 VALUE str;
208
209 key = gdbm_firstkey(dbm);
210 if (key.dptr == 0)
211 return Qnil;
212
213 str = rb_obj_alloc(rb_cString);
214 RSTRING(str)->len = key.dsize;
215 RSTRING(str)->aux.capa = key.dsize;
216 RSTRING(str)->ptr = REALLOC_N(key.dptr,char,key.dsize+1);
217 RSTRING(str)->ptr[RSTRING(str)->len] = '\0';
218
219 OBJ_TAINT(str);
220 return str;
221 }
222
223 static VALUE
224 rb_gdbm_nextkey(dbm, keystr)
225 GDBM_FILE dbm;
226 VALUE keystr;
227 {
228 datum key, key2;
229 VALUE str;
230
231 key.dptr = RSTRING(keystr)->ptr;
232 key.dsize = RSTRING(keystr)->len;
233 key2 = gdbm_nextkey(dbm, key);
234 if (key2.dptr == 0)
235 return Qnil;
236
237 str = rb_obj_alloc(rb_cString);
238 RSTRING(str)->len = key2.dsize;
239 RSTRING(str)->aux.capa = key2.dsize;
240 RSTRING(str)->ptr = REALLOC_N(key2.dptr,char,key2.dsize+1);
241 RSTRING(str)->ptr[RSTRING(str)->len] = '\0';
242
243 OBJ_TAINT(str);
244 return str;
245 }
246
247 static VALUE
248 fgdbm_fetch(obj, keystr, ifnone)
249 VALUE obj, keystr, ifnone;
250 {
251 VALUE valstr;
252
253 valstr = rb_gdbm_fetch3(obj, keystr);
254 if (NIL_P(valstr)) {
255 if (ifnone == Qnil && rb_block_given_p())
256 return rb_yield(keystr);
257 return ifnone;
258 }
259 return valstr;
260 }
261
262 static VALUE
263 fgdbm_aref(obj, keystr)
264 VALUE obj, keystr;
265 {
266 return rb_gdbm_fetch3(obj, keystr);
267 }
268
269 static VALUE
270 fgdbm_fetch_m(argc, argv, obj)
271 int argc;
272 VALUE *argv;
273 VALUE obj;
274 {
275 VALUE keystr, valstr, ifnone;
276
277 rb_scan_args(argc, argv, "11", &keystr, &ifnone);
278 valstr = fgdbm_fetch(obj, keystr, ifnone);
279 if (argc == 1 && !rb_block_given_p() && NIL_P(valstr))
280 rb_raise(rb_eIndexError, "key not found");
281
282 return valstr;
283 }
284
285 static VALUE
286 fgdbm_index(obj, valstr)
287 VALUE obj, valstr;
288 {
289 struct dbmdata *dbmp;
290 GDBM_FILE dbm;
291 VALUE keystr, valstr2;
292
293 StringValue(valstr);
294 GetDBM(obj, dbmp);
295 dbm = dbmp->di_dbm;
296 for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
297 keystr = rb_gdbm_nextkey(dbm, keystr)) {
298
299 valstr2 = rb_gdbm_fetch2(dbm, keystr);
300 if (!NIL_P(valstr2) &&
301 RSTRING(valstr)->len == RSTRING(valstr2)->len &&
302 memcmp(RSTRING(valstr)->ptr, RSTRING(valstr2)->ptr,
303 RSTRING(valstr)->len) == 0) {
304 return keystr;
305 }
306 }
307 return Qnil;
308 }
309
310 static VALUE
311 fgdbm_indexes(argc, argv, obj)
312 int argc;
313 VALUE *argv;
314 VALUE obj;
315 {
316 VALUE new;
317 int i;
318
319 new = rb_ary_new2(argc);
320 for (i=0; i<argc; i++) {
321 rb_ary_push(new, rb_gdbm_fetch3(obj, argv[i]));
322 }
323
324 return new;
325 }
326
327 static VALUE
328 fgdbm_select(argc, argv, obj)
329 int argc;
330 VALUE *argv;
331 VALUE obj;
332 {
333 VALUE new = rb_ary_new2(argc);
334 int i;
335
336 if (rb_block_given_p()) {
337 GDBM_FILE dbm;
338 struct dbmdata *dbmp;
339 VALUE keystr;
340
341 if (argc > 0) {
342 rb_raise(rb_eArgError, "wrong number arguments(%d for 0)", argc);
343 }
344 GetDBM(obj, dbmp);
345 dbm = dbmp->di_dbm;
346
347 for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
348 keystr = rb_gdbm_nextkey(dbm, keystr)) {
349 VALUE assoc = rb_assoc_new(keystr, rb_gdbm_fetch2(dbm, keystr));
350
351 if (RTEST(rb_yield(assoc)))
352 rb_ary_push(new, assoc);
353 }
354 }
355 else {
356 for (i=0; i<argc; i++) {
357 rb_ary_push(new, rb_gdbm_fetch3(obj, argv[i]));
358 }
359 }
360
361 return new;
362 }
363
364 static VALUE
365 rb_gdbm_delete(obj, keystr)
366 VALUE obj, keystr;
367 {
368 datum key;
369 struct dbmdata *dbmp;
370 GDBM_FILE dbm;
371
372 rb_secure(4);
373 StringValue(keystr);
374 key.dptr = RSTRING(keystr)->ptr;
375 key.dsize = RSTRING(keystr)->len;
376
377 GetDBM(obj, dbmp);
378 dbm = dbmp->di_dbm;
379
380 if (!gdbm_exists(dbm, key)) {
381 return Qnil;
382 }
383
384 if (gdbm_delete(dbm, key)) {
385 dbmp->di_size = -1;
386 rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
387 }
388 else if (dbmp->di_size >= 0) {
389 dbmp->di_size--;
390 }
391 return obj;
392 }
393
394 static VALUE
395 fgdbm_delete(obj, keystr)
396 VALUE obj, keystr;
397 {
398 VALUE valstr;
399
400 valstr = fgdbm_fetch(obj, keystr, Qnil);
401 rb_gdbm_delete(obj, keystr);
402 return valstr;
403 }
404
405 static VALUE
406 fgdbm_shift(obj)
407 VALUE obj;
408 {
409 struct dbmdata *dbmp;
410 GDBM_FILE dbm;
411 VALUE keystr, valstr;
412
413 rb_secure(4);
414 GetDBM(obj, dbmp);
415 dbm = dbmp->di_dbm;
416
417 keystr = rb_gdbm_firstkey(dbm);
418 if (NIL_P(keystr)) return Qnil;
419 valstr = rb_gdbm_fetch2(dbm, keystr);
420 rb_gdbm_delete(obj, keystr);
421
422 return rb_assoc_new(keystr, valstr);
423 }
424
425 static VALUE
426 fgdbm_delete_if(obj)
427 VALUE obj;
428 {
429 struct dbmdata *dbmp;
430 GDBM_FILE dbm;
431 VALUE keystr, valstr;
432 VALUE ret, ary = rb_ary_new();
433 int i, status = 0, n;
434
435 rb_secure(4);
436 GetDBM(obj, dbmp);
437 dbm = dbmp->di_dbm;
438 n = dbmp->di_size;
439 dbmp->di_size = -1;
440
441 for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
442 keystr = rb_gdbm_nextkey(dbm, keystr)) {
443
444 valstr = rb_gdbm_fetch2(dbm, keystr);
445 ret = rb_protect(rb_yield, rb_assoc_new(keystr, valstr), &status);
446 if (status != 0) break;
447 if (RTEST(ret)) rb_ary_push(ary, keystr);
448 }
449
450 for (i = 0; i < RARRAY(ary)->len; i++)
451 rb_gdbm_delete(obj, RARRAY(ary)->ptr[i]);
452 if (status) rb_jump_tag(status);
453 if (n > 0) dbmp->di_size = n - RARRAY(ary)->len;
454
455 return obj;
456 }
457
458 static VALUE
459 fgdbm_clear(obj)
460 VALUE obj;
461 {
462 datum key, nextkey;
463 struct dbmdata *dbmp;
464 GDBM_FILE dbm;
465
466 rb_secure(4);
467 GetDBM(obj, dbmp);
468 dbm = dbmp->di_dbm;
469 dbmp->di_size = -1;
470
471 #if 0
472 while (key = gdbm_firstkey(dbm), key.dptr) {
473 if (gdbm_delete(dbm, key)) {
474 free(key.dptr);
475 rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
476 }
477 free(key.dptr);
478 }
479 #else
480 while (key = gdbm_firstkey(dbm), key.dptr) {
481 for (; key.dptr; key = nextkey) {
482 nextkey = gdbm_nextkey(dbm, key);
483 if (gdbm_delete(dbm, key)) {
484 free(key.dptr);
485 if (nextkey.dptr) free(nextkey.dptr);
486 rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
487 }
488 free(key.dptr);
489 }
490 }
491 #endif
492 dbmp->di_size = 0;
493
494 return obj;
495 }
496
497 static VALUE
498 fgdbm_invert(obj)
499 VALUE obj;
500 {
501 struct dbmdata *dbmp;
502 GDBM_FILE dbm;
503 VALUE keystr, valstr;
504 VALUE hash = rb_hash_new();
505
506 GetDBM(obj, dbmp);
507 dbm = dbmp->di_dbm;
508 for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
509 keystr = rb_gdbm_nextkey(dbm, keystr)) {
510 valstr = rb_gdbm_fetch2(dbm, keystr);
511
512 rb_hash_aset(hash, valstr, keystr);
513 }
514 return hash;
515 }
516
517 static VALUE
518 each_pair(obj)
519 VALUE obj;
520 {
521 return rb_funcall(obj, rb_intern("each_pair"), 0, 0);
522 }
523
524 static VALUE fgdbm_store _((VALUE,VALUE,VALUE));
525
526 static VALUE
527 update_i(pair, dbm)
528 VALUE pair, dbm;
529 {
530 Check_Type(pair, T_ARRAY);
531 if (RARRAY(pair)->len < 2) {
532 rb_raise(rb_eArgError, "pair must be [key, value]");
533 }
534 fgdbm_store(dbm, RARRAY(pair)->ptr[0], RARRAY(pair)->ptr[1]);
535 return Qnil;
536 }
537
538 static VALUE
539 fgdbm_update(obj, other)
540 VALUE obj, other;
541 {
542 rb_iterate(each_pair, other, update_i, obj);
543 return obj;
544 }
545
546 static VALUE
547 fgdbm_replace(obj, other)
548 VALUE obj, other;
549 {
550 fgdbm_clear(obj);
551 rb_iterate(each_pair, other, update_i, obj);
552 return obj;
553 }
554
555 static VALUE
556 fgdbm_store(obj, keystr, valstr)
557 VALUE obj, keystr, valstr;
558 {
559 datum key, val;
560 struct dbmdata *dbmp;
561 GDBM_FILE dbm;
562
563 rb_secure(4);
564 StringValue(keystr);
565 key.dptr = RSTRING(keystr)->ptr;
566 key.dsize = RSTRING(keystr)->len;
567
568 StringValue(valstr);
569 val.dptr = RSTRING(valstr)->ptr;
570 val.dsize = RSTRING(valstr)->len;
571
572 GetDBM(obj, dbmp);
573 dbmp->di_size = -1;
574 dbm = dbmp->di_dbm;
575 if (gdbm_store(dbm, key, val, GDBM_REPLACE)) {
576 if (errno == EPERM) rb_sys_fail(0);
577 rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
578 }
579
580 return valstr;
581 }
582
583 static VALUE
584 fgdbm_length(obj)
585 VALUE obj;
586 {
587 datum key, nextkey;
588 struct dbmdata *dbmp;
589 GDBM_FILE dbm;
590 int i = 0;
591
592 GetDBM(obj, dbmp);
593 if (dbmp->di_size > 0) return INT2FIX(dbmp->di_size);
594 dbm = dbmp->di_dbm;
595
596 for (key = gdbm_firstkey(dbm); key.dptr; key = nextkey) {
597 nextkey = gdbm_nextkey(dbm, key);
598 free(key.dptr);
599 i++;
600 }
601 dbmp->di_size = i;
602
603 return INT2FIX(i);
604 }
605
606 static VALUE
607 fgdbm_empty_p(obj)
608 VALUE obj;
609 {
610 datum key;
611 struct dbmdata *dbmp;
612 GDBM_FILE dbm;
613
614 GetDBM(obj, dbmp);
615 if (dbmp->di_size < 0) {
616 dbm = dbmp->di_dbm;
617
618 key = gdbm_firstkey(dbm);
619 if (key.dptr) {
620 free(key.dptr);
621 return Qfalse;
622 }
623 return Qtrue;
624 }
625
626 if (dbmp->di_size == 0) return Qtrue;
627 return Qfalse;
628 }
629
630 static VALUE
631 fgdbm_each_value(obj)
632 VALUE obj;
633 {
634 struct dbmdata *dbmp;
635 GDBM_FILE dbm;
636 VALUE keystr;
637
638 GetDBM(obj, dbmp);
639 dbm = dbmp->di_dbm;
640
641 for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
642 keystr = rb_gdbm_nextkey(dbm, keystr)) {
643
644 rb_yield(rb_gdbm_fetch2(dbm, keystr));
645 }
646 return obj;
647 }
648
649 static VALUE
650 fgdbm_each_key(obj)
651 VALUE obj;
652 {
653 struct dbmdata *dbmp;
654 GDBM_FILE dbm;
655 VALUE keystr;
656
657 GetDBM(obj, dbmp);
658 dbm = dbmp->di_dbm;
659
660 for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
661 keystr = rb_gdbm_nextkey(dbm, keystr)) {
662
663 rb_yield(keystr);
664 }
665 return obj;
666 }
667
668 static VALUE
669 fgdbm_each_pair(obj)
670 VALUE obj;
671 {
672 GDBM_FILE dbm;
673 struct dbmdata *dbmp;
674 VALUE keystr;
675
676 GetDBM(obj, dbmp);
677 dbm = dbmp->di_dbm;
678
679 for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
680 keystr = rb_gdbm_nextkey(dbm, keystr)) {
681
682 rb_yield(rb_assoc_new(keystr, rb_gdbm_fetch2(dbm, keystr)));
683 }
684
685 return obj;
686 }
687
688 static VALUE
689 fgdbm_keys(obj)
690 VALUE obj;
691 {
692 struct dbmdata *dbmp;
693 GDBM_FILE dbm;
694 VALUE keystr, ary;
695
696 GetDBM(obj, dbmp);
697 dbm = dbmp->di_dbm;
698
699 ary = rb_ary_new();
700 for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
701 keystr = rb_gdbm_nextkey(dbm, keystr)) {
702
703 rb_ary_push(ary, keystr);
704 }
705
706 return ary;
707 }
708
709 static VALUE
710 fgdbm_values(obj)
711 VALUE obj;
712 {
713 datum key, nextkey;
714 struct dbmdata *dbmp;
715 GDBM_FILE dbm;
716 VALUE valstr, ary;
717
718 GetDBM(obj, dbmp);
719 dbm = dbmp->di_dbm;
720
721 ary = rb_ary_new();
722 for (key = gdbm_firstkey(dbm); key.dptr; key = nextkey) {
723 nextkey = gdbm_nextkey(dbm, key);
724 valstr = rb_gdbm_fetch(dbm, key);
725 free(key.dptr);
726 rb_ary_push(ary, valstr);
727 }
728
729 return ary;
730 }
731
732 static VALUE
733 fgdbm_has_key(obj, keystr)
734 VALUE obj, keystr;
735 {
736 datum key;
737 struct dbmdata *dbmp;
738 GDBM_FILE dbm;
739
740 StringValue(keystr);
741 key.dptr = RSTRING(keystr)->ptr;
742 key.dsize = RSTRING(keystr)->len;
743
744 GetDBM(obj, dbmp);
745 dbm = dbmp->di_dbm;
746 if (gdbm_exists(dbm, key))
747 return Qtrue;
748 return Qfalse;
749 }
750
751 static VALUE
752 fgdbm_has_value(obj, valstr)
753 VALUE obj, valstr;
754 {
755 struct dbmdata *dbmp;
756 GDBM_FILE dbm;
757 VALUE keystr, valstr2;
758
759 StringValue(valstr);
760 GetDBM(obj, dbmp);
761 dbm = dbmp->di_dbm;
762 for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
763 keystr = rb_gdbm_nextkey(dbm, keystr)) {
764
765 valstr2 = rb_gdbm_fetch2(dbm, keystr);
766
767 if (!NIL_P(valstr2) &&
768 RSTRING(valstr)->len == RSTRING(valstr2)->len &&
769 memcmp(RSTRING(valstr)->ptr, RSTRING(valstr2)->ptr,
770 RSTRING(valstr)->len) == 0) {
771 return Qtrue;
772 }
773 }
774 return Qfalse;
775 }
776
777 static VALUE
778 fgdbm_to_a(obj)
779 VALUE obj;
780 {
781 struct dbmdata *dbmp;
782 GDBM_FILE dbm;
783 VALUE keystr, ary;
784
785 GetDBM(obj, dbmp);
786 dbm = dbmp->di_dbm;
787
788 ary = rb_ary_new();
789 for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
790 keystr = rb_gdbm_nextkey(dbm, keystr)) {
791
792 rb_ary_push(ary, rb_assoc_new(keystr, rb_gdbm_fetch2(dbm, keystr)));
793 }
794
795 return ary;
796 }
797
798 static VALUE
799 fgdbm_reorganize(obj)
800 VALUE obj;
801 {
802 struct dbmdata *dbmp;
803 GDBM_FILE dbm;
804
805 rb_secure(4);
806 GetDBM(obj, dbmp);
807 dbm = dbmp->di_dbm;
808 gdbm_reorganize(dbm);
809 return obj;
810 }
811
812 static VALUE
813 fgdbm_sync(obj)
814 VALUE obj;
815 {
816 struct dbmdata *dbmp;
817 GDBM_FILE dbm;
818
819 rb_secure(4);
820 GetDBM(obj, dbmp);
821 dbm = dbmp->di_dbm;
822 gdbm_sync(dbm);
823 return obj;
824 }
825
826 static VALUE
827 fgdbm_set_cachesize(obj, val)
828 VALUE obj, val;
829 {
830 struct dbmdata *dbmp;
831 GDBM_FILE dbm;
832 int optval;
833
834 GetDBM(obj, dbmp);
835 dbm = dbmp->di_dbm;
836
837 optval = FIX2INT(val);
838 if (gdbm_setopt(dbm, GDBM_CACHESIZE, &optval, sizeof(optval)) == -1) {
839 rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
840 }
841 return val;
842 }
843
844 static VALUE
845 fgdbm_set_fastmode(obj, val)
846 VALUE obj, val;
847 {
848 struct dbmdata *dbmp;
849 GDBM_FILE dbm;
850 int optval;
851
852 GetDBM(obj, dbmp);
853 dbm = dbmp->di_dbm;
854
855 optval = 0;
856 if (RTEST(val))
857 optval = 1;
858
859 if (gdbm_setopt(dbm, GDBM_FASTMODE, &optval, sizeof(optval)) == -1) {
860 rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
861 }
862 return val;
863 }
864
865 static VALUE
866 fgdbm_set_syncmode(obj, val)
867 VALUE obj, val;
868 {
869 #if !defined(GDBM_SYNCMODE)
870 fgdbm_set_fastmode(obj, RTEST(val) ? Qfalse : Qtrue);
871 return val;
872 #else
873 struct dbmdata *dbmp;
874 GDBM_FILE dbm;
875 int optval;
876
877 GetDBM(obj, dbmp);
878 dbm = dbmp->di_dbm;
879
880 optval = 0;
881 if (RTEST(val))
882 optval = 1;
883
884 if (gdbm_setopt(dbm, GDBM_FASTMODE, &optval, sizeof(optval)) == -1) {
885 rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
886 }
887 return val;
888 #endif
889 }
890
891 static VALUE
892 fgdbm_to_hash(obj)
893 VALUE obj;
894 {
895 struct dbmdata *dbmp;
896 GDBM_FILE dbm;
897 VALUE keystr, hash;
898
899 GetDBM(obj, dbmp);
900 dbm = dbmp->di_dbm;
901
902 hash = rb_hash_new();
903 for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
904 keystr = rb_gdbm_nextkey(dbm, keystr)) {
905
906 rb_hash_aset(hash, keystr, rb_gdbm_fetch2(dbm, keystr));
907 }
908
909 return hash;
910 }
911
912 static VALUE
913 fgdbm_reject(obj)
914 VALUE obj;
915 {
916 return rb_hash_delete_if(fgdbm_to_hash(obj));
917 }
918
919 void
920 Init_gdbm()
921 {
922 rb_cGDBM = rb_define_class("GDBM", rb_cObject);
923 rb_eGDBMError = rb_define_class("GDBMError", rb_eStandardError);
924 rb_eGDBMFatalError = rb_define_class("GDBMFatalError", rb_eException);
925 rb_include_module(rb_cGDBM, rb_mEnumerable);
926
927 rb_define_singleton_method(rb_cGDBM, "new", fgdbm_s_new, -1);
928 rb_define_singleton_method(rb_cGDBM, "open", fgdbm_s_open, -1);
929
930 rb_define_method(rb_cGDBM, "initialize", fgdbm_initialize, -1);
931 rb_define_method(rb_cGDBM, "close", fgdbm_close, 0);
932 rb_define_method(rb_cGDBM, "[]", fgdbm_aref, 1);
933 rb_define_method(rb_cGDBM, "fetch", fgdbm_fetch_m, -1);
934 rb_define_method(rb_cGDBM, "[]=", fgdbm_store, 2);
935 rb_define_method(rb_cGDBM, "store", fgdbm_store, 2);
936 rb_define_method(rb_cGDBM, "index", fgdbm_index, 1);
937 rb_define_method(rb_cGDBM, "indexes", fgdbm_indexes, -1);
938 rb_define_method(rb_cGDBM, "indices", fgdbm_indexes, -1);
939 rb_define_method(rb_cGDBM, "select", fgdbm_select, -1);
940 rb_define_method(rb_cGDBM, "length", fgdbm_length, 0);
941 rb_define_method(rb_cGDBM, "size", fgdbm_length, 0);
942 rb_define_method(rb_cGDBM, "empty?", fgdbm_empty_p, 0);
943 rb_define_method(rb_cGDBM, "each", fgdbm_each_pair, 0);
944 rb_define_method(rb_cGDBM, "each_value", fgdbm_each_value, 0);
945 rb_define_method(rb_cGDBM, "each_key", fgdbm_each_key, 0);
946 rb_define_method(rb_cGDBM, "each_pair", fgdbm_each_pair, 0);
947 rb_define_method(rb_cGDBM, "keys", fgdbm_keys, 0);
948 rb_define_method(rb_cGDBM, "values", fgdbm_values, 0);
949 rb_define_method(rb_cGDBM, "shift", fgdbm_shift, 0);
950 rb_define_method(rb_cGDBM, "delete", fgdbm_delete, 1);
951 rb_define_method(rb_cGDBM, "delete_if", fgdbm_delete_if, 0);
952 rb_define_method(rb_cGDBM, "reject!", fgdbm_delete_if, 0);
953 rb_define_method(rb_cGDBM, "reject", fgdbm_reject, 0);
954 rb_define_method(rb_cGDBM, "clear", fgdbm_clear, 0);
955 rb_define_method(rb_cGDBM,"invert", fgdbm_invert, 0);
956 rb_define_method(rb_cGDBM,"update", fgdbm_update, 1);
957 rb_define_method(rb_cGDBM,"replace", fgdbm_replace, 1);
958 rb_define_method(rb_cGDBM,"reorganize", fgdbm_reorganize, 0);
959 rb_define_method(rb_cGDBM,"sync", fgdbm_sync, 0);
960
961 rb_define_method(rb_cGDBM,"cachesize=", fgdbm_set_cachesize, 1);
962 rb_define_method(rb_cGDBM,"fastmode=", fgdbm_set_fastmode, 1);
963 rb_define_method(rb_cGDBM,"syncmode=", fgdbm_set_syncmode, 1);
964
965 rb_define_method(rb_cGDBM, "include?", fgdbm_has_key, 1);
966 rb_define_method(rb_cGDBM, "has_key?", fgdbm_has_key, 1);
967 rb_define_method(rb_cGDBM, "member?", fgdbm_has_key, 1);
968 rb_define_method(rb_cGDBM, "has_value?", fgdbm_has_value, 1);
969 rb_define_method(rb_cGDBM, "key?", fgdbm_has_key, 1);
970 rb_define_method(rb_cGDBM, "value?", fgdbm_has_value, 1);
971
972 rb_define_method(rb_cGDBM, "to_a", fgdbm_to_a, 0);
973 rb_define_method(rb_cGDBM, "to_hash", fgdbm_to_hash, 0);
974
975
976
977
978
979
980
981
982 rb_define_const(rb_cGDBM, "FAST", INT2FIX(GDBM_FAST));
983
984
985
986
987 #if defined(GDBM_SYNC)
988 rb_define_const(rb_cGDBM, "SYNC", INT2FIX(GDBM_SYNC));
989 #endif
990 #if defined(GDBM_NOLOCK)
991 rb_define_const(rb_cGDBM, "NOLOCK", INT2FIX(GDBM_NOLOCK));
992 #endif
993 rb_define_const(rb_cGDBM, "VERSION", rb_str_new2(gdbm_version));
994 }