bdb1 0.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+ }