mbed I/F binding for mruby

Dependents:   mruby_mbed_web mirb_mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers array.c Source File

array.c

00001 #include "mruby.h"
00002 #include "mruby/value.h"
00003 #include "mruby/array.h"
00004 #include "mruby/range.h"
00005 #include "mruby/hash.h"
00006 
00007 /*
00008  *  call-seq:
00009  *     ary.assoc(obj)   -> new_ary  or  nil
00010  *
00011  *  Searches through an array whose elements are also arrays
00012  *  comparing _obj_ with the first element of each contained array
00013  *  using obj.==.
00014  *  Returns the first contained array that matches (that
00015  *  is, the first associated array),
00016  *  or +nil+ if no match is found.
00017  *  See also <code>Array#rassoc</code>.
00018  *
00019  *     s1 = [ "colors", "red", "blue", "green" ]
00020  *     s2 = [ "letters", "a", "b", "c" ]
00021  *     s3 = "foo"
00022  *     a  = [ s1, s2, s3 ]
00023  *     a.assoc("letters")  #=> [ "letters", "a", "b", "c" ]
00024  *     a.assoc("foo")      #=> nil
00025  */
00026 
00027 static mrb_value
00028 mrb_ary_assoc(mrb_state *mrb, mrb_value ary)
00029 {
00030   mrb_int i;
00031   mrb_value v, k;
00032 
00033   mrb_get_args(mrb, "o", &k);
00034 
00035   for (i = 0; i < RARRAY_LEN(ary); ++i) {
00036     v = mrb_check_array_type(mrb, RARRAY_PTR(ary)[i]);
00037     if (!mrb_nil_p(v) && RARRAY_LEN(v) > 0 &&
00038         mrb_equal(mrb, RARRAY_PTR(v)[0], k))
00039       return v;
00040   }
00041   return mrb_nil_value();
00042 }
00043 
00044 /*
00045  *  call-seq:
00046  *     ary.rassoc(obj) -> new_ary or nil
00047  *
00048  *  Searches through the array whose elements are also arrays. Compares
00049  *  _obj_ with the second element of each contained array using
00050  *  <code>==</code>. Returns the first contained array that matches. See
00051  *  also <code>Array#assoc</code>.
00052  *
00053  *     a = [ [ 1, "one"], [2, "two"], [3, "three"], ["ii", "two"] ]
00054  *     a.rassoc("two")    #=> [2, "two"]
00055  *     a.rassoc("four")   #=> nil
00056  */
00057 
00058 static mrb_value
00059 mrb_ary_rassoc(mrb_state *mrb, mrb_value ary)
00060 {
00061   mrb_int i;
00062   mrb_value v, value;
00063 
00064   mrb_get_args(mrb, "o", &value);
00065 
00066   for (i = 0; i < RARRAY_LEN(ary); ++i) {
00067     v = RARRAY_PTR(ary)[i];
00068     if (mrb_type(v) == MRB_TT_ARRAY &&
00069         RARRAY_LEN(v) > 1 &&
00070         mrb_equal(mrb, RARRAY_PTR(v)[1], value))
00071       return v;
00072   }
00073   return mrb_nil_value();
00074 }
00075 
00076 /*
00077  *  call-seq:
00078  *     ary.at(index)   ->   obj  or nil
00079  *
00080  *  Returns the element at _index_. A
00081  *  negative index counts from the end of +self+.  Returns +nil+
00082  *  if the index is out of range. See also <code>Array#[]</code>.
00083  *
00084  *     a = [ "a", "b", "c", "d", "e" ]
00085  *     a.at(0)     #=> "a"
00086  *     a.at(-1)    #=> "e"
00087  */
00088 
00089 static mrb_value
00090 mrb_ary_at(mrb_state *mrb, mrb_value ary)
00091 {
00092   mrb_int pos;
00093   mrb_get_args(mrb, "i", &pos);
00094 
00095   return mrb_ary_entry(ary, pos);
00096 }
00097 
00098 static mrb_value
00099 mrb_ary_values_at(mrb_state *mrb, mrb_value self)
00100 {
00101   mrb_int argc;
00102   mrb_value *argv;
00103 
00104   mrb_get_args(mrb, "*", &argv, &argc);
00105 
00106   return mrb_get_values_at(mrb, self, RARRAY_LEN(self), argc, argv, mrb_ary_ref);
00107 }
00108 
00109 /*
00110  *  call-seq:
00111  *     ary.to_h   ->   Hash
00112  *
00113  *  Returns the result of interpreting <i>aray</i> as an array of
00114  *  <tt>[key, value]</tt> paris.
00115  *
00116  *     [[:foo, :bar], [1, 2]].to_h
00117  *       # => {:foo => :bar, 1 => 2}
00118  */
00119 
00120 static mrb_value
00121 mrb_ary_to_h(mrb_state *mrb, mrb_value ary)
00122 {
00123   mrb_int i;
00124   mrb_value v, hash;
00125 
00126   hash = mrb_hash_new_capa(mrb, 0);
00127 
00128   for (i = 0; i < RARRAY_LEN(ary); ++i) {
00129     v = mrb_check_array_type(mrb, RARRAY_PTR(ary)[i]);
00130 
00131     if (mrb_nil_p(v)) {
00132       mrb_raisef(mrb, E_TYPE_ERROR, "wrong element type %S at %S (expected array)",
00133         mrb_str_new_cstr(mrb,  mrb_obj_classname(mrb, RARRAY_PTR(ary)[i])),
00134         mrb_fixnum_value(i)
00135       );
00136     }
00137 
00138     if (RARRAY_LEN(v) != 2) {
00139       mrb_raisef(mrb, E_ARGUMENT_ERROR, "wrong array length at %S (expected 2, was %S)",
00140         mrb_fixnum_value(i),
00141         mrb_fixnum_value(RARRAY_LEN(v))
00142       );
00143     }
00144 
00145     mrb_hash_set(mrb, hash, RARRAY_PTR(v)[0], RARRAY_PTR(v)[1]);
00146   }
00147 
00148   return hash;
00149 }
00150 
00151 void
00152 mrb_mruby_array_ext_gem_init(mrb_state* mrb)
00153 {
00154   struct RClass * a = mrb->array_class;
00155 
00156   mrb_define_method(mrb, a, "assoc",  mrb_ary_assoc,  MRB_ARGS_REQ(1));
00157   mrb_define_method(mrb, a, "at",     mrb_ary_at,     MRB_ARGS_REQ(1));
00158   mrb_define_method(mrb, a, "rassoc", mrb_ary_rassoc, MRB_ARGS_REQ(1));
00159   mrb_define_method(mrb, a, "values_at", mrb_ary_values_at, MRB_ARGS_ANY());
00160   mrb_define_method(mrb, a, "to_h",   mrb_ary_to_h, MRB_ARGS_REQ(0));
00161 }
00162 
00163 void
00164 mrb_mruby_array_ext_gem_final(mrb_state* mrb)
00165 {
00166 }
00167