[331] | 1 | #include <mruby.h>
|
---|
| 2 | #include <mruby/value.h>
|
---|
| 3 | #include <mruby/array.h>
|
---|
| 4 | #include <mruby/range.h>
|
---|
| 5 | #include <mruby/hash.h>
|
---|
[270] | 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];
|
---|
[439] | 68 | if (mrb_array_p(v) &&
|
---|
[270] | 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 |
|
---|
[331] | 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);
|
---|
[439] | 135 | mrb_int i, j, k, len, alen;
|
---|
[331] | 136 | mrb_value val;
|
---|
| 137 | mrb_value *ptr;
|
---|
| 138 | mrb_value ary;
|
---|
| 139 |
|
---|
| 140 | mrb_ary_modify(mrb, a);
|
---|
| 141 |
|
---|
[439] | 142 | if (mrb_get_argc(mrb) == 1) {
|
---|
| 143 | mrb_value index;
|
---|
| 144 |
|
---|
| 145 | mrb_get_args(mrb, "o|i", &index, &len);
|
---|
[331] | 146 | switch (mrb_type(index)) {
|
---|
| 147 | case MRB_TT_RANGE:
|
---|
[439] | 148 | if (mrb_range_beg_len(mrb, index, &i, &len, ARY_LEN(a), TRUE) == MRB_RANGE_OK) {
|
---|
[331] | 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 |
|
---|
[439] | 163 | mrb_get_args(mrb, "ii", &i, &len);
|
---|
[331] | 164 | delete_pos_len:
|
---|
[439] | 165 | alen = ARY_LEN(a);
|
---|
| 166 | if (i < 0) i += alen;
|
---|
| 167 | if (i < 0 || alen < i) return mrb_nil_value();
|
---|
[331] | 168 | if (len < 0) return mrb_nil_value();
|
---|
[439] | 169 | if (alen == i) return mrb_ary_new(mrb);
|
---|
| 170 | if (len > alen - i) len = alen - i;
|
---|
[331] | 171 |
|
---|
| 172 | ary = mrb_ary_new_capa(mrb, len);
|
---|
[439] | 173 | ptr = ARY_PTR(a);
|
---|
[331] | 174 | for (j = i, k = 0; k < len; ++j, ++k) {
|
---|
[439] | 175 | mrb_ary_push(mrb, ary, ptr[j]);
|
---|
[331] | 176 | }
|
---|
| 177 |
|
---|
[439] | 178 | ptr += i;
|
---|
| 179 | for (j = i; j < alen - len; ++j) {
|
---|
[331] | 180 | *ptr = *(ptr+len);
|
---|
| 181 | ++ptr;
|
---|
| 182 | }
|
---|
| 183 |
|
---|
[439] | 184 | mrb_ary_resize(mrb, self, alen - len);
|
---|
[331] | 185 | return ary;
|
---|
| 186 | }
|
---|
| 187 |
|
---|
[270] | 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());
|
---|
[439] | 197 | mrb_define_method(mrb, a, "slice!", mrb_ary_slice_bang, MRB_ARGS_ARG(1,1));
|
---|
[270] | 198 | }
|
---|
| 199 |
|
---|
| 200 | void
|
---|
| 201 | mrb_mruby_array_ext_gem_final(mrb_state* mrb)
|
---|
| 202 | {
|
---|
| 203 | }
|
---|