mbed I/F binding for mruby
Dependents: mruby_mbed_web mirb_mbed
mbed-mruby
How to use
Class
src/range.c@0:158c61bb030f, 2015-03-25 (annotated)
- Committer:
- mzta
- Date:
- Wed Mar 25 17:36:16 2015 +0000
- Revision:
- 0:158c61bb030f
mirb_mbed initial commit;
Who changed what in which revision?
User | Revision | Line number | New 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 |