1 | #include <mruby.h>
|
---|
2 | #include <mruby/value.h>
|
---|
3 | #include <mruby/array.h>
|
---|
4 | #include <mruby/range.h>
|
---|
5 | #include <mruby/hash.h>
|
---|
6 |
|
---|
7 | /*
|
---|
8 | * call-seq:
|
---|
9 | * ary.assoc(obj) -> new_ary or nil
|
---|
10 | *
|
---|
11 | * Searches through an array whose elements are also arrays
|
---|
12 | * comparing _obj_ with the first element of each contained array
|
---|
13 | * using obj.==.
|
---|
14 | * Returns the first contained array that matches (that
|
---|
15 | * is, the first associated array),
|
---|
16 | * or +nil+ if no match is found.
|
---|
17 | * See also <code>Array#rassoc</code>.
|
---|
18 | *
|
---|
19 | * s1 = [ "colors", "red", "blue", "green" ]
|
---|
20 | * s2 = [ "letters", "a", "b", "c" ]
|
---|
21 | * s3 = "foo"
|
---|
22 | * a = [ s1, s2, s3 ]
|
---|
23 | * a.assoc("letters") #=> [ "letters", "a", "b", "c" ]
|
---|
24 | * a.assoc("foo") #=> nil
|
---|
25 | */
|
---|
26 |
|
---|
27 | static mrb_value
|
---|
28 | mrb_ary_assoc(mrb_state *mrb, mrb_value ary)
|
---|
29 | {
|
---|
30 | mrb_int i;
|
---|
31 | mrb_value v, k;
|
---|
32 |
|
---|
33 | mrb_get_args(mrb, "o", &k);
|
---|
34 |
|
---|
35 | for (i = 0; i < RARRAY_LEN(ary); ++i) {
|
---|
36 | v = mrb_check_array_type(mrb, RARRAY_PTR(ary)[i]);
|
---|
37 | if (!mrb_nil_p(v) && RARRAY_LEN(v) > 0 &&
|
---|
38 | mrb_equal(mrb, RARRAY_PTR(v)[0], k))
|
---|
39 | return v;
|
---|
40 | }
|
---|
41 | return mrb_nil_value();
|
---|
42 | }
|
---|
43 |
|
---|
44 | /*
|
---|
45 | * call-seq:
|
---|
46 | * ary.rassoc(obj) -> new_ary or nil
|
---|
47 | *
|
---|
48 | * Searches through the array whose elements are also arrays. Compares
|
---|
49 | * _obj_ with the second element of each contained array using
|
---|
50 | * <code>==</code>. Returns the first contained array that matches. See
|
---|
51 | * also <code>Array#assoc</code>.
|
---|
52 | *
|
---|
53 | * a = [ [ 1, "one"], [2, "two"], [3, "three"], ["ii", "two"] ]
|
---|
54 | * a.rassoc("two") #=> [2, "two"]
|
---|
55 | * a.rassoc("four") #=> nil
|
---|
56 | */
|
---|
57 |
|
---|
58 | static mrb_value
|
---|
59 | mrb_ary_rassoc(mrb_state *mrb, mrb_value ary)
|
---|
60 | {
|
---|
61 | mrb_int i;
|
---|
62 | mrb_value v, value;
|
---|
63 |
|
---|
64 | mrb_get_args(mrb, "o", &value);
|
---|
65 |
|
---|
66 | for (i = 0; i < RARRAY_LEN(ary); ++i) {
|
---|
67 | v = RARRAY_PTR(ary)[i];
|
---|
68 | if (mrb_array_p(v) &&
|
---|
69 | RARRAY_LEN(v) > 1 &&
|
---|
70 | mrb_equal(mrb, RARRAY_PTR(v)[1], value))
|
---|
71 | return v;
|
---|
72 | }
|
---|
73 | return mrb_nil_value();
|
---|
74 | }
|
---|
75 |
|
---|
76 | /*
|
---|
77 | * call-seq:
|
---|
78 | * ary.at(index) -> obj or nil
|
---|
79 | *
|
---|
80 | * Returns the element at _index_. A
|
---|
81 | * negative index counts from the end of +self+. Returns +nil+
|
---|
82 | * if the index is out of range. See also <code>Array#[]</code>.
|
---|
83 | *
|
---|
84 | * a = [ "a", "b", "c", "d", "e" ]
|
---|
85 | * a.at(0) #=> "a"
|
---|
86 | * a.at(-1) #=> "e"
|
---|
87 | */
|
---|
88 |
|
---|
89 | static mrb_value
|
---|
90 | mrb_ary_at(mrb_state *mrb, mrb_value ary)
|
---|
91 | {
|
---|
92 | mrb_int pos;
|
---|
93 | mrb_get_args(mrb, "i", &pos);
|
---|
94 |
|
---|
95 | return mrb_ary_entry(ary, pos);
|
---|
96 | }
|
---|
97 |
|
---|
98 | static mrb_value
|
---|
99 | mrb_ary_values_at(mrb_state *mrb, mrb_value self)
|
---|
100 | {
|
---|
101 | mrb_int argc;
|
---|
102 | mrb_value *argv;
|
---|
103 |
|
---|
104 | mrb_get_args(mrb, "*", &argv, &argc);
|
---|
105 |
|
---|
106 | return mrb_get_values_at(mrb, self, RARRAY_LEN(self), argc, argv, mrb_ary_ref);
|
---|
107 | }
|
---|
108 |
|
---|
109 |
|
---|
110 | /*
|
---|
111 | * call-seq:
|
---|
112 | * ary.slice!(index) -> obj or nil
|
---|
113 | * ary.slice!(start, length) -> new_ary or nil
|
---|
114 | * ary.slice!(range) -> new_ary or nil
|
---|
115 | *
|
---|
116 | * Deletes the element(s) given by an +index+ (optionally up to +length+
|
---|
117 | * elements) or by a +range+.
|
---|
118 | *
|
---|
119 | * Returns the deleted object (or objects), or +nil+ if the +index+ is out of
|
---|
120 | * range.
|
---|
121 | *
|
---|
122 | * a = [ "a", "b", "c" ]
|
---|
123 | * a.slice!(1) #=> "b"
|
---|
124 | * a #=> ["a", "c"]
|
---|
125 | * a.slice!(-1) #=> "c"
|
---|
126 | * a #=> ["a"]
|
---|
127 | * a.slice!(100) #=> nil
|
---|
128 | * a #=> ["a"]
|
---|
129 | */
|
---|
130 |
|
---|
131 | static mrb_value
|
---|
132 | mrb_ary_slice_bang(mrb_state *mrb, mrb_value self)
|
---|
133 | {
|
---|
134 | struct RArray *a = mrb_ary_ptr(self);
|
---|
135 | mrb_int i, j, k, len, alen;
|
---|
136 | mrb_value val;
|
---|
137 | mrb_value *ptr;
|
---|
138 | mrb_value ary;
|
---|
139 |
|
---|
140 | mrb_ary_modify(mrb, a);
|
---|
141 |
|
---|
142 | if (mrb_get_argc(mrb) == 1) {
|
---|
143 | mrb_value index;
|
---|
144 |
|
---|
145 | mrb_get_args(mrb, "o|i", &index, &len);
|
---|
146 | switch (mrb_type(index)) {
|
---|
147 | case MRB_TT_RANGE:
|
---|
148 | if (mrb_range_beg_len(mrb, index, &i, &len, ARY_LEN(a), TRUE) == MRB_RANGE_OK) {
|
---|
149 | goto delete_pos_len;
|
---|
150 | }
|
---|
151 | else {
|
---|
152 | return mrb_nil_value();
|
---|
153 | }
|
---|
154 | case MRB_TT_FIXNUM:
|
---|
155 | val = mrb_funcall(mrb, self, "delete_at", 1, index);
|
---|
156 | return val;
|
---|
157 | default:
|
---|
158 | val = mrb_funcall(mrb, self, "delete_at", 1, index);
|
---|
159 | return val;
|
---|
160 | }
|
---|
161 | }
|
---|
162 |
|
---|
163 | mrb_get_args(mrb, "ii", &i, &len);
|
---|
164 | delete_pos_len:
|
---|
165 | alen = ARY_LEN(a);
|
---|
166 | if (i < 0) i += alen;
|
---|
167 | if (i < 0 || alen < i) return mrb_nil_value();
|
---|
168 | if (len < 0) return mrb_nil_value();
|
---|
169 | if (alen == i) return mrb_ary_new(mrb);
|
---|
170 | if (len > alen - i) len = alen - i;
|
---|
171 |
|
---|
172 | ary = mrb_ary_new_capa(mrb, len);
|
---|
173 | ptr = ARY_PTR(a);
|
---|
174 | for (j = i, k = 0; k < len; ++j, ++k) {
|
---|
175 | mrb_ary_push(mrb, ary, ptr[j]);
|
---|
176 | }
|
---|
177 |
|
---|
178 | ptr += i;
|
---|
179 | for (j = i; j < alen - len; ++j) {
|
---|
180 | *ptr = *(ptr+len);
|
---|
181 | ++ptr;
|
---|
182 | }
|
---|
183 |
|
---|
184 | mrb_ary_resize(mrb, self, alen - len);
|
---|
185 | return ary;
|
---|
186 | }
|
---|
187 |
|
---|
188 | void
|
---|
189 | mrb_mruby_array_ext_gem_init(mrb_state* mrb)
|
---|
190 | {
|
---|
191 | struct RClass * a = mrb->array_class;
|
---|
192 |
|
---|
193 | mrb_define_method(mrb, a, "assoc", mrb_ary_assoc, MRB_ARGS_REQ(1));
|
---|
194 | mrb_define_method(mrb, a, "at", mrb_ary_at, MRB_ARGS_REQ(1));
|
---|
195 | mrb_define_method(mrb, a, "rassoc", mrb_ary_rassoc, MRB_ARGS_REQ(1));
|
---|
196 | mrb_define_method(mrb, a, "values_at", mrb_ary_values_at, MRB_ARGS_ANY());
|
---|
197 | mrb_define_method(mrb, a, "slice!", mrb_ary_slice_bang, MRB_ARGS_ARG(1,1));
|
---|
198 | }
|
---|
199 |
|
---|
200 | void
|
---|
201 | mrb_mruby_array_ext_gem_final(mrb_state* mrb)
|
---|
202 | {
|
---|
203 | }
|
---|