mbed I/F binding for mruby

Dependents:   mruby_mbed_web mirb_mbed

mbed-mruby

How to use

Class

Committer:
mzta
Date:
Mon Apr 13 05:20:15 2015 +0000
Revision:
1:8ccd1d494a4b
Parent:
0:158c61bb030f
- code refactoring.; - add SPI, SPISlave, I2C class to mruby-mbed (Incomplete).

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mzta 0:158c61bb030f 1 /*
mzta 0:158c61bb030f 2 ** range.c - Range class
mzta 0:158c61bb030f 3 **
mzta 0:158c61bb030f 4 ** See Copyright Notice in mruby.h
mzta 0:158c61bb030f 5 */
mzta 0:158c61bb030f 6
mzta 0:158c61bb030f 7 #include "mruby.h"
mzta 0:158c61bb030f 8 #include "mruby/class.h"
mzta 0:158c61bb030f 9 #include "mruby/range.h"
mzta 0:158c61bb030f 10 #include "mruby/string.h"
mzta 0:158c61bb030f 11 #include "mruby/array.h"
mzta 0:158c61bb030f 12
mzta 0:158c61bb030f 13 #define RANGE_CLASS (mrb_class_get(mrb, "Range"))
mzta 0:158c61bb030f 14
mzta 0:158c61bb030f 15 static void
mzta 0:158c61bb030f 16 range_check(mrb_state *mrb, mrb_value a, mrb_value b)
mzta 0:158c61bb030f 17 {
mzta 0:158c61bb030f 18 mrb_value ans;
mzta 0:158c61bb030f 19 enum mrb_vtype ta;
mzta 0:158c61bb030f 20 enum mrb_vtype tb;
mzta 0:158c61bb030f 21
mzta 0:158c61bb030f 22 ta = mrb_type(a);
mzta 0:158c61bb030f 23 tb = mrb_type(b);
mzta 0:158c61bb030f 24 if ((ta == MRB_TT_FIXNUM || ta == MRB_TT_FLOAT) &&
mzta 0:158c61bb030f 25 (tb == MRB_TT_FIXNUM || tb == MRB_TT_FLOAT)) {
mzta 0:158c61bb030f 26 return;
mzta 0:158c61bb030f 27 }
mzta 0:158c61bb030f 28
mzta 0:158c61bb030f 29 ans = mrb_funcall(mrb, a, "<=>", 1, b);
mzta 0:158c61bb030f 30 if (mrb_nil_p(ans)) {
mzta 0:158c61bb030f 31 /* can not be compared */
mzta 0:158c61bb030f 32 mrb_raise(mrb, E_ARGUMENT_ERROR, "bad value for range");
mzta 0:158c61bb030f 33 }
mzta 0:158c61bb030f 34 }
mzta 0:158c61bb030f 35
mzta 0:158c61bb030f 36 MRB_API mrb_value
mzta 0:158c61bb030f 37 mrb_range_new(mrb_state *mrb, mrb_value beg, mrb_value end, mrb_bool excl)
mzta 0:158c61bb030f 38 {
mzta 0:158c61bb030f 39 struct RRange *r;
mzta 0:158c61bb030f 40
mzta 0:158c61bb030f 41 range_check(mrb, beg, end);
mzta 0:158c61bb030f 42 r = (struct RRange*)mrb_obj_alloc(mrb, MRB_TT_RANGE, RANGE_CLASS);
mzta 0:158c61bb030f 43 r->edges = (mrb_range_edges *)mrb_malloc(mrb, sizeof(mrb_range_edges));
mzta 0:158c61bb030f 44 r->edges->beg = beg;
mzta 0:158c61bb030f 45 r->edges->end = end;
mzta 0:158c61bb030f 46 r->excl = excl;
mzta 0:158c61bb030f 47 return mrb_range_value(r);
mzta 0:158c61bb030f 48 }
mzta 0:158c61bb030f 49
mzta 0:158c61bb030f 50 /*
mzta 0:158c61bb030f 51 * call-seq:
mzta 0:158c61bb030f 52 * rng.first => obj
mzta 0:158c61bb030f 53 * rng.begin => obj
mzta 0:158c61bb030f 54 *
mzta 0:158c61bb030f 55 * Returns the first object in <i>rng</i>.
mzta 0:158c61bb030f 56 */
mzta 0:158c61bb030f 57 mrb_value
mzta 0:158c61bb030f 58 mrb_range_beg(mrb_state *mrb, mrb_value range)
mzta 0:158c61bb030f 59 {
mzta 0:158c61bb030f 60 struct RRange *r = mrb_range_ptr(range);
mzta 0:158c61bb030f 61
mzta 0:158c61bb030f 62 return r->edges->beg;
mzta 0:158c61bb030f 63 }
mzta 0:158c61bb030f 64
mzta 0:158c61bb030f 65 /*
mzta 0:158c61bb030f 66 * call-seq:
mzta 0:158c61bb030f 67 * rng.end => obj
mzta 0:158c61bb030f 68 * rng.last => obj
mzta 0:158c61bb030f 69 *
mzta 0:158c61bb030f 70 * Returns the object that defines the end of <i>rng</i>.
mzta 0:158c61bb030f 71 *
mzta 0:158c61bb030f 72 * (1..10).end #=> 10
mzta 0:158c61bb030f 73 * (1...10).end #=> 10
mzta 0:158c61bb030f 74 */
mzta 0:158c61bb030f 75
mzta 0:158c61bb030f 76 mrb_value
mzta 0:158c61bb030f 77 mrb_range_end(mrb_state *mrb, mrb_value range)
mzta 0:158c61bb030f 78 {
mzta 0:158c61bb030f 79 struct RRange *r = mrb_range_ptr(range);
mzta 0:158c61bb030f 80
mzta 0:158c61bb030f 81 return r->edges->end;
mzta 0:158c61bb030f 82 }
mzta 0:158c61bb030f 83
mzta 0:158c61bb030f 84 /*
mzta 0:158c61bb030f 85 * call-seq:
mzta 0:158c61bb030f 86 * range.exclude_end? => true or false
mzta 0:158c61bb030f 87 *
mzta 0:158c61bb030f 88 * Returns <code>true</code> if <i>range</i> excludes its end value.
mzta 0:158c61bb030f 89 */
mzta 0:158c61bb030f 90 mrb_value
mzta 0:158c61bb030f 91 mrb_range_excl(mrb_state *mrb, mrb_value range)
mzta 0:158c61bb030f 92 {
mzta 0:158c61bb030f 93 struct RRange *r = mrb_range_ptr(range);
mzta 0:158c61bb030f 94
mzta 0:158c61bb030f 95 return mrb_bool_value(r->excl);
mzta 0:158c61bb030f 96 }
mzta 0:158c61bb030f 97
mzta 0:158c61bb030f 98 static void
mzta 0:158c61bb030f 99 range_init(mrb_state *mrb, mrb_value range, mrb_value beg, mrb_value end, mrb_bool exclude_end)
mzta 0:158c61bb030f 100 {
mzta 0:158c61bb030f 101 struct RRange *r = mrb_range_ptr(range);
mzta 0:158c61bb030f 102
mzta 0:158c61bb030f 103 range_check(mrb, beg, end);
mzta 0:158c61bb030f 104 r->excl = exclude_end;
mzta 0:158c61bb030f 105 if (!r->edges) {
mzta 0:158c61bb030f 106 r->edges = (mrb_range_edges *)mrb_malloc(mrb, sizeof(mrb_range_edges));
mzta 0:158c61bb030f 107 }
mzta 0:158c61bb030f 108 r->edges->beg = beg;
mzta 0:158c61bb030f 109 r->edges->end = end;
mzta 0:158c61bb030f 110 }
mzta 0:158c61bb030f 111 /*
mzta 0:158c61bb030f 112 * call-seq:
mzta 0:158c61bb030f 113 * Range.new(start, end, exclusive=false) => range
mzta 0:158c61bb030f 114 *
mzta 0:158c61bb030f 115 * Constructs a range using the given <i>start</i> and <i>end</i>. If the third
mzta 0:158c61bb030f 116 * parameter is omitted or is <code>false</code>, the <i>range</i> will include
mzta 0:158c61bb030f 117 * the end object; otherwise, it will be excluded.
mzta 0:158c61bb030f 118 */
mzta 0:158c61bb030f 119
mzta 0:158c61bb030f 120 mrb_value
mzta 0:158c61bb030f 121 mrb_range_initialize(mrb_state *mrb, mrb_value range)
mzta 0:158c61bb030f 122 {
mzta 0:158c61bb030f 123 mrb_value beg, end;
mzta 0:158c61bb030f 124 mrb_bool exclusive;
mzta 0:158c61bb030f 125 int n;
mzta 0:158c61bb030f 126
mzta 0:158c61bb030f 127 n = mrb_get_args(mrb, "oo|b", &beg, &end, &exclusive);
mzta 0:158c61bb030f 128 if (n != 3) {
mzta 0:158c61bb030f 129 exclusive = FALSE;
mzta 0:158c61bb030f 130 }
mzta 0:158c61bb030f 131 /* Ranges are immutable, so that they should be initialized only once. */
mzta 0:158c61bb030f 132 range_init(mrb, range, beg, end, exclusive);
mzta 0:158c61bb030f 133 return range;
mzta 0:158c61bb030f 134 }
mzta 0:158c61bb030f 135 /*
mzta 0:158c61bb030f 136 * call-seq:
mzta 0:158c61bb030f 137 * range == obj => true or false
mzta 0:158c61bb030f 138 *
mzta 0:158c61bb030f 139 * Returns <code>true</code> only if
mzta 0:158c61bb030f 140 * 1) <i>obj</i> is a Range,
mzta 0:158c61bb030f 141 * 2) <i>obj</i> has equivalent beginning and end items (by comparing them with <code>==</code>),
mzta 0:158c61bb030f 142 * 3) <i>obj</i> has the same #exclude_end? setting as <i>rng</t>.
mzta 0:158c61bb030f 143 *
mzta 0:158c61bb030f 144 * (0..2) == (0..2) #=> true
mzta 0:158c61bb030f 145 * (0..2) == Range.new(0,2) #=> true
mzta 0:158c61bb030f 146 * (0..2) == (0...2) #=> false
mzta 0:158c61bb030f 147 *
mzta 0:158c61bb030f 148 */
mzta 0:158c61bb030f 149
mzta 0:158c61bb030f 150 mrb_value
mzta 0:158c61bb030f 151 mrb_range_eq(mrb_state *mrb, mrb_value range)
mzta 0:158c61bb030f 152 {
mzta 0:158c61bb030f 153 struct RRange *rr;
mzta 0:158c61bb030f 154 struct RRange *ro;
mzta 0:158c61bb030f 155 mrb_value obj;
mzta 0:158c61bb030f 156
mzta 0:158c61bb030f 157 mrb_get_args(mrb, "o", &obj);
mzta 0:158c61bb030f 158
mzta 0:158c61bb030f 159 if (mrb_obj_equal(mrb, range, obj)) return mrb_true_value();
mzta 0:158c61bb030f 160 if (!mrb_obj_is_instance_of(mrb, obj, mrb_obj_class(mrb, range))) { /* same class? */
mzta 0:158c61bb030f 161 return mrb_false_value();
mzta 0:158c61bb030f 162 }
mzta 0:158c61bb030f 163
mzta 0:158c61bb030f 164 rr = mrb_range_ptr(range);
mzta 0:158c61bb030f 165 ro = mrb_range_ptr(obj);
mzta 0:158c61bb030f 166 if (!mrb_bool(mrb_funcall(mrb, rr->edges->beg, "==", 1, ro->edges->beg)) ||
mzta 0:158c61bb030f 167 !mrb_bool(mrb_funcall(mrb, rr->edges->end, "==", 1, ro->edges->end)) ||
mzta 0:158c61bb030f 168 rr->excl != ro->excl) {
mzta 0:158c61bb030f 169 return mrb_false_value();
mzta 0:158c61bb030f 170 }
mzta 0:158c61bb030f 171 return mrb_true_value();
mzta 0:158c61bb030f 172 }
mzta 0:158c61bb030f 173
mzta 0:158c61bb030f 174 static mrb_bool
mzta 0:158c61bb030f 175 r_le(mrb_state *mrb, mrb_value a, mrb_value b)
mzta 0:158c61bb030f 176 {
mzta 0:158c61bb030f 177 mrb_value r = mrb_funcall(mrb, a, "<=>", 1, b); /* compare result */
mzta 0:158c61bb030f 178 /* output :a < b => -1, a = b => 0, a > b => +1 */
mzta 0:158c61bb030f 179
mzta 0:158c61bb030f 180 if (mrb_fixnum_p(r)) {
mzta 0:158c61bb030f 181 mrb_int c = mrb_fixnum(r);
mzta 0:158c61bb030f 182 if (c == 0 || c == -1) return TRUE;
mzta 0:158c61bb030f 183 }
mzta 0:158c61bb030f 184
mzta 0:158c61bb030f 185 return FALSE;
mzta 0:158c61bb030f 186 }
mzta 0:158c61bb030f 187
mzta 0:158c61bb030f 188 static mrb_bool
mzta 0:158c61bb030f 189 r_gt(mrb_state *mrb, mrb_value a, mrb_value b)
mzta 0:158c61bb030f 190 {
mzta 0:158c61bb030f 191 mrb_value r = mrb_funcall(mrb, a, "<=>", 1, b);
mzta 0:158c61bb030f 192 /* output :a < b => -1, a = b => 0, a > b => +1 */
mzta 0:158c61bb030f 193
mzta 0:158c61bb030f 194 return mrb_fixnum_p(r) && mrb_fixnum(r) == 1;
mzta 0:158c61bb030f 195 }
mzta 0:158c61bb030f 196
mzta 0:158c61bb030f 197 static mrb_bool
mzta 0:158c61bb030f 198 r_ge(mrb_state *mrb, mrb_value a, mrb_value b)
mzta 0:158c61bb030f 199 {
mzta 0:158c61bb030f 200 mrb_value r = mrb_funcall(mrb, a, "<=>", 1, b); /* compare result */
mzta 0:158c61bb030f 201 /* output :a < b => -1, a = b => 0, a > b => +1 */
mzta 0:158c61bb030f 202
mzta 0:158c61bb030f 203 if (mrb_fixnum_p(r)) {
mzta 0:158c61bb030f 204 mrb_int c = mrb_fixnum(r);
mzta 0:158c61bb030f 205 if (c == 0 || c == 1) return TRUE;
mzta 0:158c61bb030f 206 }
mzta 0:158c61bb030f 207
mzta 0:158c61bb030f 208 return FALSE;
mzta 0:158c61bb030f 209 }
mzta 0:158c61bb030f 210
mzta 0:158c61bb030f 211 /*
mzta 0:158c61bb030f 212 * call-seq:
mzta 0:158c61bb030f 213 * range === obj => true or false
mzta 0:158c61bb030f 214 * range.member?(val) => true or false
mzta 0:158c61bb030f 215 * range.include?(val) => true or false
mzta 0:158c61bb030f 216 *
mzta 0:158c61bb030f 217 */
mzta 0:158c61bb030f 218 mrb_value
mzta 0:158c61bb030f 219 mrb_range_include(mrb_state *mrb, mrb_value range)
mzta 0:158c61bb030f 220 {
mzta 0:158c61bb030f 221 mrb_value val;
mzta 0:158c61bb030f 222 struct RRange *r = mrb_range_ptr(range);
mzta 0:158c61bb030f 223 mrb_value beg, end;
mzta 0:158c61bb030f 224 mrb_bool include_p;
mzta 0:158c61bb030f 225
mzta 0:158c61bb030f 226 mrb_get_args(mrb, "o", &val);
mzta 0:158c61bb030f 227
mzta 0:158c61bb030f 228 beg = r->edges->beg;
mzta 0:158c61bb030f 229 end = r->edges->end;
mzta 0:158c61bb030f 230 include_p = r_le(mrb, beg, val) && /* beg <= val */
mzta 0:158c61bb030f 231 ((r->excl && r_gt(mrb, end, val)) || /* end > val */
mzta 0:158c61bb030f 232 (r_ge(mrb, end, val))); /* end >= val */
mzta 0:158c61bb030f 233
mzta 0:158c61bb030f 234 return mrb_bool_value(include_p);
mzta 0:158c61bb030f 235 }
mzta 0:158c61bb030f 236
mzta 0:158c61bb030f 237 static mrb_bool
mzta 0:158c61bb030f 238 range_beg_len(mrb_state *mrb, mrb_value range, mrb_int *begp, mrb_int *lenp, mrb_int len, mrb_bool trunc)
mzta 0:158c61bb030f 239 {
mzta 0:158c61bb030f 240 mrb_int beg, end;
mzta 0:158c61bb030f 241 struct RRange *r = mrb_range_ptr(range);
mzta 0:158c61bb030f 242
mzta 0:158c61bb030f 243 if (mrb_type(range) != MRB_TT_RANGE) return FALSE;
mzta 0:158c61bb030f 244
mzta 0:158c61bb030f 245 beg = mrb_int(mrb, r->edges->beg);
mzta 0:158c61bb030f 246 end = mrb_int(mrb, r->edges->end);
mzta 0:158c61bb030f 247
mzta 0:158c61bb030f 248 if (beg < 0) {
mzta 0:158c61bb030f 249 beg += len;
mzta 0:158c61bb030f 250 if (beg < 0) return FALSE;
mzta 0:158c61bb030f 251 }
mzta 0:158c61bb030f 252
mzta 0:158c61bb030f 253 if (trunc) {
mzta 0:158c61bb030f 254 if (beg > len) return FALSE;
mzta 0:158c61bb030f 255 if (end > len) end = len;
mzta 0:158c61bb030f 256 }
mzta 0:158c61bb030f 257
mzta 0:158c61bb030f 258 if (end < 0) end += len;
mzta 0:158c61bb030f 259 if (!r->excl && (!trunc || end < len))
mzta 0:158c61bb030f 260 end++; /* include end point */
mzta 0:158c61bb030f 261 len = end - beg;
mzta 0:158c61bb030f 262 if (len < 0) len = 0;
mzta 0:158c61bb030f 263
mzta 0:158c61bb030f 264 *begp = beg;
mzta 0:158c61bb030f 265 *lenp = len;
mzta 0:158c61bb030f 266 return TRUE;
mzta 0:158c61bb030f 267 }
mzta 0:158c61bb030f 268
mzta 0:158c61bb030f 269 MRB_API mrb_bool
mzta 0:158c61bb030f 270 mrb_range_beg_len(mrb_state *mrb, mrb_value range, mrb_int *begp, mrb_int *lenp, mrb_int len)
mzta 0:158c61bb030f 271 {
mzta 0:158c61bb030f 272 return range_beg_len(mrb, range, begp, lenp, len, TRUE);
mzta 0:158c61bb030f 273 }
mzta 0:158c61bb030f 274
mzta 0:158c61bb030f 275 /* 15.2.14.4.12(x) */
mzta 0:158c61bb030f 276 /*
mzta 0:158c61bb030f 277 * call-seq:
mzta 0:158c61bb030f 278 * rng.to_s -> string
mzta 0:158c61bb030f 279 *
mzta 0:158c61bb030f 280 * Convert this range object to a printable form.
mzta 0:158c61bb030f 281 */
mzta 0:158c61bb030f 282
mzta 0:158c61bb030f 283 static mrb_value
mzta 0:158c61bb030f 284 range_to_s(mrb_state *mrb, mrb_value range)
mzta 0:158c61bb030f 285 {
mzta 0:158c61bb030f 286 mrb_value str, str2;
mzta 0:158c61bb030f 287 struct RRange *r = mrb_range_ptr(range);
mzta 0:158c61bb030f 288
mzta 0:158c61bb030f 289 str = mrb_obj_as_string(mrb, r->edges->beg);
mzta 0:158c61bb030f 290 str2 = mrb_obj_as_string(mrb, r->edges->end);
mzta 0:158c61bb030f 291 str = mrb_str_dup(mrb, str);
mzta 0:158c61bb030f 292 mrb_str_cat(mrb, str, "...", r->excl ? 3 : 2);
mzta 0:158c61bb030f 293 mrb_str_append(mrb, str, str2);
mzta 0:158c61bb030f 294
mzta 0:158c61bb030f 295 return str;
mzta 0:158c61bb030f 296 }
mzta 0:158c61bb030f 297
mzta 0:158c61bb030f 298 /* 15.2.14.4.13(x) */
mzta 0:158c61bb030f 299 /*
mzta 0:158c61bb030f 300 * call-seq:
mzta 0:158c61bb030f 301 * rng.inspect -> string
mzta 0:158c61bb030f 302 *
mzta 0:158c61bb030f 303 * Convert this range object to a printable form (using
mzta 0:158c61bb030f 304 * <code>inspect</code> to convert the start and end
mzta 0:158c61bb030f 305 * objects).
mzta 0:158c61bb030f 306 */
mzta 0:158c61bb030f 307
mzta 0:158c61bb030f 308 static mrb_value
mzta 0:158c61bb030f 309 range_inspect(mrb_state *mrb, mrb_value range)
mzta 0:158c61bb030f 310 {
mzta 0:158c61bb030f 311 mrb_value str, str2;
mzta 0:158c61bb030f 312 struct RRange *r = mrb_range_ptr(range);
mzta 0:158c61bb030f 313
mzta 0:158c61bb030f 314 str = mrb_inspect(mrb, r->edges->beg);
mzta 0:158c61bb030f 315 str2 = mrb_inspect(mrb, r->edges->end);
mzta 0:158c61bb030f 316 str = mrb_str_dup(mrb, str);
mzta 0:158c61bb030f 317 mrb_str_cat(mrb, str, "...", r->excl ? 3 : 2);
mzta 0:158c61bb030f 318 mrb_str_append(mrb, str, str2);
mzta 0:158c61bb030f 319
mzta 0:158c61bb030f 320 return str;
mzta 0:158c61bb030f 321 }
mzta 0:158c61bb030f 322
mzta 0:158c61bb030f 323 /* 15.2.14.4.14(x) */
mzta 0:158c61bb030f 324 /*
mzta 0:158c61bb030f 325 * call-seq:
mzta 0:158c61bb030f 326 * rng.eql?(obj) -> true or false
mzta 0:158c61bb030f 327 *
mzta 0:158c61bb030f 328 * Returns <code>true</code> only if <i>obj</i> is a Range, has equivalent
mzta 0:158c61bb030f 329 * beginning and end items (by comparing them with #eql?), and has the same
mzta 0:158c61bb030f 330 * #exclude_end? setting as <i>rng</i>.
mzta 0:158c61bb030f 331 *
mzta 0:158c61bb030f 332 * (0..2).eql?(0..2) #=> true
mzta 0:158c61bb030f 333 * (0..2).eql?(Range.new(0,2)) #=> true
mzta 0:158c61bb030f 334 * (0..2).eql?(0...2) #=> false
mzta 0:158c61bb030f 335 *
mzta 0:158c61bb030f 336 */
mzta 0:158c61bb030f 337
mzta 0:158c61bb030f 338 static mrb_value
mzta 0:158c61bb030f 339 range_eql(mrb_state *mrb, mrb_value range)
mzta 0:158c61bb030f 340 {
mzta 0:158c61bb030f 341 mrb_value obj;
mzta 0:158c61bb030f 342 struct RRange *r, *o;
mzta 0:158c61bb030f 343
mzta 0:158c61bb030f 344 mrb_get_args(mrb, "o", &obj);
mzta 0:158c61bb030f 345
mzta 0:158c61bb030f 346 if (mrb_obj_equal(mrb, range, obj)) return mrb_true_value();
mzta 0:158c61bb030f 347 if (!mrb_obj_is_kind_of(mrb, obj, RANGE_CLASS)) {
mzta 0:158c61bb030f 348 return mrb_false_value();
mzta 0:158c61bb030f 349 }
mzta 0:158c61bb030f 350 if (mrb_type(obj) != MRB_TT_RANGE) return mrb_false_value();
mzta 0:158c61bb030f 351
mzta 0:158c61bb030f 352 r = mrb_range_ptr(range);
mzta 0:158c61bb030f 353 o = mrb_range_ptr(obj);
mzta 0:158c61bb030f 354 if (!mrb_eql(mrb, r->edges->beg, o->edges->beg) ||
mzta 0:158c61bb030f 355 !mrb_eql(mrb, r->edges->end, o->edges->end) ||
mzta 0:158c61bb030f 356 (r->excl != o->excl)) {
mzta 0:158c61bb030f 357 return mrb_false_value();
mzta 0:158c61bb030f 358 }
mzta 0:158c61bb030f 359 return mrb_true_value();
mzta 0:158c61bb030f 360 }
mzta 0:158c61bb030f 361
mzta 0:158c61bb030f 362 /* 15.2.14.4.15(x) */
mzta 0:158c61bb030f 363 static mrb_value
mzta 0:158c61bb030f 364 range_initialize_copy(mrb_state *mrb, mrb_value copy)
mzta 0:158c61bb030f 365 {
mzta 0:158c61bb030f 366 mrb_value src;
mzta 0:158c61bb030f 367 struct RRange *r;
mzta 0:158c61bb030f 368
mzta 0:158c61bb030f 369 mrb_get_args(mrb, "o", &src);
mzta 0:158c61bb030f 370
mzta 0:158c61bb030f 371 if (mrb_obj_equal(mrb, copy, src)) return copy;
mzta 0:158c61bb030f 372 if (!mrb_obj_is_instance_of(mrb, src, mrb_obj_class(mrb, copy))) {
mzta 0:158c61bb030f 373 mrb_raise(mrb, E_TYPE_ERROR, "wrong argument class");
mzta 0:158c61bb030f 374 }
mzta 0:158c61bb030f 375
mzta 0:158c61bb030f 376 r = mrb_range_ptr(src);
mzta 0:158c61bb030f 377 range_init(mrb, copy, r->edges->beg, r->edges->end, r->excl);
mzta 0:158c61bb030f 378
mzta 0:158c61bb030f 379 return copy;
mzta 0:158c61bb030f 380 }
mzta 0:158c61bb030f 381
mzta 0:158c61bb030f 382 mrb_value
mzta 0:158c61bb030f 383 mrb_get_values_at(mrb_state *mrb, mrb_value obj, mrb_int olen, mrb_int argc, const mrb_value *argv, mrb_value (*func)(mrb_state*, mrb_value, mrb_int))
mzta 0:158c61bb030f 384 {
mzta 0:158c61bb030f 385 mrb_int i, j, beg, len;
mzta 0:158c61bb030f 386 mrb_value result;
mzta 0:158c61bb030f 387 result = mrb_ary_new(mrb);
mzta 0:158c61bb030f 388
mzta 0:158c61bb030f 389 for (i = 0; i < argc; ++i) {
mzta 0:158c61bb030f 390 if (mrb_fixnum_p(argv[i])) {
mzta 0:158c61bb030f 391 mrb_ary_push(mrb, result, func(mrb, obj, mrb_fixnum(argv[i])));
mzta 0:158c61bb030f 392 }
mzta 0:158c61bb030f 393 else if (range_beg_len(mrb, argv[i], &beg, &len, olen, FALSE)) {
mzta 0:158c61bb030f 394 mrb_int const end = olen < beg + len ? olen : beg + len;
mzta 0:158c61bb030f 395 for (j = beg; j < end; ++j) {
mzta 0:158c61bb030f 396 mrb_ary_push(mrb, result, func(mrb, obj, j));
mzta 0:158c61bb030f 397 }
mzta 0:158c61bb030f 398
mzta 0:158c61bb030f 399 for (; j < beg + len; ++j) {
mzta 0:158c61bb030f 400 mrb_ary_push(mrb, result, mrb_nil_value());
mzta 0:158c61bb030f 401 }
mzta 0:158c61bb030f 402 }
mzta 0:158c61bb030f 403 else {
mzta 0:158c61bb030f 404 mrb_raisef(mrb, E_TYPE_ERROR, "invalid values selector: %S", argv[i]);
mzta 0:158c61bb030f 405 }
mzta 0:158c61bb030f 406 }
mzta 0:158c61bb030f 407
mzta 0:158c61bb030f 408 return result;
mzta 0:158c61bb030f 409 }
mzta 0:158c61bb030f 410
mzta 0:158c61bb030f 411 void
mzta 0:158c61bb030f 412 mrb_init_range(mrb_state *mrb)
mzta 0:158c61bb030f 413 {
mzta 0:158c61bb030f 414 struct RClass *r;
mzta 0:158c61bb030f 415
mzta 0:158c61bb030f 416 r = mrb_define_class(mrb, "Range", mrb->object_class); /* 15.2.14 */
mzta 0:158c61bb030f 417 MRB_SET_INSTANCE_TT(r, MRB_TT_RANGE);
mzta 0:158c61bb030f 418
mzta 0:158c61bb030f 419 mrb_define_method(mrb, r, "begin", mrb_range_beg, MRB_ARGS_NONE()); /* 15.2.14.4.3 */
mzta 0:158c61bb030f 420 mrb_define_method(mrb, r, "end", mrb_range_end, MRB_ARGS_NONE()); /* 15.2.14.4.5 */
mzta 0:158c61bb030f 421 mrb_define_method(mrb, r, "==", mrb_range_eq, MRB_ARGS_REQ(1)); /* 15.2.14.4.1 */
mzta 0:158c61bb030f 422 mrb_define_method(mrb, r, "===", mrb_range_include, MRB_ARGS_REQ(1)); /* 15.2.14.4.2 */
mzta 0:158c61bb030f 423 mrb_define_method(mrb, r, "exclude_end?", mrb_range_excl, MRB_ARGS_NONE()); /* 15.2.14.4.6 */
mzta 0:158c61bb030f 424 mrb_define_method(mrb, r, "first", mrb_range_beg, MRB_ARGS_NONE()); /* 15.2.14.4.7 */
mzta 0:158c61bb030f 425 mrb_define_method(mrb, r, "include?", mrb_range_include, MRB_ARGS_REQ(1)); /* 15.2.14.4.8 */
mzta 0:158c61bb030f 426 mrb_define_method(mrb, r, "initialize", mrb_range_initialize, MRB_ARGS_ANY()); /* 15.2.14.4.9 */
mzta 0:158c61bb030f 427 mrb_define_method(mrb, r, "last", mrb_range_end, MRB_ARGS_NONE()); /* 15.2.14.4.10 */
mzta 0:158c61bb030f 428 mrb_define_method(mrb, r, "member?", mrb_range_include, MRB_ARGS_REQ(1)); /* 15.2.14.4.11 */
mzta 0:158c61bb030f 429
mzta 0:158c61bb030f 430 mrb_define_method(mrb, r, "to_s", range_to_s, MRB_ARGS_NONE()); /* 15.2.14.4.12(x) */
mzta 0:158c61bb030f 431 mrb_define_method(mrb, r, "inspect", range_inspect, MRB_ARGS_NONE()); /* 15.2.14.4.13(x) */
mzta 0:158c61bb030f 432 mrb_define_method(mrb, r, "eql?", range_eql, MRB_ARGS_REQ(1)); /* 15.2.14.4.14(x) */
mzta 0:158c61bb030f 433 mrb_define_method(mrb, r, "initialize_copy", range_initialize_copy, MRB_ARGS_REQ(1)); /* 15.2.14.4.15(x) */
mzta 0:158c61bb030f 434 }
mzta 0:158c61bb030f 435