~ubuntu-branches/ubuntu/intrepid/ruby1.8/intrepid-updates

« back to all changes in this revision

Viewing changes to ext/gdbm/gdbm.c

  • Committer: Bazaar Package Importer
  • Author(s): akira yamada
  • Date: 2007-03-13 22:11:58 UTC
  • mfrom: (1.1.5 upstream)
  • Revision ID: james.westby@ubuntu.com-20070313221158-h3oql37brlaf2go2
Tags: 1.8.6-1
* new upstream version, 1.8.6.
* libruby1.8 conflicts with libopenssl-ruby1.8 (< 1.8.6) (closes: #410018)
* changed packaging style to cdbs from dbs.

Show diffs side-by-side

added added

removed removed

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