[270] | 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_type(v) == MRB_TT_ARRAY &&
|
---|
| 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 | * call-seq:
|
---|
| 111 | * ary.to_h -> Hash
|
---|
| 112 | *
|
---|
| 113 | * Returns the result of interpreting <i>aray</i> as an array of
|
---|
| 114 | * <tt>[key, value]</tt> paris.
|
---|
| 115 | *
|
---|
| 116 | * [[:foo, :bar], [1, 2]].to_h
|
---|
| 117 | * # => {:foo => :bar, 1 => 2}
|
---|
| 118 | *
|
---|
| 119 | */
|
---|
| 120 |
|
---|
| 121 | static mrb_value
|
---|
| 122 | mrb_ary_to_h(mrb_state *mrb, mrb_value ary)
|
---|
| 123 | {
|
---|
| 124 | mrb_int i;
|
---|
| 125 | mrb_value v, hash;
|
---|
| 126 |
|
---|
| 127 | hash = mrb_hash_new_capa(mrb, 0);
|
---|
| 128 |
|
---|
| 129 | for (i = 0; i < RARRAY_LEN(ary); ++i) {
|
---|
| 130 | v = mrb_check_array_type(mrb, RARRAY_PTR(ary)[i]);
|
---|
| 131 |
|
---|
| 132 | if (mrb_nil_p(v)) {
|
---|
| 133 | mrb_raisef(mrb, E_TYPE_ERROR, "wrong element type %S at %S (expected array)",
|
---|
| 134 | mrb_str_new_cstr(mrb, mrb_obj_classname(mrb, RARRAY_PTR(ary)[i])),
|
---|
| 135 | mrb_fixnum_value(i)
|
---|
| 136 | );
|
---|
| 137 | }
|
---|
| 138 |
|
---|
| 139 | if (RARRAY_LEN(v) != 2) {
|
---|
| 140 | mrb_raisef(mrb, E_ARGUMENT_ERROR, "wrong array length at %S (expected 2, was %S)",
|
---|
| 141 | mrb_fixnum_value(i),
|
---|
| 142 | mrb_fixnum_value(RARRAY_LEN(v))
|
---|
| 143 | );
|
---|
| 144 | }
|
---|
| 145 |
|
---|
| 146 | mrb_hash_set(mrb, hash, RARRAY_PTR(v)[0], RARRAY_PTR(v)[1]);
|
---|
| 147 | }
|
---|
| 148 |
|
---|
| 149 | return hash;
|
---|
| 150 | }
|
---|
| 151 |
|
---|
| 152 | void
|
---|
| 153 | mrb_mruby_array_ext_gem_init(mrb_state* mrb)
|
---|
| 154 | {
|
---|
| 155 | struct RClass * a = mrb->array_class;
|
---|
| 156 |
|
---|
| 157 | mrb_define_method(mrb, a, "assoc", mrb_ary_assoc, MRB_ARGS_REQ(1));
|
---|
| 158 | mrb_define_method(mrb, a, "at", mrb_ary_at, MRB_ARGS_REQ(1));
|
---|
| 159 | mrb_define_method(mrb, a, "rassoc", mrb_ary_rassoc, MRB_ARGS_REQ(1));
|
---|
| 160 | mrb_define_method(mrb, a, "values_at", mrb_ary_values_at, MRB_ARGS_ANY());
|
---|
| 161 | mrb_define_method(mrb, a, "to_h", mrb_ary_to_h, MRB_ARGS_REQ(0));
|
---|
| 162 | }
|
---|
| 163 |
|
---|
| 164 | void
|
---|
| 165 | mrb_mruby_array_ext_gem_final(mrb_state* mrb)
|
---|
| 166 | {
|
---|
| 167 | }
|
---|