Changeset 439 for EcnlProtoTool/trunk/mruby-2.1.1/src/range.c
- Timestamp:
- Jul 9, 2020, 8:51:43 AM (4 years ago)
- Location:
- EcnlProtoTool/trunk/mruby-2.1.1
- Files:
-
- 1 edited
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
EcnlProtoTool/trunk/mruby-2.1.1/src/range.c
r331 r439 11 11 #include <mruby/array.h> 12 12 13 #define RANGE_CLASS (mrb_class_get(mrb, "Range")) 14 15 MRB_API struct RRange* 16 mrb_range_ptr(mrb_state *mrb, mrb_value v) 17 { 18 struct RRange *r = (struct RRange*)mrb_ptr(v); 19 20 if (r->edges == NULL) { 21 mrb_raise(mrb, E_ARGUMENT_ERROR, "uninitialized range"); 22 } 23 return r; 24 } 13 #define RANGE_INITIALIZED_MASK 1 14 #define RANGE_INITIALIZED(p) ((p)->flags |= RANGE_INITIALIZED_MASK) 15 #define RANGE_INITIALIZED_P(p) ((p)->flags & RANGE_INITIALIZED_MASK) 25 16 26 17 static void 27 range_check(mrb_state *mrb, mrb_value a, mrb_value b) 28 { 29 mrb_value ans; 18 r_check(mrb_state *mrb, mrb_value a, mrb_value b) 19 { 30 20 enum mrb_vtype ta; 31 21 enum mrb_vtype tb; 22 mrb_int n; 32 23 33 24 ta = mrb_type(a); 34 25 tb = mrb_type(b); 26 #ifdef MRB_WITHOUT_FLOAT 27 if (ta == MRB_TT_FIXNUM && tb == MRB_TT_FIXNUM ) { 28 #else 35 29 if ((ta == MRB_TT_FIXNUM || ta == MRB_TT_FLOAT) && 36 30 (tb == MRB_TT_FIXNUM || tb == MRB_TT_FLOAT)) { 31 #endif 37 32 return; 38 33 } 39 34 40 ans = mrb_funcall(mrb, a, "<=>", 1, b); 41 if (mrb_nil_p(ans)) { 42 /* can not be compared */ 35 n = mrb_cmp(mrb, a, b); 36 if (n == -2) { /* can not be compared */ 43 37 mrb_raise(mrb, E_ARGUMENT_ERROR, "bad value for range"); 44 38 } 45 39 } 46 40 47 MRB_API mrb_value 48 mrb_range_new(mrb_state *mrb, mrb_value beg, mrb_value end, mrb_bool excl) 49 { 50 struct RRange *r; 51 52 range_check(mrb, beg, end); 53 r = (struct RRange*)mrb_obj_alloc(mrb, MRB_TT_RANGE, RANGE_CLASS); 41 static mrb_bool 42 r_le(mrb_state *mrb, mrb_value a, mrb_value b) 43 { 44 mrb_int n = mrb_cmp(mrb, a, b); 45 46 if (n == 0 || n == -1) return TRUE; 47 return FALSE; 48 } 49 50 static mrb_bool 51 r_gt(mrb_state *mrb, mrb_value a, mrb_value b) 52 { 53 return mrb_cmp(mrb, a, b) == 1; 54 } 55 56 static mrb_bool 57 r_ge(mrb_state *mrb, mrb_value a, mrb_value b) 58 { 59 mrb_int n = mrb_cmp(mrb, a, b); 60 61 if (n == 0 || n == 1) return TRUE; 62 return FALSE; 63 } 64 65 static void 66 range_ptr_alloc_edges(mrb_state *mrb, struct RRange *r) 67 { 68 #ifndef MRB_RANGE_EMBED 54 69 r->edges = (mrb_range_edges *)mrb_malloc(mrb, sizeof(mrb_range_edges)); 55 r->edges->beg = beg; 56 r->edges->end = end; 57 r->excl = excl; 58 return mrb_range_value(r); 70 #endif 71 } 72 73 static struct RRange * 74 range_ptr_init(mrb_state *mrb, struct RRange *r, mrb_value beg, mrb_value end, mrb_bool excl) 75 { 76 r_check(mrb, beg, end); 77 78 if (r) { 79 if (RANGE_INITIALIZED_P(r)) { 80 /* Ranges are immutable, so that they should be initialized only once. */ 81 mrb_name_error(mrb, mrb_intern_lit(mrb, "initialize"), "'initialize' called twice"); 82 } 83 else { 84 range_ptr_alloc_edges(mrb, r); 85 } 86 } 87 else { 88 r = (struct RRange*)mrb_obj_alloc(mrb, MRB_TT_RANGE, mrb->range_class); 89 range_ptr_alloc_edges(mrb, r); 90 } 91 92 RANGE_BEG(r) = beg; 93 RANGE_END(r) = end; 94 RANGE_EXCL(r) = excl; 95 RANGE_INITIALIZED(r); 96 97 return r; 98 } 99 100 static void 101 range_ptr_replace(mrb_state *mrb, struct RRange *r, mrb_value beg, mrb_value end, mrb_bool excl) 102 { 103 range_ptr_init(mrb, r, beg, end, excl); 104 mrb_write_barrier(mrb, (struct RBasic*)r); 59 105 } 60 106 … … 66 112 * Returns the first object in <i>rng</i>. 67 113 */ 68 mrb_value 69 mrb_range_beg(mrb_state *mrb, mrb_value range) 70 { 71 struct RRange *r = mrb_range_ptr(mrb, range); 72 73 return r->edges->beg; 114 static mrb_value 115 range_beg(mrb_state *mrb, mrb_value range) 116 { 117 return mrb_range_beg(mrb, range); 74 118 } 75 119 … … 84 128 * (1...10).end #=> 10 85 129 */ 86 87 mrb_value 88 mrb_range_end(mrb_state *mrb, mrb_value range) 89 { 90 struct RRange *r = mrb_range_ptr(mrb, range); 91 92 return r->edges->end; 130 static mrb_value 131 range_end(mrb_state *mrb, mrb_value range) 132 { 133 return mrb_range_end(mrb, range); 93 134 } 94 135 … … 99 140 * Returns <code>true</code> if <i>range</i> excludes its end value. 100 141 */ 101 mrb_value 102 mrb_range_excl(mrb_state *mrb, mrb_value range) 103 { 104 struct RRange *r = mrb_range_ptr(mrb, range); 105 106 return mrb_bool_value(r->excl); 107 } 108 109 static void 110 range_init(mrb_state *mrb, mrb_value range, mrb_value beg, mrb_value end, mrb_bool exclude_end) 111 { 112 struct RRange *r = mrb_range_raw_ptr(range); 113 114 range_check(mrb, beg, end); 115 r->excl = exclude_end; 116 if (!r->edges) { 117 r->edges = (mrb_range_edges *)mrb_malloc(mrb, sizeof(mrb_range_edges)); 118 } 119 r->edges->beg = beg; 120 r->edges->end = end; 121 } 142 static mrb_value 143 range_excl(mrb_state *mrb, mrb_value range) 144 { 145 return mrb_bool_value(mrb_range_excl_p(mrb, range)); 146 } 147 122 148 /* 123 149 * call-seq: … … 128 154 * the end object; otherwise, it will be excluded. 129 155 */ 130 131 mrb_value 132 mrb_range_initialize(mrb_state *mrb, mrb_value range) 156 static mrb_value 157 range_initialize(mrb_state *mrb, mrb_value range) 133 158 { 134 159 mrb_value beg, end; 135 mrb_bool exclusive; 136 int n; 137 138 n = mrb_get_args(mrb, "oo|b", &beg, &end, &exclusive); 139 if (n != 3) { 140 exclusive = FALSE; 141 } 142 /* Ranges are immutable, so that they should be initialized only once. */ 143 if (mrb_range_raw_ptr(range)->edges) { 144 mrb_name_error(mrb, mrb_intern_lit(mrb, "initialize"), "`initialize' called twice"); 145 } 146 range_init(mrb, range, beg, end, exclusive); 160 mrb_bool exclusive = FALSE; 161 162 mrb_get_args(mrb, "oo|b", &beg, &end, &exclusive); 163 range_ptr_replace(mrb, mrb_range_raw_ptr(range), beg, end, exclusive); 147 164 return range; 148 165 } 166 149 167 /* 150 168 * call-seq: … … 159 177 * (0..2) == Range.new(0,2) #=> true 160 178 * (0..2) == (0...2) #=> false 161 * 162 */ 163 164 mrb_value 165 mrb_range_eq(mrb_state *mrb, mrb_value range) 179 */ 180 static mrb_value 181 range_eq(mrb_state *mrb, mrb_value range) 166 182 { 167 183 struct RRange *rr; 168 184 struct RRange *ro; 169 mrb_value obj, v1, v2; 185 mrb_value obj; 186 mrb_bool v1, v2; 170 187 171 188 mrb_get_args(mrb, "o", &obj); … … 178 195 rr = mrb_range_ptr(mrb, range); 179 196 ro = mrb_range_ptr(mrb, obj); 180 v1 = mrb_ funcall(mrb, rr->edges->beg, "==", 1, ro->edges->beg);181 v2 = mrb_ funcall(mrb, rr->edges->end, "==", 1, ro->edges->end);182 if (! mrb_bool(v1) || !mrb_bool(v2) || rr->excl != ro->excl) {197 v1 = mrb_equal(mrb, RANGE_BEG(rr), RANGE_BEG(ro)); 198 v2 = mrb_equal(mrb, RANGE_END(rr), RANGE_END(ro)); 199 if (!v1 || !v2 || RANGE_EXCL(rr) != RANGE_EXCL(ro)) { 183 200 return mrb_false_value(); 184 201 } 185 202 return mrb_true_value(); 186 }187 188 static mrb_bool189 r_le(mrb_state *mrb, mrb_value a, mrb_value b)190 {191 mrb_value r = mrb_funcall(mrb, a, "<=>", 1, b); /* compare result */192 /* output :a < b => -1, a = b => 0, a > b => +1 */193 194 if (mrb_fixnum_p(r)) {195 mrb_int c = mrb_fixnum(r);196 if (c == 0 || c == -1) return TRUE;197 }198 199 return FALSE;200 }201 202 static mrb_bool203 r_gt(mrb_state *mrb, mrb_value a, mrb_value b)204 {205 mrb_value r = mrb_funcall(mrb, a, "<=>", 1, b);206 /* output :a < b => -1, a = b => 0, a > b => +1 */207 208 return mrb_fixnum_p(r) && mrb_fixnum(r) == 1;209 }210 211 static mrb_bool212 r_ge(mrb_state *mrb, mrb_value a, mrb_value b)213 {214 mrb_value r = mrb_funcall(mrb, a, "<=>", 1, b); /* compare result */215 /* output :a < b => -1, a = b => 0, a > b => +1 */216 217 if (mrb_fixnum_p(r)) {218 mrb_int c = mrb_fixnum(r);219 if (c == 0 || c == 1) return TRUE;220 }221 222 return FALSE;223 203 } 224 204 … … 228 208 * range.member?(val) => true or false 229 209 * range.include?(val) => true or false 230 * 231 */ 232 mrb_value 233 mrb_range_include(mrb_state *mrb, mrb_value range) 210 */ 211 static mrb_value 212 range_include(mrb_state *mrb, mrb_value range) 234 213 { 235 214 mrb_value val; … … 240 219 mrb_get_args(mrb, "o", &val); 241 220 242 beg = r->edges->beg;243 end = r->edges->end;244 include_p = r_le(mrb, beg, val) && /* beg <= val */245 ( r->excl? r_gt(mrb, end, val) /* end > val */246 : r_ge(mrb, end, val)); /* end >= val */221 beg = RANGE_BEG(r); 222 end = RANGE_END(r); 223 include_p = r_le(mrb, beg, val) && /* beg <= val */ 224 (RANGE_EXCL(r) ? r_gt(mrb, end, val) /* end > val */ 225 : r_ge(mrb, end, val)); /* end >= val */ 247 226 248 227 return mrb_bool_value(include_p); 249 }250 251 MRB_API mrb_int252 mrb_range_beg_len(mrb_state *mrb, mrb_value range, mrb_int *begp, mrb_int *lenp, mrb_int len, mrb_bool trunc)253 {254 mrb_int beg, end;255 struct RRange *r;256 257 if (mrb_type(range) != MRB_TT_RANGE) return 0;258 r = mrb_range_ptr(mrb, range);259 260 beg = mrb_int(mrb, r->edges->beg);261 end = mrb_int(mrb, r->edges->end);262 263 if (beg < 0) {264 beg += len;265 if (beg < 0) return 2;266 }267 268 if (trunc) {269 if (beg > len) return 2;270 if (end > len) end = len;271 }272 273 if (end < 0) end += len;274 if (!r->excl && (!trunc || end < len))275 end++; /* include end point */276 len = end - beg;277 if (len < 0) len = 0;278 279 *begp = beg;280 *lenp = len;281 return 1;282 228 } 283 229 … … 289 235 * Convert this range object to a printable form. 290 236 */ 291 292 237 static mrb_value 293 238 range_to_s(mrb_state *mrb, mrb_value range) … … 296 241 struct RRange *r = mrb_range_ptr(mrb, range); 297 242 298 str = mrb_obj_as_string(mrb, r->edges->beg);299 str2 = mrb_obj_as_string(mrb, r->edges->end);243 str = mrb_obj_as_string(mrb, RANGE_BEG(r)); 244 str2 = mrb_obj_as_string(mrb, RANGE_END(r)); 300 245 str = mrb_str_dup(mrb, str); 301 mrb_str_cat(mrb, str, "...", r->excl? 3 : 2);246 mrb_str_cat(mrb, str, "...", RANGE_EXCL(r) ? 3 : 2); 302 247 mrb_str_cat_str(mrb, str, str2); 303 248 … … 314 259 * objects). 315 260 */ 316 317 261 static mrb_value 318 262 range_inspect(mrb_state *mrb, mrb_value range) … … 321 265 struct RRange *r = mrb_range_ptr(mrb, range); 322 266 323 str = mrb_inspect(mrb, r->edges->beg);324 str2 = mrb_inspect(mrb, r->edges->end);267 str = mrb_inspect(mrb, RANGE_BEG(r)); 268 str2 = mrb_inspect(mrb, RANGE_END(r)); 325 269 str = mrb_str_dup(mrb, str); 326 mrb_str_cat(mrb, str, "...", r->excl? 3 : 2);270 mrb_str_cat(mrb, str, "...", RANGE_EXCL(r) ? 3 : 2); 327 271 mrb_str_cat_str(mrb, str, str2); 328 272 … … 342 286 * (0..2).eql?(Range.new(0,2)) #=> true 343 287 * (0..2).eql?(0...2) #=> false 344 * 345 */ 346 288 */ 347 289 static mrb_value 348 290 range_eql(mrb_state *mrb, mrb_value range) … … 354 296 355 297 if (mrb_obj_equal(mrb, range, obj)) return mrb_true_value(); 356 if (!mrb_obj_is_kind_of(mrb, obj, RANGE_CLASS)) { 357 return mrb_false_value(); 358 } 359 if (mrb_type(obj) != MRB_TT_RANGE) return mrb_false_value(); 298 if (!mrb_obj_is_kind_of(mrb, obj, mrb->range_class)) return mrb_false_value(); 299 if (!mrb_range_p(obj)) return mrb_false_value(); 360 300 361 301 r = mrb_range_ptr(mrb, range); 362 302 o = mrb_range_ptr(mrb, obj); 363 if (!mrb_eql(mrb, r->edges->beg, o->edges->beg) ||364 !mrb_eql(mrb, r->edges->end, o->edges->end) ||365 ( r->excl != o->excl)) {303 if (!mrb_eql(mrb, RANGE_BEG(r), RANGE_BEG(o)) || 304 !mrb_eql(mrb, RANGE_END(r), RANGE_END(o)) || 305 (RANGE_EXCL(r) != RANGE_EXCL(o))) { 366 306 return mrb_false_value(); 367 307 } … … 384 324 385 325 r = mrb_range_ptr(mrb, src); 386 range_ init(mrb, copy, r->edges->beg, r->edges->end, r->excl);326 range_ptr_replace(mrb, mrb_range_raw_ptr(copy), RANGE_BEG(r), RANGE_END(r), RANGE_EXCL(r)); 387 327 388 328 return copy; … … 400 340 mrb_ary_push(mrb, result, func(mrb, obj, mrb_fixnum(argv[i]))); 401 341 } 402 else if (mrb_range_beg_len(mrb, argv[i], &beg, &len, olen, FALSE) == 1) {342 else if (mrb_range_beg_len(mrb, argv[i], &beg, &len, olen, FALSE) == MRB_RANGE_OK) { 403 343 mrb_int const end = olen < beg + len ? olen : beg + len; 404 344 for (j = beg; j < end; ++j) { … … 411 351 } 412 352 else { 413 mrb_raisef(mrb, E_TYPE_ERROR, "invalid values selector: % S", argv[i]);353 mrb_raisef(mrb, E_TYPE_ERROR, "invalid values selector: %v", argv[i]); 414 354 } 415 355 } 416 356 417 357 return result; 358 } 359 360 void 361 mrb_gc_mark_range(mrb_state *mrb, struct RRange *r) 362 { 363 if (RANGE_INITIALIZED_P(r)) { 364 mrb_gc_mark_value(mrb, RANGE_BEG(r)); 365 mrb_gc_mark_value(mrb, RANGE_END(r)); 366 } 367 } 368 369 MRB_API struct RRange* 370 mrb_range_ptr(mrb_state *mrb, mrb_value range) 371 { 372 struct RRange *r = mrb_range_raw_ptr(range); 373 374 /* check for if #initialize_copy was removed [#3320] */ 375 if (!RANGE_INITIALIZED_P(r)) { 376 mrb_raise(mrb, E_ARGUMENT_ERROR, "uninitialized range"); 377 } 378 return r; 379 } 380 381 MRB_API mrb_value 382 mrb_range_new(mrb_state *mrb, mrb_value beg, mrb_value end, mrb_bool excl) 383 { 384 struct RRange *r = range_ptr_init(mrb, NULL, beg, end, excl); 385 return mrb_range_value(r); 386 } 387 388 MRB_API enum mrb_range_beg_len 389 mrb_range_beg_len(mrb_state *mrb, mrb_value range, mrb_int *begp, mrb_int *lenp, mrb_int len, mrb_bool trunc) 390 { 391 mrb_int beg, end; 392 struct RRange *r; 393 394 if (!mrb_range_p(range)) return MRB_RANGE_TYPE_MISMATCH; 395 r = mrb_range_ptr(mrb, range); 396 397 beg = mrb_int(mrb, RANGE_BEG(r)); 398 end = mrb_int(mrb, RANGE_END(r)); 399 400 if (beg < 0) { 401 beg += len; 402 if (beg < 0) return MRB_RANGE_OUT; 403 } 404 405 if (trunc) { 406 if (beg > len) return MRB_RANGE_OUT; 407 if (end > len) end = len; 408 } 409 410 if (end < 0) end += len; 411 if (!RANGE_EXCL(r) && (!trunc || end < len)) end++; /* include end point */ 412 len = end - beg; 413 if (len < 0) len = 0; 414 415 *begp = beg; 416 *lenp = len; 417 return MRB_RANGE_OK; 418 418 } 419 419 … … 424 424 425 425 r = mrb_define_class(mrb, "Range", mrb->object_class); /* 15.2.14 */ 426 mrb->range_class = r; 426 427 MRB_SET_INSTANCE_TT(r, MRB_TT_RANGE); 427 428 428 mrb_define_method(mrb, r, "begin", mrb_range_beg, MRB_ARGS_NONE()); /* 15.2.14.4.3 */ 429 mrb_define_method(mrb, r, "end", mrb_range_end, MRB_ARGS_NONE()); /* 15.2.14.4.5 */ 430 mrb_define_method(mrb, r, "==", mrb_range_eq, MRB_ARGS_REQ(1)); /* 15.2.14.4.1 */ 431 mrb_define_method(mrb, r, "===", mrb_range_include, MRB_ARGS_REQ(1)); /* 15.2.14.4.2 */ 432 mrb_define_method(mrb, r, "exclude_end?", mrb_range_excl, MRB_ARGS_NONE()); /* 15.2.14.4.6 */ 433 mrb_define_method(mrb, r, "first", mrb_range_beg, MRB_ARGS_NONE()); /* 15.2.14.4.7 */ 434 mrb_define_method(mrb, r, "include?", mrb_range_include, MRB_ARGS_REQ(1)); /* 15.2.14.4.8 */ 435 mrb_define_method(mrb, r, "initialize", mrb_range_initialize, MRB_ARGS_ANY()); /* 15.2.14.4.9 */ 436 mrb_define_method(mrb, r, "last", mrb_range_end, MRB_ARGS_NONE()); /* 15.2.14.4.10 */ 437 mrb_define_method(mrb, r, "member?", mrb_range_include, MRB_ARGS_REQ(1)); /* 15.2.14.4.11 */ 438 429 mrb_define_method(mrb, r, "begin", range_beg, MRB_ARGS_NONE()); /* 15.2.14.4.3 */ 430 mrb_define_method(mrb, r, "end", range_end, MRB_ARGS_NONE()); /* 15.2.14.4.5 */ 431 mrb_define_method(mrb, r, "==", range_eq, MRB_ARGS_REQ(1)); /* 15.2.14.4.1 */ 432 mrb_define_method(mrb, r, "===", range_include, MRB_ARGS_REQ(1)); /* 15.2.14.4.2 */ 433 mrb_define_method(mrb, r, "exclude_end?", range_excl, MRB_ARGS_NONE()); /* 15.2.14.4.6 */ 434 mrb_define_method(mrb, r, "first", range_beg, MRB_ARGS_NONE()); /* 15.2.14.4.7 */ 435 mrb_define_method(mrb, r, "include?", range_include, MRB_ARGS_REQ(1)); /* 15.2.14.4.8 */ 436 mrb_define_method(mrb, r, "initialize", range_initialize, MRB_ARGS_ANY()); /* 15.2.14.4.9 */ 437 mrb_define_method(mrb, r, "last", range_end, MRB_ARGS_NONE()); /* 15.2.14.4.10 */ 438 mrb_define_method(mrb, r, "member?", range_include, MRB_ARGS_REQ(1)); /* 15.2.14.4.11 */ 439 439 mrb_define_method(mrb, r, "to_s", range_to_s, MRB_ARGS_NONE()); /* 15.2.14.4.12(x) */ 440 440 mrb_define_method(mrb, r, "inspect", range_inspect, MRB_ARGS_NONE()); /* 15.2.14.4.13(x) */
Note:
See TracChangeset
for help on using the changeset viewer.