bdb1 0.2.4

Sign up to get free protection for your applications and to get access to all the features.
data/ext/bdb1/bdb1.h ADDED
@@ -0,0 +1,160 @@
1
+ #include <ruby.h>
2
+
3
+ #ifndef StringValue
4
+ #define StringValue(x,y) do { \
5
+ if (TYPE(x) != T_STRING) x = rb_str_to_str(x); \
6
+ } while(0)
7
+ #endif
8
+
9
+ #ifndef StringValuePtr
10
+ #define StringValuePtr(x) STR2CSTR(x)
11
+ #endif
12
+
13
+ #ifndef SafeStringValue
14
+ #define SafeStringValue(x) Check_SafeStr(x)
15
+ #endif
16
+
17
+ #ifndef RSTRING_PTR
18
+ # define RSTRING_PTR(x_) RSTRING(x_)->ptr
19
+ # define RSTRING_LEN(x_) RSTRING(x_)->len
20
+ #endif
21
+
22
+ #ifndef RARRAY_PTR
23
+ # define RARRAY_PTR(x_) RARRAY(x_)->ptr
24
+ # define RARRAY_LEN(x_) RARRAY(x_)->len
25
+ #endif
26
+
27
+ #ifdef COMPAT185
28
+ #include <db_185.h>
29
+ #else
30
+ #include <db.h>
31
+ #endif
32
+
33
+ #include <errno.h>
34
+ #include <sys/types.h>
35
+ #include <sys/stat.h>
36
+ #include <fcntl.h>
37
+
38
+ #define db_recno_t int
39
+
40
+ #define DB_VERSION_MAJOR 1
41
+ #define DB_VERSION_MINOR -1
42
+ #define DB_RELEASE_PATCH -1
43
+
44
+ #define BDB1_MARSHAL (1<<0)
45
+ #define BDB1_TXN (1<<1)
46
+ #define BDB1_RE_SOURCE (1<<2)
47
+ #define BDB1_BT_COMPARE (1<<3)
48
+ #define BDB1_BT_PREFIX (1<<4)
49
+ #define BDB1_DUP_COMPARE (1<<5)
50
+ #define BDB1_H_HASH (1<<6)
51
+ #define BDB1_NOT_OPEN (1<<7)
52
+
53
+ #define BDB1_FUNCTION (BDB1_BT_COMPARE|BDB1_BT_PREFIX|BDB1_DUP_COMPARE|BDB1_H_HASH)
54
+
55
+ #define DB_SET_RANGE R_CURSOR
56
+ #define DB_FIRST R_FIRST
57
+ #define DB_AFTER R_IAFTER
58
+ #define DB_BEFORE R_IBEFORE
59
+ #define DB_LAST R_LAST
60
+ #define DB_NEXT R_NEXT
61
+ #define DB_NOOVERWRITE R_NOOVERWRITE
62
+ #define DB_PREV R_PREV
63
+ #define DB_FIXEDLEN R_FIXEDLEN
64
+ #define DB_DUP R_DUP
65
+
66
+ #define DB_KEYEXIST 1
67
+ #define DB_NOTFOUND 1
68
+
69
+ #define DB_CREATE O_CREAT
70
+ #define DB_WRITE O_RDWR
71
+ #define DB_RDONLY O_RDONLY
72
+ #define DB_TRUNCATE O_TRUNC
73
+
74
+ #define BDB1_NEED_CURRENT (BDB1_MARSHAL | BDB1_BT_COMPARE | BDB1_BT_PREFIX | BDB1_DUP_COMPARE | BDB1_H_HASH)
75
+
76
+ typedef union {
77
+ BTREEINFO bi;
78
+ HASHINFO hi;
79
+ RECNOINFO ri;
80
+ } DB_INFO;
81
+
82
+ #define FILTER_KEY 0
83
+ #define FILTER_VALUE 1
84
+
85
+ typedef struct {
86
+ int options, len, has_info;
87
+ DBTYPE type;
88
+ VALUE bt_compare, bt_prefix, h_hash;
89
+ VALUE filter[4];
90
+ DB *dbp;
91
+ u_int32_t flags;
92
+ int array_base;
93
+ VALUE marshal;
94
+ DB_INFO info;
95
+ } bdb1_DB;
96
+
97
+ typedef struct {
98
+ bdb1_DB *dbst;
99
+ DBT *key;
100
+ VALUE value;
101
+ } bdb1_VALUE;
102
+
103
+ struct deleg_class {
104
+ int type;
105
+ VALUE db;
106
+ VALUE obj;
107
+ VALUE key;
108
+ };
109
+
110
+ extern VALUE bdb1_deleg_to_orig _((VALUE));
111
+
112
+ #define GetDB(obj, dbst) \
113
+ { \
114
+ Data_Get_Struct(obj, bdb1_DB, dbst); \
115
+ if (dbst->dbp == 0) { \
116
+ rb_raise(bdb1_eFatal, "closed DB"); \
117
+ } \
118
+ if (dbst->options & BDB1_NEED_CURRENT) { \
119
+ rb_thread_local_aset(rb_thread_current(), bdb1_id_current_db, obj); \
120
+ } \
121
+ }
122
+
123
+ #define DATA_ZERO(key) memset(&(key), 0, sizeof(key));
124
+
125
+ #define INIT_RECNO(dbst, key, recno) \
126
+ { \
127
+ recno = 1; \
128
+ memset(&(key), 0, sizeof(key)); \
129
+ if (dbst->type == DB_RECNO) { \
130
+ key.data = &recno; \
131
+ key.size = sizeof(db_recno_t); \
132
+ } \
133
+ }
134
+
135
+ #define FREE_KEY(dbst, key)
136
+
137
+ extern void bdb1_deleg_mark _((struct deleg_class *));
138
+ extern void bdb1_deleg_free _((struct deleg_class *));
139
+ extern VALUE bdb1_init _((int, VALUE *, VALUE));
140
+ extern VALUE bdb1_put _((int, VALUE *, VALUE));
141
+ extern VALUE bdb1_get _((int, VALUE *, VALUE));
142
+ extern VALUE bdb1_del _((VALUE, VALUE));
143
+ extern VALUE bdb1_test_load _((VALUE, DBT *, int));
144
+ extern int bdb1_test_error _((int));
145
+ extern VALUE bdb1_each_value _((VALUE));
146
+ extern VALUE bdb1_each_eulav _((VALUE));
147
+ extern VALUE bdb1_each_key _((VALUE));
148
+ extern VALUE bdb1_index _((VALUE, VALUE));
149
+ extern VALUE bdb1_has_value _((VALUE, VALUE));
150
+ extern VALUE bdb1_internal_value _((VALUE, VALUE, VALUE, int));
151
+ extern VALUE bdb1_to_type _((VALUE, VALUE, VALUE));
152
+ extern VALUE bdb1_clear _((VALUE));
153
+ extern VALUE bdb1_each_vc _((VALUE, int, int));
154
+ extern void bdb1_init_delegator _((void));
155
+ extern void bdb1_init_recnum _((void));
156
+
157
+ extern VALUE bdb1_mDb, bdb1_cCommon, bdb1_cDelegate, bdb1_cRecnum;
158
+ extern VALUE bdb1_mMarshal, bdb1_eFatal;
159
+
160
+ extern ID bdb1_id_current_db;
@@ -0,0 +1,196 @@
1
+ #include "bdb1.h"
2
+
3
+ static ID id_send;
4
+ VALUE bdb1_cDelegate;
5
+
6
+ void
7
+ bdb1_deleg_free(delegst)
8
+ struct deleg_class *delegst;
9
+ {
10
+ free(delegst);
11
+ }
12
+
13
+ void
14
+ bdb1_deleg_mark(delegst)
15
+ struct deleg_class *delegst;
16
+ {
17
+ bdb1_DB *dbst;
18
+
19
+ if (delegst->db) {
20
+ Data_Get_Struct(delegst->db, bdb1_DB, dbst);
21
+ if (dbst->dbp) {
22
+ rb_gc_mark(delegst->db);
23
+ if (delegst->key) rb_gc_mark(delegst->key);
24
+ }
25
+ }
26
+ if (delegst->obj) rb_gc_mark(delegst->obj);
27
+ }
28
+
29
+ #ifndef HAVE_RB_BLOCK_CALL
30
+
31
+ static VALUE
32
+ bdb1_deleg_each(tmp)
33
+ VALUE *tmp;
34
+ {
35
+ return rb_funcall2(tmp[0], id_send, (int)tmp[1], (VALUE *)tmp[2]);
36
+ }
37
+
38
+ static VALUE
39
+ bdb1_deleg_yield(i, res)
40
+ VALUE i, res;
41
+ {
42
+ return rb_ary_push(res, rb_yield(i));
43
+ }
44
+
45
+ #endif
46
+
47
+ static VALUE
48
+ bdb1_deleg_missing(argc, argv, obj)
49
+ int argc;
50
+ VALUE *argv, obj;
51
+ {
52
+ struct deleg_class *delegst, *newst;
53
+ bdb1_DB *dbst;
54
+ VALUE res, new;
55
+
56
+ Data_Get_Struct(obj, struct deleg_class, delegst);
57
+ if (rb_block_given_p()) {
58
+ #if HAVE_RB_BLOCK_CALL
59
+ res = rb_block_call(delegst->obj, id_send, argc, argv, rb_yield, 0);
60
+ #else
61
+ VALUE tmp[3];
62
+
63
+ tmp[0] = delegst->obj;
64
+ tmp[1] = (VALUE)argc;
65
+ tmp[2] = (VALUE)argv;
66
+ res = rb_ary_new();
67
+ rb_iterate(bdb1_deleg_each, (VALUE)tmp, bdb1_deleg_yield, res);
68
+ #endif
69
+ }
70
+ else {
71
+ res = rb_funcall2(delegst->obj, id_send, argc, argv);
72
+ }
73
+ Data_Get_Struct(delegst->db, bdb1_DB, dbst);
74
+ if (dbst->dbp) {
75
+ VALUE nargv[2];
76
+
77
+ if (!SPECIAL_CONST_P(res) &&
78
+ (TYPE(res) != T_DATA ||
79
+ RDATA(res)->dmark != (RUBY_DATA_FUNC)bdb1_deleg_mark)) {
80
+ new = Data_Make_Struct(bdb1_cDelegate, struct deleg_class,
81
+ bdb1_deleg_mark, bdb1_deleg_free, newst);
82
+ newst->db = delegst->db;
83
+ newst->obj = res;
84
+ newst->key = (!delegst->type)?obj:delegst->key;
85
+ newst->type = 1;
86
+ res = new;
87
+ }
88
+ if (!delegst->type) {
89
+ nargv[0] = delegst->key;
90
+ nargv[1] = delegst->obj;
91
+ }
92
+ else {
93
+ Data_Get_Struct(delegst->key, struct deleg_class, newst);
94
+ nargv[0] = newst->key;
95
+ nargv[1] = newst->obj;
96
+ }
97
+ bdb1_put(2, nargv, delegst->db);
98
+ }
99
+ return res;
100
+ }
101
+
102
+ #define DELEG_0(id) \
103
+ VALUE obj; \
104
+ { \
105
+ struct deleg_class *delegst; \
106
+ Data_Get_Struct(obj, struct deleg_class, delegst); \
107
+ return rb_funcall2(delegst->obj, id, 0, 0); \
108
+ }
109
+
110
+ static VALUE bdb1_deleg_inspect(obj) DELEG_0(rb_intern("inspect"))
111
+ static VALUE bdb1_deleg_to_s(obj) DELEG_0(rb_intern("to_s"))
112
+ static VALUE bdb1_deleg_to_str(obj) DELEG_0(rb_intern("to_str"))
113
+ static VALUE bdb1_deleg_to_a(obj) DELEG_0(rb_intern("to_a"))
114
+ static VALUE bdb1_deleg_to_ary(obj) DELEG_0(rb_intern("to_ary"))
115
+ static VALUE bdb1_deleg_to_i(obj) DELEG_0(rb_intern("to_i"))
116
+ static VALUE bdb1_deleg_to_int(obj) DELEG_0(rb_intern("to_int"))
117
+ static VALUE bdb1_deleg_to_f(obj) DELEG_0(rb_intern("to_f"))
118
+ static VALUE bdb1_deleg_to_hash(obj) DELEG_0(rb_intern("to_hash"))
119
+ static VALUE bdb1_deleg_to_io(obj) DELEG_0(rb_intern("to_io"))
120
+ static VALUE bdb1_deleg_to_proc(obj) DELEG_0(rb_intern("to_proc"))
121
+
122
+ VALUE
123
+ bdb1_deleg_to_orig(obj)
124
+ VALUE obj;
125
+ {
126
+ struct deleg_class *delegst;
127
+ Data_Get_Struct(obj, struct deleg_class, delegst);
128
+ return delegst->obj;
129
+ }
130
+
131
+ static VALUE
132
+ bdb1_deleg_orig(obj)
133
+ VALUE obj;
134
+ {
135
+ return obj;
136
+ }
137
+
138
+ static VALUE
139
+ bdb1_deleg_dump(obj, limit)
140
+ VALUE obj, limit;
141
+ {
142
+ struct deleg_class *delegst;
143
+ bdb1_DB *dbst;
144
+ Data_Get_Struct(obj, struct deleg_class, delegst);
145
+ Data_Get_Struct(delegst->db, bdb1_DB, dbst);
146
+ return rb_funcall(dbst->marshal, rb_intern("dump"), 1, delegst->obj);
147
+ }
148
+
149
+ static VALUE
150
+ bdb1_deleg_load(obj, str)
151
+ VALUE obj, str;
152
+ {
153
+ bdb1_DB *dbst;
154
+
155
+ if ((obj = rb_thread_local_aref(rb_thread_current(), bdb1_id_current_db)) == Qnil) {
156
+ rb_raise(bdb1_eFatal, "BUG : current_db not set");
157
+ }
158
+ Data_Get_Struct(obj, bdb1_DB, dbst);
159
+ return rb_funcall(dbst->marshal, rb_intern("load"), 1, str);
160
+ }
161
+
162
+ void bdb1_init_delegator()
163
+ {
164
+ id_send = rb_intern("send");
165
+ bdb1_cDelegate = rb_define_class_under(bdb1_mDb, "Delegate", rb_cObject);
166
+ {
167
+ VALUE ary, tmp = Qfalse;
168
+ char *method;
169
+ int i;
170
+
171
+ ary = rb_class_instance_methods(1, &tmp, rb_mKernel);
172
+ for (i = 0; i < RARRAY_LEN(ary); i++) {
173
+ method = StringValuePtr(RARRAY_PTR(ary)[i]);
174
+ if (!strcmp(method, "==") ||
175
+ !strcmp(method, "===") || !strcmp(method, "=~")) continue;
176
+ rb_undef_method(bdb1_cDelegate, method);
177
+ }
178
+ }
179
+ rb_define_method(bdb1_cDelegate, "method_missing", bdb1_deleg_missing, -1);
180
+ rb_define_method(bdb1_cDelegate, "inspect", bdb1_deleg_inspect, 0);
181
+ rb_define_method(bdb1_cDelegate, "to_s", bdb1_deleg_to_s, 0);
182
+ rb_define_method(bdb1_cDelegate, "to_str", bdb1_deleg_to_str, 0);
183
+ rb_define_method(bdb1_cDelegate, "to_a", bdb1_deleg_to_a, 0);
184
+ rb_define_method(bdb1_cDelegate, "to_ary", bdb1_deleg_to_ary, 0);
185
+ rb_define_method(bdb1_cDelegate, "to_i", bdb1_deleg_to_i, 0);
186
+ rb_define_method(bdb1_cDelegate, "to_int", bdb1_deleg_to_int, 0);
187
+ rb_define_method(bdb1_cDelegate, "to_f", bdb1_deleg_to_f, 0);
188
+ rb_define_method(bdb1_cDelegate, "to_hash", bdb1_deleg_to_hash, 0);
189
+ rb_define_method(bdb1_cDelegate, "to_io", bdb1_deleg_to_io, 0);
190
+ rb_define_method(bdb1_cDelegate, "to_proc", bdb1_deleg_to_proc, 0);
191
+ rb_define_method(bdb1_cDelegate, "_dump", bdb1_deleg_dump, 1);
192
+ rb_define_singleton_method(bdb1_cDelegate, "_load", bdb1_deleg_load, 1);
193
+ /* don't use please */
194
+ rb_define_method(bdb1_cDelegate, "to_orig", bdb1_deleg_to_orig, 0);
195
+ rb_define_method(rb_mKernel, "to_orig", bdb1_deleg_orig, 0);
196
+ }
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/ruby
2
+ require 'mkmf'
3
+
4
+ dir_config("db")
5
+
6
+ unless have_func("dbopen") || have_library("db1", "dbopen") ||
7
+ have_library("db", "dbopen")
8
+ raise "libdb not found"
9
+ end
10
+
11
+ if enable_config("shared", true)
12
+ $static = nil
13
+ end
14
+
15
+ %w[rb_frame_this_func rb_block_call].each do |f|
16
+ have_func(f)
17
+ end
18
+
19
+ %w[insert values_at map select].each do |f|
20
+ print "checking for Array\##{f}... "
21
+ if [].respond_to?(f)
22
+ puts "yes"
23
+ $CFLAGS += " -DHAVE_RB_ARY_#{f.upcase}"
24
+ else
25
+ puts "no"
26
+ end
27
+ end
28
+
29
+ create_makefile("bdb1")
30
+
31
+ File.open("Makefile", "a") { |make|
32
+ make.puts "test: $(DLLIB)"
33
+ }
data/ext/bdb1/recnum.c ADDED
@@ -0,0 +1,1093 @@
1
+ #include "bdb1.h"
2
+
3
+ static ID id_cmp;
4
+
5
+ static VALUE
6
+ bdb1_recnum_init(argc, argv, obj)
7
+ int argc;
8
+ VALUE *argv, obj;
9
+ {
10
+ VALUE *nargv;
11
+ VALUE array = rb_str_new2("array_base");
12
+ VALUE sarray = rb_str_new2("set_array_base");
13
+
14
+ if (!argc || TYPE(argv[argc - 1]) != T_HASH) {
15
+ nargv = ALLOCA_N(VALUE, argc + 1);
16
+ MEMCPY(nargv, argv, VALUE, argc);
17
+ nargv[argc] = rb_hash_new();
18
+ argv = nargv;
19
+ argc++;
20
+ }
21
+ rb_hash_aset(argv[argc - 1], array, INT2FIX(0));
22
+ if (rb_hash_aref(argv[argc - 1], sarray) != RHASH(argv[argc - 1])->ifnone) {
23
+ rb_hash_aset(argv[argc - 1], sarray, INT2FIX(0));
24
+ }
25
+ return bdb1_init(argc, argv, obj);
26
+ }
27
+
28
+ static VALUE
29
+ bdb1_sary_subseq(obj, beg, len)
30
+ VALUE obj;
31
+ long beg, len;
32
+ {
33
+ VALUE ary2, a;
34
+ bdb1_DB *dbst;
35
+ long i;
36
+
37
+ GetDB(obj, dbst);
38
+ if (beg > dbst->len) return Qnil;
39
+ if (beg < 0 || len < 0) return Qnil;
40
+
41
+ if (beg + len > dbst->len) {
42
+ len = dbst->len - beg;
43
+ }
44
+ if (len <= 0) return rb_ary_new2(0);
45
+
46
+ ary2 = rb_ary_new2(len);
47
+ for (i = 0; i < len; i++) {
48
+ a = INT2NUM(i + beg);
49
+ rb_ary_push(ary2, bdb1_get(1, &a, obj));
50
+ }
51
+ return ary2;
52
+ }
53
+
54
+ static VALUE
55
+ bdb1_sary_entry(obj, position)
56
+ VALUE obj, position;
57
+ {
58
+ bdb1_DB *dbst;
59
+ long offset;
60
+
61
+ GetDB(obj, dbst);
62
+ if (dbst->len == 0) return Qnil;
63
+ offset = NUM2LONG(position);
64
+ if (offset < 0) {
65
+ offset += dbst->len;
66
+ }
67
+ if (offset < 0 || dbst->len <= offset) return Qnil;
68
+ position = INT2NUM(offset);
69
+ return bdb1_get(1, &position, obj);
70
+ }
71
+
72
+ /*
73
+ * call-seq:
74
+ * db[nth]
75
+ * db[start..end]
76
+ * db[start, length]
77
+ *
78
+ * Element reference - with the following syntax:
79
+ *
80
+ * * db[nth]
81
+ * Retrieves the +nth+ item from an array. Index starts from zero.
82
+ * If index is the negative, counts backward from the end of the
83
+ * array. The index of the last element is -1. Returns +nil+, if
84
+ * the +nth+ element is not exist in the array.
85
+ *
86
+ * * db[start..end]
87
+ * Returns an array containing the objects from +start+ to +end+,
88
+ * including both ends. if end is larger than the length of the
89
+ * array, it will be rounded to the length. If +start+ is out of an
90
+ * array range , returns +nil+. And if +start+ is larger than end
91
+ * with in array range, returns empty array ([]).
92
+
93
+ * * db[start, length]
94
+ * Returns an array containing +length+ items from +start+. Returns
95
+ * +nil+ if +length+ is negative.
96
+ */
97
+ static VALUE
98
+ bdb1_sary_aref(argc, argv, obj)
99
+ int argc;
100
+ VALUE *argv, obj;
101
+ {
102
+ VALUE arg1, arg2;
103
+ long beg, len;
104
+ bdb1_DB *dbst;
105
+
106
+ GetDB(obj, dbst);
107
+ if (rb_scan_args(argc, argv, "11", &arg1, &arg2) == 2) {
108
+ beg = NUM2LONG(arg1);
109
+ len = NUM2LONG(arg2);
110
+ if (beg < 0) {
111
+ beg = dbst->len + beg;
112
+ }
113
+ return bdb1_sary_subseq(obj, beg, len);
114
+ }
115
+
116
+ if (FIXNUM_P(arg1)) {
117
+ return bdb1_sary_entry(obj, arg1);
118
+ }
119
+ else if (TYPE(arg1) == T_BIGNUM) {
120
+ rb_raise(rb_eIndexError, "index too big");
121
+ }
122
+ else {
123
+ switch (rb_range_beg_len(arg1, &beg, &len, dbst->len, 0)) {
124
+ case Qfalse:
125
+ break;
126
+ case Qnil:
127
+ return Qnil;
128
+ default:
129
+ return bdb1_sary_subseq(obj, beg, len);
130
+ }
131
+ }
132
+ return bdb1_sary_entry(obj, arg1);
133
+ }
134
+
135
+ static VALUE
136
+ bdb1_intern_shift_pop(obj, depart, len)
137
+ VALUE obj;
138
+ int depart, len;
139
+ {
140
+ bdb1_DB *dbst;
141
+ DBT key, data;
142
+ int ret, i;
143
+ db_recno_t recno;
144
+ VALUE res;
145
+
146
+ rb_secure(4);
147
+ GetDB(obj, dbst);
148
+ INIT_RECNO(dbst, key, recno);
149
+ DATA_ZERO(data);
150
+ res = rb_ary_new2(len);
151
+ for (i = 0; i < len; i++) {
152
+ ret = bdb1_test_error(dbst->dbp->seq(dbst->dbp, &key, &data, depart));
153
+ if (ret == DB_NOTFOUND) break;
154
+ rb_ary_push(res, bdb1_test_load(obj, &data, FILTER_VALUE));
155
+ bdb1_test_error(dbst->dbp->del(dbst->dbp, 0, R_CURSOR));
156
+ if (dbst->len > 0) dbst->len--;
157
+ }
158
+ if (RARRAY_LEN(res) == 0) return Qnil;
159
+ else if (RARRAY_LEN(res) == 1) return RARRAY_PTR(res)[0];
160
+ else return res;
161
+ }
162
+
163
+ static void
164
+ bdb1_sary_replace(obj, beg, len, rpl)
165
+ VALUE obj, rpl;
166
+ long beg, len;
167
+ {
168
+ long i, j, rlen;
169
+ VALUE tmp[2];
170
+ bdb1_DB *dbst;
171
+
172
+ GetDB(obj, dbst);
173
+ if (len < 0) rb_raise(rb_eIndexError, "negative length %d", len);
174
+ if (beg < 0) {
175
+ beg += dbst->len;
176
+ }
177
+ if (beg < 0) {
178
+ beg -= dbst->len;
179
+ rb_raise(rb_eIndexError, "index %d out of array", beg);
180
+ }
181
+ if (beg + len > dbst->len) {
182
+ len = dbst->len - beg;
183
+ }
184
+
185
+ if (NIL_P(rpl)) {
186
+ rpl = rb_ary_new2(0);
187
+ }
188
+ else if (TYPE(rpl) != T_ARRAY) {
189
+ rpl = rb_ary_new3(1, rpl);
190
+ }
191
+ rlen = RARRAY_LEN(rpl);
192
+
193
+ tmp[1] = Qnil;
194
+ if (beg >= dbst->len) {
195
+ for (i = dbst->len; i < beg; i++) {
196
+ tmp[0] = INT2NUM(i);
197
+ bdb1_put(2, tmp, obj);
198
+ dbst->len++;
199
+ }
200
+ for (i = beg, j = 0; j < RARRAY_LEN(rpl); i++, j++) {
201
+ tmp[0] = INT2NUM(i);
202
+ tmp[1] = RARRAY_PTR(rpl)[j];
203
+ bdb1_put(2, tmp, obj);
204
+ dbst->len++;
205
+ }
206
+ }
207
+ else {
208
+ if (len < rlen) {
209
+ tmp[1] = Qnil;
210
+ for (i = dbst->len - 1; i >= (beg + len); i--) {
211
+ tmp[0] = INT2NUM(i);
212
+ tmp[1] = bdb1_get(1, tmp, obj);
213
+ tmp[0] = INT2NUM(i + rlen - len);
214
+ bdb1_put(2, tmp, obj);
215
+ }
216
+ dbst->len += rlen - len;
217
+ }
218
+ for (i = beg, j = 0; j < rlen; i++, j++) {
219
+ tmp[0] = INT2NUM(i);
220
+ tmp[1] = RARRAY_PTR(rpl)[j];
221
+ bdb1_put(2, tmp, obj);
222
+ }
223
+ if (len > rlen) {
224
+ for (i = beg + len; i < dbst->len; i++) {
225
+ tmp[0] = INT2NUM(i);
226
+ tmp[1] = bdb1_get(1, tmp, obj);
227
+ tmp[0] = INT2NUM(i + rlen - len);
228
+ bdb1_put(2, tmp, obj);
229
+ }
230
+ bdb1_intern_shift_pop(obj, DB_LAST, len - rlen);
231
+ }
232
+ }
233
+ }
234
+
235
+ /*
236
+ * call-seq:
237
+ * db[nth] = val
238
+ * db[start..end] = val
239
+ * db[start, length] = val
240
+ *
241
+ * Element assignment - with the following syntax:
242
+ *
243
+ * * db[nth]
244
+ * Changes the +nth+ element of the array into +val+. If +nth+ is
245
+ * larger than array length, the array shall be extended
246
+ * automatically. Extended region shall be initialized by +nil+.
247
+ *
248
+ * * db[start..end]
249
+ * Replaces the items from +start+ to +end+ with +val+. If +val+ is
250
+ * not an array, the type of +val+ will be converted into the Array
251
+ * using +to_a+ method.
252
+ *
253
+ * * db[start, length]
254
+ * Replaces the +length+ items from +start+ with +val+. If +val+ is
255
+ * not an array, the type of +val+ will be converted into the Array
256
+ * using +to_a+.
257
+ */
258
+ static VALUE
259
+ bdb1_sary_aset(argc, argv, obj)
260
+ int argc;
261
+ VALUE *argv;
262
+ VALUE obj;
263
+ {
264
+ long beg, len;
265
+ bdb1_DB *dbst;
266
+
267
+ GetDB(obj, dbst);
268
+ if (argc == 3) {
269
+ bdb1_sary_replace(obj, NUM2LONG(argv[0]), NUM2LONG(argv[1]), argv[2]);
270
+ return argv[2];
271
+ }
272
+ if (argc != 2) {
273
+ rb_raise(rb_eArgError, "wrong # of arguments(%d for 2)", argc);
274
+ }
275
+ if (FIXNUM_P(argv[0])) {
276
+ beg = FIX2LONG(argv[0]);
277
+ goto fixnum;
278
+ }
279
+ else if (rb_range_beg_len(argv[0], &beg, &len, dbst->len, 1)) {
280
+ bdb1_sary_replace(obj, beg, len, argv[1]);
281
+ return argv[1];
282
+ }
283
+ if (TYPE(argv[0]) == T_BIGNUM) {
284
+ rb_raise(rb_eIndexError, "index too big");
285
+ }
286
+
287
+ beg = NUM2LONG(argv[0]);
288
+ fixnum:
289
+ if (beg < 0) {
290
+ beg += dbst->len;
291
+ if (beg < 0) {
292
+ rb_raise(rb_eIndexError, "index %d out of array",
293
+ beg - dbst->len);
294
+ }
295
+ }
296
+ if (beg > dbst->len) {
297
+ VALUE nargv[2];
298
+ int i;
299
+
300
+ nargv[1] = Qnil;
301
+ for (i = dbst->len; i < beg; i++) {
302
+ nargv[0] = INT2NUM(i);
303
+ bdb1_put(2, nargv, obj);
304
+ dbst->len++;
305
+ }
306
+ }
307
+ argv[0] = INT2NUM(beg);
308
+ bdb1_put(2, argv, obj);
309
+ dbst->len++;
310
+ return argv[1];
311
+ }
312
+
313
+ #if HAVE_RB_ARY_INSERT
314
+
315
+ static VALUE
316
+ bdb1_sary_insert(argc, argv, obj)
317
+ int argc;
318
+ VALUE *argv;
319
+ VALUE obj;
320
+ {
321
+ long pos;
322
+
323
+ if (argc < 2) {
324
+ rb_raise(rb_eArgError, "wrong number of arguments(at least 2)");
325
+ }
326
+ pos = NUM2LONG(argv[0]);
327
+ if (pos == -1) {
328
+ bdb1_DB *dbst;
329
+
330
+ GetDB(obj, dbst);
331
+ pos = dbst->len;
332
+ }
333
+ else if (pos < 0) {
334
+ pos++;
335
+ }
336
+
337
+ bdb1_sary_replace(obj, pos, 0, rb_ary_new4(argc-1, argv+1));
338
+ return obj;
339
+ }
340
+
341
+ #endif
342
+
343
+ static VALUE
344
+ bdb1_sary_at(obj, pos)
345
+ VALUE obj, pos;
346
+ {
347
+ return bdb1_sary_entry(obj, pos);
348
+ }
349
+
350
+ static VALUE
351
+ bdb1_sary_first(obj)
352
+ VALUE obj;
353
+ {
354
+ bdb1_DB *dbst;
355
+ VALUE tmp;
356
+
357
+ GetDB(obj, dbst);
358
+ tmp = INT2NUM(0);
359
+ return bdb1_get(1, &tmp, obj);
360
+ }
361
+
362
+ static VALUE
363
+ bdb1_sary_last(obj)
364
+ VALUE obj;
365
+ {
366
+ bdb1_DB *dbst;
367
+ VALUE tmp;
368
+
369
+ GetDB(obj, dbst);
370
+ if (!dbst->len) return Qnil;
371
+ tmp = INT2NUM(dbst->len - 1);
372
+ return bdb1_get(1, &tmp, obj);
373
+ }
374
+
375
+ static VALUE
376
+ bdb1_sary_fetch(argc, argv, obj)
377
+ int argc;
378
+ VALUE *argv, obj;
379
+ {
380
+ VALUE pos, ifnone;
381
+ bdb1_DB *dbst;
382
+ long idx;
383
+
384
+ GetDB(obj, dbst);
385
+ rb_scan_args(argc, argv, "11", &pos, &ifnone);
386
+ idx = NUM2LONG(pos);
387
+
388
+ if (idx < 0) {
389
+ idx += dbst->len;
390
+ }
391
+ if (idx < 0 || dbst->len <= idx) {
392
+ return ifnone;
393
+ }
394
+ pos = INT2NUM(idx);
395
+ return bdb1_get(1, &pos, obj);
396
+ }
397
+
398
+
399
+ static VALUE
400
+ bdb1_sary_concat(obj, y)
401
+ VALUE obj, y;
402
+ {
403
+ bdb1_DB *dbst;
404
+ long i;
405
+ VALUE tmp[2];
406
+
407
+ y = rb_convert_type(y, T_ARRAY, "Array", "to_ary");
408
+ GetDB(obj, dbst);
409
+ for (i = 0; i < RARRAY_LEN(y); i++) {
410
+ tmp[0] = INT2NUM(dbst->len);
411
+ tmp[1] = RARRAY_PTR(y)[i];
412
+ bdb1_put(2, tmp, obj);
413
+ dbst->len++;
414
+ }
415
+ return obj;
416
+ }
417
+
418
+ static VALUE
419
+ bdb1_sary_push(obj, y)
420
+ VALUE obj, y;
421
+ {
422
+ bdb1_DB *dbst;
423
+ VALUE tmp[2];
424
+
425
+ GetDB(obj, dbst);
426
+ tmp[0] = INT2NUM(dbst->len);
427
+ tmp[1] = y;
428
+ bdb1_put(2, tmp, obj);
429
+ dbst->len++;
430
+ return obj;
431
+ }
432
+
433
+ static VALUE
434
+ bdb1_sary_push_m(argc, argv, obj)
435
+ int argc;
436
+ VALUE obj, *argv;
437
+ {
438
+ bdb1_DB *dbst;
439
+ long i;
440
+ VALUE tmp[2];
441
+
442
+ if (argc == 0) {
443
+ rb_raise(rb_eArgError, "wrong # of arguments(at least 1)");
444
+ }
445
+ if (argc > 0) {
446
+ GetDB(obj, dbst);
447
+ for (i = 0; i < argc; i++) {
448
+ tmp[0] = INT2NUM(dbst->len);
449
+ tmp[1] = argv[i];
450
+ bdb1_put(2, tmp, obj);
451
+ dbst->len++;
452
+ }
453
+ }
454
+ return obj;
455
+ }
456
+
457
+ static VALUE
458
+ bdb1_sary_s_create(argc, argv, obj)
459
+ int argc;
460
+ VALUE *argv;
461
+ VALUE obj;
462
+ {
463
+ VALUE res;
464
+ int i;
465
+
466
+ res = rb_funcall2(obj, rb_intern("new"), 0, 0);
467
+ if (argc < 0) {
468
+ rb_raise(rb_eArgError, "negative number of arguments");
469
+ }
470
+ if (argc > 0) {
471
+ bdb1_sary_push_m(argc, argv, res);
472
+ }
473
+ return res;
474
+ }
475
+
476
+ static VALUE
477
+ bdb1_sary_shift(obj)
478
+ VALUE obj;
479
+ {
480
+ VALUE res;
481
+ bdb1_DB *dbst;
482
+
483
+ GetDB(obj, dbst);
484
+ if (dbst->len == 0) return Qnil;
485
+ res = bdb1_intern_shift_pop(obj, DB_FIRST, 1);
486
+ return res;
487
+ }
488
+
489
+ static VALUE
490
+ bdb1_sary_pop(obj)
491
+ VALUE obj;
492
+ {
493
+ VALUE res;
494
+ bdb1_DB *dbst;
495
+
496
+ GetDB(obj, dbst);
497
+ if (dbst->len == 0) return Qnil;
498
+ res = bdb1_intern_shift_pop(obj, DB_LAST, 1);
499
+ return res;
500
+ }
501
+
502
+ static VALUE
503
+ bdb1_sary_unshift_m(argc, argv, obj)
504
+ int argc;
505
+ VALUE *argv;
506
+ VALUE obj;
507
+ {
508
+ bdb1_DB *dbst;
509
+ VALUE tmp[3];
510
+ long i;
511
+
512
+ if (argc == 0) {
513
+ rb_raise(rb_eArgError, "wrong # of arguments(at least 1)");
514
+ }
515
+ if (argc > 0) {
516
+ GetDB(obj, dbst);
517
+ tmp[0] = INT2NUM(0);
518
+ tmp[2] = INT2NUM(R_IBEFORE);
519
+ for (i = argc - 1; i >= 0; i--) {
520
+ tmp[1] = argv[i];
521
+ bdb1_put(3, tmp, obj);
522
+ dbst->len++;
523
+ }
524
+ }
525
+ return obj;
526
+ }
527
+
528
+ static VALUE
529
+ bdb1_sary_length(obj)
530
+ VALUE obj;
531
+ {
532
+ bdb1_DB *dbst;
533
+
534
+ GetDB(obj, dbst);
535
+ if (dbst->len < 0) rb_raise(bdb1_eFatal, "Invalid BDB::Recnum");
536
+ return INT2NUM(dbst->len);
537
+ }
538
+
539
+ static VALUE
540
+ bdb1_sary_empty_p(obj)
541
+ VALUE obj;
542
+ {
543
+ bdb1_DB *dbst;
544
+
545
+ GetDB(obj, dbst);
546
+ if (dbst->len < 0) rb_raise(bdb1_eFatal, "Invalid BDB::Recnum");
547
+ return (dbst->len)?Qfalse:Qtrue;
548
+ }
549
+
550
+ static VALUE
551
+ bdb1_sary_rindex(obj, a)
552
+ VALUE obj, a;
553
+ {
554
+ return bdb1_internal_value(obj, a, Qtrue, DB_PREV);
555
+ }
556
+
557
+ static VALUE
558
+ bdb1_sary_to_a(obj)
559
+ VALUE obj;
560
+ {
561
+ return bdb1_to_type(obj, rb_ary_new(), Qfalse);
562
+ }
563
+
564
+ static VALUE
565
+ bdb1_sary_reverse_m(obj)
566
+ VALUE obj;
567
+ {
568
+ return bdb1_to_type(obj, rb_ary_new(), Qnil);
569
+ }
570
+
571
+ static VALUE
572
+ bdb1_sary_reverse_bang(obj)
573
+ VALUE obj;
574
+ {
575
+ long i, j;
576
+ bdb1_DB *dbst;
577
+ VALUE tmp[2], interm;
578
+
579
+ GetDB(obj, dbst);
580
+ if (dbst->len <= 1) return obj;
581
+ i = 0;
582
+ j = dbst->len - 1;
583
+ while (i < j) {
584
+ tmp[0] = INT2NUM(i);
585
+ interm = bdb1_get(1, tmp, obj);
586
+ tmp[0] = INT2NUM(j);
587
+ tmp[1] = bdb1_get(1, tmp, obj);
588
+ tmp[0] = INT2NUM(i);
589
+ bdb1_put(2, tmp, obj);
590
+ tmp[0] = INT2NUM(j);
591
+ tmp[1] = interm;
592
+ bdb1_put(2, tmp, obj);
593
+ i++; j--;
594
+ }
595
+ return obj;
596
+ }
597
+
598
+ static VALUE
599
+ bdb1_sary_collect_bang(obj)
600
+ VALUE obj;
601
+ {
602
+ return bdb1_each_vc(obj, Qtrue, Qfalse);
603
+ }
604
+
605
+ static VALUE
606
+ bdb1_sary_collect(obj)
607
+ VALUE obj;
608
+ {
609
+ if (!rb_block_given_p()) {
610
+ return bdb1_sary_to_a(obj);
611
+ }
612
+ return bdb1_each_vc(obj, Qfalse, Qfalse);
613
+ }
614
+
615
+ static VALUE
616
+ bdb1_sary_values_at(argc, argv, obj)
617
+ int argc;
618
+ VALUE *argv, obj;
619
+ {
620
+ VALUE result;
621
+ long i;
622
+
623
+ result = rb_ary_new();
624
+ for (i = 0; i < argc; i++) {
625
+ rb_ary_push(result, bdb1_sary_fetch(1, argv + i, obj));
626
+ }
627
+ return result;
628
+ }
629
+
630
+ static VALUE
631
+ bdb1_sary_select(argc, argv, obj)
632
+ int argc;
633
+ VALUE *argv, obj;
634
+ {
635
+ VALUE result;
636
+ long i;
637
+
638
+ if (rb_block_given_p()) {
639
+ if (argc > 0) {
640
+ rb_raise(rb_eArgError, "wrong number arguments(%d for 0)", argc);
641
+ }
642
+ return bdb1_each_vc(obj, Qfalse, Qtrue);
643
+ }
644
+ #if HAVE_RB_ARY_VALUES_AT
645
+ rb_warn("Recnum#%s is deprecated; use Recnum#values_at",
646
+ #if HAVE_RB_FRAME_THIS_FUNC
647
+ rb_id2name(rb_frame_this_func()));
648
+ #else
649
+ rb_id2name(rb_frame_last_func()));
650
+ #endif
651
+ #endif
652
+ return bdb1_sary_values_at(argc, argv, obj);
653
+ }
654
+
655
+ static VALUE
656
+ bdb1_sary_indexes(argc, argv, obj)
657
+ int argc;
658
+ VALUE obj, *argv;
659
+ {
660
+ VALUE indexes;
661
+ int i;
662
+
663
+ #if HAVE_RB_ARY_VALUES_AT
664
+ rb_warn("Recnum#%s is deprecated; use Recnum#values_at",
665
+ #if HAVE_RB_FRAME_THIS_FUNC
666
+ rb_id2name(rb_frame_this_func()));
667
+ #else
668
+ rb_id2name(rb_frame_last_func()));
669
+ #endif
670
+ #endif
671
+ return bdb1_sary_select(argc, argv, obj);
672
+ }
673
+
674
+ static VALUE
675
+ bdb1_sary_filter(obj)
676
+ VALUE obj;
677
+ {
678
+ rb_warn("BDB1::Recnum#filter is deprecated; use BDB1::Recnum#collect!");
679
+ return bdb1_sary_collect_bang(obj);
680
+ }
681
+
682
+ static VALUE
683
+ bdb1_sary_delete(obj, item)
684
+ VALUE obj, item;
685
+ {
686
+ bdb1_DB *dbst;
687
+ long i1, i2;
688
+ VALUE tmp, a;
689
+
690
+ GetDB(obj, dbst);
691
+ i2 = dbst->len;
692
+ for (i1 = 0; i1 < dbst->len;) {
693
+ tmp = INT2NUM(i1);
694
+ a = bdb1_get(1, &tmp, obj);
695
+ if (rb_equal(a, item)) {
696
+ bdb1_del(obj, INT2NUM(i1));
697
+ dbst->len--;
698
+ }
699
+ else {
700
+ i1++;
701
+ }
702
+ }
703
+ if (dbst->len == i2) {
704
+ if (rb_block_given_p()) {
705
+ return rb_yield(item);
706
+ }
707
+ return Qnil;
708
+ }
709
+ return item;
710
+ }
711
+
712
+ static VALUE
713
+ bdb1_sary_delete_at_m(obj, a)
714
+ VALUE obj, a;
715
+ {
716
+ bdb1_DB *dbst;
717
+ long pos;
718
+ VALUE tmp;
719
+ VALUE del = Qnil;
720
+
721
+ GetDB(obj, dbst);
722
+ pos = NUM2INT(a);
723
+ if (pos >= dbst->len) return Qnil;
724
+ if (pos < 0) pos += dbst->len;
725
+ if (pos < 0) return Qnil;
726
+
727
+ tmp = INT2NUM(pos);
728
+ del = bdb1_get(1, &tmp, obj);
729
+ bdb1_del(obj, tmp);
730
+ dbst->len--;
731
+ return del;
732
+ }
733
+
734
+ static VALUE
735
+ bdb1_sary_reject_bang(obj)
736
+ VALUE obj;
737
+ {
738
+ bdb1_DB *dbst;
739
+ long i1, i2;
740
+ VALUE tmp, a;
741
+
742
+ GetDB(obj, dbst);
743
+ i2 = dbst->len;
744
+ for (i1 = 0; i1 < dbst->len;) {
745
+ tmp = INT2NUM(i1);
746
+ a = bdb1_get(1, &tmp, obj);
747
+ if (!RTEST(rb_yield(a))) {
748
+ i1++;
749
+ continue;
750
+ }
751
+ bdb1_del(obj, tmp);
752
+ dbst->len--;
753
+ }
754
+ if (dbst->len == i2) return Qnil;
755
+ return obj;
756
+ }
757
+
758
+ static VALUE
759
+ bdb1_sary_delete_if(obj)
760
+ VALUE obj;
761
+ {
762
+ bdb1_sary_reject_bang(obj);
763
+ return obj;
764
+ }
765
+
766
+ static VALUE
767
+ bdb1_sary_replace_m(obj, obj2)
768
+ VALUE obj, obj2;
769
+ {
770
+ bdb1_DB *dbst;
771
+
772
+ GetDB(obj, dbst);
773
+ obj2 = rb_convert_type(obj2, T_ARRAY, "Array", "to_ary");
774
+ bdb1_sary_replace(obj, 0, dbst->len, obj2);
775
+ return obj;
776
+ }
777
+
778
+ static VALUE
779
+ bdb1_sary_clear(obj)
780
+ VALUE obj;
781
+ {
782
+ bdb1_DB *dbst;
783
+ bdb1_clear(obj);
784
+ GetDB(obj, dbst);
785
+ dbst->len = 0;
786
+ return obj;
787
+ }
788
+
789
+ static VALUE
790
+ bdb1_sary_fill(argc, argv, obj)
791
+ int argc;
792
+ VALUE *argv;
793
+ VALUE obj;
794
+ {
795
+ VALUE item, arg1, arg2, tmp[2];
796
+ long beg, len, i;
797
+ bdb1_DB *dbst;
798
+
799
+ GetDB(obj, dbst);
800
+ rb_scan_args(argc, argv, "12", &item, &arg1, &arg2);
801
+ switch (argc) {
802
+ case 1:
803
+ len = dbst->len;
804
+ beg = 0;
805
+ break;
806
+ case 2:
807
+ if (rb_range_beg_len(arg1, &beg, &len, dbst->len, 1)) {
808
+ break;
809
+ }
810
+ /* fall through */
811
+ case 3:
812
+ beg = NIL_P(arg1)?0:NUM2LONG(arg1);
813
+ if (beg < 0) {
814
+ beg += dbst->len;
815
+ if (beg < 0) beg = 0;
816
+ }
817
+ len = NIL_P(arg2)?dbst->len - beg:NUM2LONG(arg2);
818
+ break;
819
+ }
820
+ tmp[1] = item;
821
+ for (i = 0; i < len; i++) {
822
+ tmp[0] = INT2NUM(i + beg);
823
+ bdb1_put(2, tmp, obj);
824
+ if ((i + beg) >= dbst->len) dbst->len++;
825
+ }
826
+ return obj;
827
+ }
828
+
829
+ static VALUE
830
+ bdb1_sary_cmp(obj, obj2)
831
+ VALUE obj, obj2;
832
+ {
833
+ bdb1_DB *dbst, *dbst2;
834
+ VALUE a, a2, tmp, ary;
835
+ long i, len;
836
+
837
+ if (obj == obj2) return INT2FIX(0);
838
+ GetDB(obj, dbst);
839
+ len = dbst->len;
840
+ if (!rb_obj_is_kind_of(obj2, bdb1_cRecnum)) {
841
+ obj2 = rb_convert_type(obj2, T_ARRAY, "Array", "to_ary");
842
+ if (len > RARRAY_LEN(obj2)) {
843
+ len = RARRAY_LEN(obj2);
844
+ }
845
+ ary = Qtrue;
846
+ }
847
+ else {
848
+ GetDB(obj2, dbst2);
849
+ if (len > dbst2->len) {
850
+ len = dbst2->len;
851
+ }
852
+ ary = Qfalse;
853
+ }
854
+ for (i = 0; i < len; i++) {
855
+ tmp = INT2NUM(i);
856
+ a = bdb1_get(1, &tmp, obj);
857
+ if (ary) {
858
+ a2 = RARRAY_PTR(obj2)[i];
859
+ }
860
+ else {
861
+ a2 = bdb1_get(1, &tmp, obj2);
862
+ }
863
+ tmp = rb_funcall(a, id_cmp, 1, a2);
864
+ if (tmp != INT2FIX(0)) {
865
+ return tmp;
866
+ }
867
+ }
868
+ len = dbst->len - (ary?RARRAY_LEN(obj2):dbst2->len);
869
+ if (len == 0) return INT2FIX(0);
870
+ if (len > 0) return INT2FIX(1);
871
+ return INT2FIX(-1);
872
+ }
873
+
874
+ static VALUE
875
+ bdb1_sary_slice_bang(argc, argv, obj)
876
+ int argc;
877
+ VALUE *argv;
878
+ VALUE obj;
879
+ {
880
+ VALUE arg1, arg2;
881
+ long pos, len;
882
+ bdb1_DB *dbst;
883
+
884
+ GetDB(obj, dbst);
885
+ if (rb_scan_args(argc, argv, "11", &arg1, &arg2) == 2) {
886
+ pos = NUM2LONG(arg1);
887
+ len = NUM2LONG(arg2);
888
+ delete_pos_len:
889
+ if (pos < 0) {
890
+ pos = dbst->len + pos;
891
+ }
892
+ arg2 = bdb1_sary_subseq(obj, pos, len);
893
+ bdb1_sary_replace(obj, pos, len, Qnil);
894
+ return arg2;
895
+ }
896
+
897
+ if (!FIXNUM_P(arg1) && rb_range_beg_len(arg1, &pos, &len, dbst->len, 1)) {
898
+ goto delete_pos_len;
899
+ }
900
+
901
+ pos = NUM2LONG(arg1);
902
+ if (pos >= dbst->len) return Qnil;
903
+ if (pos < 0) pos += dbst->len;
904
+ if (pos < 0) return Qnil;
905
+
906
+ arg1 = INT2NUM(pos);
907
+ arg2 = bdb1_sary_at(obj, arg1);
908
+ if (bdb1_del(obj, arg1) != Qnil) dbst->len--;
909
+ return arg2;
910
+ }
911
+
912
+ static VALUE
913
+ bdb1_sary_plus(obj, y)
914
+ VALUE obj, y;
915
+ {
916
+ return rb_ary_plus(bdb1_sary_to_a(obj), y);
917
+ }
918
+
919
+ static VALUE
920
+ bdb1_sary_times(obj, y)
921
+ VALUE obj, y;
922
+ {
923
+ return rb_funcall(bdb1_sary_to_a(obj), rb_intern("*"), 1, y);
924
+ }
925
+
926
+ static VALUE
927
+ bdb1_sary_diff(obj, y)
928
+ VALUE obj, y;
929
+ {
930
+ return rb_funcall(bdb1_sary_to_a(obj), rb_intern("-"), 1, y);
931
+ }
932
+
933
+ static VALUE
934
+ bdb1_sary_and(obj, y)
935
+ VALUE obj, y;
936
+ {
937
+ return rb_funcall(bdb1_sary_to_a(obj), rb_intern("&"), 1, y);
938
+ }
939
+
940
+ static VALUE
941
+ bdb1_sary_or(obj, y)
942
+ VALUE obj, y;
943
+ {
944
+ return rb_funcall(bdb1_sary_to_a(obj), rb_intern("|"), 1, y);
945
+ }
946
+
947
+ static VALUE
948
+ bdb1_sary_compact(obj)
949
+ VALUE obj;
950
+ {
951
+ return rb_funcall(bdb1_sary_to_a(obj), rb_intern("compact"), 0, 0);
952
+ }
953
+
954
+ static VALUE
955
+ bdb1_sary_compact_bang(obj)
956
+ VALUE obj;
957
+ {
958
+ bdb1_DB *dbst;
959
+ long i, j;
960
+ VALUE tmp;
961
+
962
+ GetDB(obj, dbst);
963
+ j = dbst->len;
964
+ for (i = 0; i < dbst->len; ) {
965
+ tmp = INT2NUM(i);
966
+ tmp = bdb1_get(1, &tmp, obj);
967
+ if (NIL_P(tmp)) {
968
+ bdb1_del(obj, INT2NUM(i));
969
+ dbst->len--;
970
+ }
971
+ else {
972
+ i++;
973
+ }
974
+ }
975
+ if (dbst->len == j) return Qnil;
976
+ return obj;
977
+ }
978
+
979
+ static VALUE
980
+ bdb1_sary_nitems(obj)
981
+ VALUE obj;
982
+ {
983
+ bdb1_DB *dbst;
984
+ long i, j;
985
+ VALUE tmp;
986
+
987
+ GetDB(obj, dbst);
988
+ j = 0;
989
+ for (i = 0; i < dbst->len; i++) {
990
+ tmp = INT2NUM(i);
991
+ tmp = bdb1_get(1, &tmp, obj);
992
+ if (!NIL_P(tmp)) j++;
993
+ }
994
+ return INT2NUM(j);
995
+ }
996
+
997
+ static VALUE
998
+ bdb1_sary_each_index(obj)
999
+ VALUE obj;
1000
+ {
1001
+ bdb1_DB *dbst;
1002
+ long i;
1003
+
1004
+ GetDB(obj, dbst);
1005
+ for (i = 0; i< dbst->len; i++) {
1006
+ rb_yield(INT2NUM(i));
1007
+ }
1008
+ return obj;
1009
+ }
1010
+
1011
+ void bdb1_init_recnum()
1012
+ {
1013
+ id_cmp = rb_intern("<=>");
1014
+ bdb1_cRecnum = rb_define_class_under(bdb1_mDb, "Recnum", bdb1_cCommon);
1015
+ rb_define_singleton_method(bdb1_cRecnum, "[]", bdb1_sary_s_create, -1);
1016
+ rb_const_set(bdb1_mDb, rb_intern("Recno"), bdb1_cRecnum);
1017
+ rb_define_private_method(bdb1_cRecnum, "initialize", bdb1_recnum_init, -1);
1018
+ rb_define_method(bdb1_cRecnum, "[]", bdb1_sary_aref, -1);
1019
+ rb_define_method(bdb1_cRecnum, "[]=", bdb1_sary_aset, -1);
1020
+ rb_define_method(bdb1_cRecnum, "at", bdb1_sary_at, 1);
1021
+ rb_define_method(bdb1_cRecnum, "fetch", bdb1_sary_fetch, -1);
1022
+ rb_define_method(bdb1_cRecnum, "first", bdb1_sary_first, 0);
1023
+ rb_define_method(bdb1_cRecnum, "last", bdb1_sary_last, 0);
1024
+ rb_define_method(bdb1_cRecnum, "concat", bdb1_sary_concat, 1);
1025
+ rb_define_method(bdb1_cRecnum, "<<", bdb1_sary_push, 1);
1026
+ rb_define_method(bdb1_cRecnum, "push", bdb1_sary_push_m, -1);
1027
+ rb_define_method(bdb1_cRecnum, "pop", bdb1_sary_pop, 0);
1028
+ rb_define_method(bdb1_cRecnum, "shift", bdb1_sary_shift, 0);
1029
+ rb_define_method(bdb1_cRecnum, "unshift", bdb1_sary_unshift_m, -1);
1030
+ #if HAVE_RB_ARY_INSERT
1031
+ rb_define_method(bdb1_cRecnum, "insert", bdb1_sary_insert, -1);
1032
+ #endif
1033
+ rb_define_method(bdb1_cRecnum, "each", bdb1_each_value, 0);
1034
+ rb_define_method(bdb1_cRecnum, "each_index", bdb1_sary_each_index, 0);
1035
+ rb_define_method(bdb1_cRecnum, "reverse_each", bdb1_each_eulav, 0);
1036
+ rb_define_method(bdb1_cRecnum, "length", bdb1_sary_length, 0);
1037
+ rb_define_alias(bdb1_cRecnum, "size", "length");
1038
+ rb_define_method(bdb1_cRecnum, "empty?", bdb1_sary_empty_p, 0);
1039
+ rb_define_method(bdb1_cRecnum, "index", bdb1_index, 1);
1040
+ rb_define_method(bdb1_cRecnum, "rindex", bdb1_sary_rindex, 1);
1041
+ rb_define_method(bdb1_cRecnum, "indexes", bdb1_sary_indexes, -1);
1042
+ rb_define_method(bdb1_cRecnum, "indices", bdb1_sary_indexes, -1);
1043
+ rb_define_method(bdb1_cRecnum, "reverse", bdb1_sary_reverse_m, 0);
1044
+ rb_define_method(bdb1_cRecnum, "reverse!", bdb1_sary_reverse_bang, 0);
1045
+ rb_define_method(bdb1_cRecnum, "collect", bdb1_sary_collect, 0);
1046
+ rb_define_method(bdb1_cRecnum, "collect!", bdb1_sary_collect_bang, 0);
1047
+ #if HAVE_RB_ARY_MAP
1048
+ rb_define_method(bdb1_cRecnum, "map", bdb1_sary_collect, 0);
1049
+ #endif
1050
+ #if HAVE_RB_ARY_VALUES_AT
1051
+ rb_define_method(bdb1_cRecnum, "values_at", bdb1_sary_values_at, -1);
1052
+ #endif
1053
+ #if HAVE_RB_ARY_SELECT
1054
+ rb_define_method(bdb1_cRecnum, "select", bdb1_sary_select, -1);
1055
+ #endif
1056
+ rb_define_method(bdb1_cRecnum, "map!", bdb1_sary_collect_bang, 0);
1057
+ rb_define_method(bdb1_cRecnum, "filter", bdb1_sary_filter, 0);
1058
+ rb_define_method(bdb1_cRecnum, "delete", bdb1_sary_delete, 1);
1059
+ rb_define_method(bdb1_cRecnum, "delete_at", bdb1_sary_delete_at_m, 1);
1060
+ rb_define_method(bdb1_cRecnum, "delete_if", bdb1_sary_delete_if, 0);
1061
+ rb_define_method(bdb1_cRecnum, "reject!", bdb1_sary_reject_bang, 0);
1062
+ rb_define_method(bdb1_cRecnum, "replace", bdb1_sary_replace_m, 1);
1063
+ rb_define_method(bdb1_cRecnum, "clear", bdb1_sary_clear, 0);
1064
+ rb_define_method(bdb1_cRecnum, "fill", bdb1_sary_fill, -1);
1065
+ rb_define_method(bdb1_cRecnum, "include?", bdb1_has_value, 1);
1066
+ rb_define_method(bdb1_cRecnum, "<=>", bdb1_sary_cmp, 1);
1067
+ rb_define_method(bdb1_cRecnum, "slice", bdb1_sary_aref, -1);
1068
+ rb_define_method(bdb1_cRecnum, "slice!", bdb1_sary_slice_bang, -1);
1069
+ /*
1070
+ rb_define_method(bdb1_cRecnum, "assoc", bdb1_sary_assoc, 1);
1071
+ rb_define_method(bdb1_cRecnum, "rassoc", bdb1_sary_rassoc, 1);
1072
+ */
1073
+ rb_define_method(bdb1_cRecnum, "+", bdb1_sary_plus, 1);
1074
+ rb_define_method(bdb1_cRecnum, "*", bdb1_sary_times, 1);
1075
+
1076
+ rb_define_method(bdb1_cRecnum, "-", bdb1_sary_diff, 1);
1077
+ rb_define_method(bdb1_cRecnum, "&", bdb1_sary_and, 1);
1078
+ rb_define_method(bdb1_cRecnum, "|", bdb1_sary_or, 1);
1079
+
1080
+ /*
1081
+ rb_define_method(bdb1_cRecnum, "uniq", bdb1_sary_uniq, 0);
1082
+ rb_define_method(bdb1_cRecnum, "uniq!", bdb1_sary_uniq_bang, 0);
1083
+ */
1084
+ rb_define_method(bdb1_cRecnum, "compact", bdb1_sary_compact, 0);
1085
+ rb_define_method(bdb1_cRecnum, "compact!", bdb1_sary_compact_bang, 0);
1086
+ /*
1087
+ rb_define_method(bdb1_cRecnum, "flatten", bdb1_sary_flatten, 0);
1088
+ rb_define_method(bdb1_cRecnum, "flatten!", bdb1_sary_flatten_bang, 0);
1089
+ */
1090
+ rb_define_method(bdb1_cRecnum, "nitems", bdb1_sary_nitems, 0);
1091
+ rb_define_method(bdb1_cRecnum, "to_a", bdb1_sary_to_a, 0);
1092
+ rb_define_method(bdb1_cRecnum, "to_ary", bdb1_sary_to_a, 0);
1093
+ }