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 | }
|
---|