gdbm 1.3.1 → 2.0.0.beta1

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