rubysl-gdbm 0.0.1 → 2.0.0

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