diff --git a/include/mruby/range.h b/include/mruby/range.h
index 4df5ccc70..b5626993a 100644
--- a/include/mruby/range.h
+++ b/include/mruby/range.h
@@ -38,7 +38,7 @@ struct RRange {
mrb_range_edges *edges;
mrb_bool excl;
};
-# define mrb_gc_free_range(mrb, p) mrb_free(mrb, ((struct RRange*)p)->edges)
+# define mrb_gc_free_range(mrb, p) mrb_free(mrb, (p)->edges)
# define RANGE_BEG(p) ((p)->edges->beg)
# define RANGE_END(p) ((p)->edges->end)
#endif
diff --git a/src/range.c b/src/range.c
index d2f897bd5..2f2521f5e 100644
--- a/src/range.c
+++ b/src/range.c
@@ -14,20 +14,8 @@
#define RANGE_INITIALIZED(p) ((p)->flags |= RANGE_INITIALIZED_MASK)
#define RANGE_INITIALIZED_P(p) ((p)->flags & RANGE_INITIALIZED_MASK)
-MRB_API struct RRange*
-mrb_range_ptr(mrb_state *mrb, mrb_value range)
-{
- struct RRange *r = mrb_range_raw_ptr(range);
-
- /* check for if #initialize_copy was removed [#3320] */
- if (!RANGE_INITIALIZED_P(r)) {
- mrb_raise(mrb, E_ARGUMENT_ERROR, "uninitialized range");
- }
- return r;
-}
-
static void
-range_check(mrb_state *mrb, mrb_value a, mrb_value b)
+r_check(mrb_state *mrb, mrb_value a, mrb_value b)
{
mrb_value ans;
enum mrb_vtype ta;
@@ -51,159 +39,6 @@ range_check(mrb_state *mrb, mrb_value a, mrb_value b)
}
}
-static void
-range_ptr_alloc_edges(mrb_state *mrb, struct RRange *r)
-{
-#ifndef MRB_RANGE_EMBED
- r->edges = (mrb_range_edges *)mrb_malloc(mrb, sizeof(mrb_range_edges));
-#endif
-}
-
-static struct RRange *
-range_ptr_init(mrb_state *mrb, struct RRange *r, mrb_value beg, mrb_value end, mrb_bool excl)
-{
- range_check(mrb, beg, end);
-
- if (r) {
- if (RANGE_INITIALIZED_P(r)) {
- /* Ranges are immutable, so that they should be initialized only once. */
- mrb_name_error(mrb, mrb_intern_lit(mrb, "initialize"), "`initialize' called twice");
- }
- else {
- range_ptr_alloc_edges(mrb, r);
- }
- }
- else {
- r = (struct RRange*)mrb_obj_alloc(mrb, MRB_TT_RANGE, mrb->range_class);
- range_ptr_alloc_edges(mrb, r);
- }
-
- RANGE_BEG(r) = beg;
- RANGE_END(r) = end;
- RANGE_EXCL(r) = excl;
- RANGE_INITIALIZED(r);
-
- return r;
-}
-
-static void
-range_ptr_replace(mrb_state *mrb, struct RRange *r, mrb_value beg, mrb_value end, mrb_bool excl)
-{
- range_ptr_init(mrb, r, beg, end, excl);
- mrb_write_barrier(mrb, (struct RBasic*)r);
-}
-
-MRB_API mrb_value
-mrb_range_new(mrb_state *mrb, mrb_value beg, mrb_value end, mrb_bool excl)
-{
- struct RRange *r = range_ptr_init(mrb, NULL, beg, end, excl);
- return mrb_range_value(r);
-}
-
-/*
- * call-seq:
- * rng.first => obj
- * rng.begin => obj
- *
- * Returns the first object in rng.
- */
-static mrb_value
-range_beg(mrb_state *mrb, mrb_value range)
-{
- return mrb_range_beg(mrb, range);
-}
-
-/*
- * call-seq:
- * rng.end => obj
- * rng.last => obj
- *
- * Returns the object that defines the end of rng.
- *
- * (1..10).end #=> 10
- * (1...10).end #=> 10
- */
-
-static mrb_value
-range_end(mrb_state *mrb, mrb_value range)
-{
- return mrb_range_end(mrb, range);
-}
-
-/*
- * call-seq:
- * range.exclude_end? => true or false
- *
- * Returns true if range excludes its end value.
- */
-mrb_value
-mrb_range_excl(mrb_state *mrb, mrb_value range)
-{
- return mrb_bool_value(mrb_range_excl_p(mrb, range));
-}
-
-/*
- * call-seq:
- * Range.new(start, end, exclusive=false) => range
- *
- * Constructs a range using the given start and end. If the third
- * parameter is omitted or is false, the range will include
- * the end object; otherwise, it will be excluded.
- */
-
-mrb_value
-mrb_range_initialize(mrb_state *mrb, mrb_value range)
-{
- mrb_value beg, end;
- mrb_bool exclusive;
- mrb_int n;
-
- n = mrb_get_args(mrb, "oo|b", &beg, &end, &exclusive);
- if (n != 3) {
- exclusive = FALSE;
- }
- range_ptr_replace(mrb, mrb_range_raw_ptr(range), beg, end, exclusive);
- return range;
-}
-/*
- * call-seq:
- * range == obj => true or false
- *
- * Returns true only if
- * 1) obj is a Range,
- * 2) obj has equivalent beginning and end items (by comparing them with ==),
- * 3) obj has the same #exclude_end? setting as rng.
- *
- * (0..2) == (0..2) #=> true
- * (0..2) == Range.new(0,2) #=> true
- * (0..2) == (0...2) #=> false
- *
- */
-
-mrb_value
-mrb_range_eq(mrb_state *mrb, mrb_value range)
-{
- struct RRange *rr;
- struct RRange *ro;
- mrb_value obj, v1, v2;
-
- mrb_get_args(mrb, "o", &obj);
-
- if (mrb_obj_equal(mrb, range, obj)) return mrb_true_value();
- if (!mrb_obj_is_instance_of(mrb, obj, mrb_obj_class(mrb, range))) { /* same class? */
- return mrb_false_value();
- }
-
- rr = mrb_range_ptr(mrb, range);
- ro = mrb_range_ptr(mrb, obj);
- v1 = mrb_funcall(mrb, RANGE_BEG(rr), "==", 1, RANGE_BEG(ro));
- v2 = mrb_funcall(mrb, RANGE_END(rr), "==", 1, RANGE_END(ro));
- if (!mrb_bool(v1) || !mrb_bool(v2) || RANGE_EXCL(rr) != RANGE_EXCL(ro)) {
- return mrb_false_value();
- }
- return mrb_true_value();
-}
-
static mrb_bool
r_le(mrb_state *mrb, mrb_value a, mrb_value b)
{
@@ -241,15 +76,154 @@ r_ge(mrb_state *mrb, mrb_value a, mrb_value b)
return FALSE;
}
+static void
+range_ptr_alloc_edges(mrb_state *mrb, struct RRange *r)
+{
+#ifndef MRB_RANGE_EMBED
+ r->edges = (mrb_range_edges *)mrb_malloc(mrb, sizeof(mrb_range_edges));
+#endif
+}
+
+static struct RRange *
+range_ptr_init(mrb_state *mrb, struct RRange *r, mrb_value beg, mrb_value end, mrb_bool excl)
+{
+ r_check(mrb, beg, end);
+
+ if (r) {
+ if (RANGE_INITIALIZED_P(r)) {
+ /* Ranges are immutable, so that they should be initialized only once. */
+ mrb_name_error(mrb, mrb_intern_lit(mrb, "initialize"), "`initialize' called twice");
+ }
+ else {
+ range_ptr_alloc_edges(mrb, r);
+ }
+ }
+ else {
+ r = (struct RRange*)mrb_obj_alloc(mrb, MRB_TT_RANGE, mrb->range_class);
+ range_ptr_alloc_edges(mrb, r);
+ }
+
+ RANGE_BEG(r) = beg;
+ RANGE_END(r) = end;
+ RANGE_EXCL(r) = excl;
+ RANGE_INITIALIZED(r);
+
+ return r;
+}
+
+static void
+range_ptr_replace(mrb_state *mrb, struct RRange *r, mrb_value beg, mrb_value end, mrb_bool excl)
+{
+ range_ptr_init(mrb, r, beg, end, excl);
+ mrb_write_barrier(mrb, (struct RBasic*)r);
+}
+
+/*
+ * call-seq:
+ * rng.first => obj
+ * rng.begin => obj
+ *
+ * Returns the first object in rng.
+ */
+static mrb_value
+range_beg(mrb_state *mrb, mrb_value range)
+{
+ return mrb_range_beg(mrb, range);
+}
+
+/*
+ * call-seq:
+ * rng.end => obj
+ * rng.last => obj
+ *
+ * Returns the object that defines the end of rng.
+ *
+ * (1..10).end #=> 10
+ * (1...10).end #=> 10
+ */
+static mrb_value
+range_end(mrb_state *mrb, mrb_value range)
+{
+ return mrb_range_end(mrb, range);
+}
+
+/*
+ * call-seq:
+ * range.exclude_end? => true or false
+ *
+ * Returns true if range excludes its end value.
+ */
+static mrb_value
+range_excl(mrb_state *mrb, mrb_value range)
+{
+ return mrb_bool_value(mrb_range_excl_p(mrb, range));
+}
+
+/*
+ * call-seq:
+ * Range.new(start, end, exclusive=false) => range
+ *
+ * Constructs a range using the given start and end. If the third
+ * parameter is omitted or is false, the range will include
+ * the end object; otherwise, it will be excluded.
+ */
+static mrb_value
+range_initialize(mrb_state *mrb, mrb_value range)
+{
+ mrb_value beg, end;
+ mrb_bool exclusive = FALSE;
+ mrb_int n;
+
+ n = mrb_get_args(mrb, "oo|b", &beg, &end, &exclusive);
+ range_ptr_replace(mrb, mrb_range_raw_ptr(range), beg, end, exclusive);
+ return range;
+}
+
+/*
+ * call-seq:
+ * range == obj => true or false
+ *
+ * Returns true only if
+ * 1) obj is a Range,
+ * 2) obj has equivalent beginning and end items (by comparing them with ==),
+ * 3) obj has the same #exclude_end? setting as rng.
+ *
+ * (0..2) == (0..2) #=> true
+ * (0..2) == Range.new(0,2) #=> true
+ * (0..2) == (0...2) #=> false
+ */
+static mrb_value
+range_eq(mrb_state *mrb, mrb_value range)
+{
+ struct RRange *rr;
+ struct RRange *ro;
+ mrb_value obj, v1, v2;
+
+ mrb_get_args(mrb, "o", &obj);
+
+ if (mrb_obj_equal(mrb, range, obj)) return mrb_true_value();
+ if (!mrb_obj_is_instance_of(mrb, obj, mrb_obj_class(mrb, range))) { /* same class? */
+ return mrb_false_value();
+ }
+
+ rr = mrb_range_ptr(mrb, range);
+ ro = mrb_range_ptr(mrb, obj);
+ v1 = mrb_funcall(mrb, RANGE_BEG(rr), "==", 1, RANGE_BEG(ro));
+ v2 = mrb_funcall(mrb, RANGE_END(rr), "==", 1, RANGE_END(ro));
+ if (!mrb_bool(v1) || !mrb_bool(v2) || RANGE_EXCL(rr) != RANGE_EXCL(ro)) {
+ return mrb_false_value();
+ }
+ return mrb_true_value();
+}
+
/*
* call-seq:
* range === obj => true or false
* range.member?(val) => true or false
* range.include?(val) => true or false
- *
*/
-mrb_value
-mrb_range_include(mrb_state *mrb, mrb_value range)
+static mrb_value
+range_include(mrb_state *mrb, mrb_value range)
{
mrb_value val;
struct RRange *r = mrb_range_ptr(mrb, range);
@@ -267,39 +241,6 @@ mrb_range_include(mrb_state *mrb, mrb_value range)
return mrb_bool_value(include_p);
}
-MRB_API mrb_int
-mrb_range_beg_len(mrb_state *mrb, mrb_value range, mrb_int *begp, mrb_int *lenp, mrb_int len, mrb_bool trunc)
-{
- mrb_int beg, end;
- struct RRange *r;
-
- if (mrb_type(range) != MRB_TT_RANGE) return 0;
- r = mrb_range_ptr(mrb, range);
-
- beg = mrb_int(mrb, RANGE_BEG(r));
- end = mrb_int(mrb, RANGE_END(r));
-
- if (beg < 0) {
- beg += len;
- if (beg < 0) return 2;
- }
-
- if (trunc) {
- if (beg > len) return 2;
- if (end > len) end = len;
- }
-
- if (end < 0) end += len;
- if (!RANGE_EXCL(r) && (!trunc || end < len))
- end++; /* include end point */
- len = end - beg;
- if (len < 0) len = 0;
-
- *begp = beg;
- *lenp = len;
- return 1;
-}
-
/* 15.2.14.4.12(x) */
/*
* call-seq:
@@ -307,7 +248,6 @@ mrb_range_beg_len(mrb_state *mrb, mrb_value range, mrb_int *begp, mrb_int *lenp,
*
* Convert this range object to a printable form.
*/
-
static mrb_value
range_to_s(mrb_state *mrb, mrb_value range)
{
@@ -332,7 +272,6 @@ range_to_s(mrb_state *mrb, mrb_value range)
* inspect to convert the start and end
* objects).
*/
-
static mrb_value
range_inspect(mrb_state *mrb, mrb_value range)
{
@@ -360,9 +299,7 @@ range_inspect(mrb_state *mrb, mrb_value range)
* (0..2).eql?(0..2) #=> true
* (0..2).eql?(Range.new(0,2)) #=> true
* (0..2).eql?(0...2) #=> false
- *
*/
-
static mrb_value
range_eql(mrb_state *mrb, mrb_value range)
{
@@ -372,9 +309,7 @@ range_eql(mrb_state *mrb, mrb_value range)
mrb_get_args(mrb, "o", &obj);
if (mrb_obj_equal(mrb, range, obj)) return mrb_true_value();
- if (!mrb_obj_is_kind_of(mrb, obj, mrb->range_class)) {
- return mrb_false_value();
- }
+ if (!mrb_obj_is_kind_of(mrb, obj, mrb->range_class)) return mrb_false_value();
if (mrb_type(obj) != MRB_TT_RANGE) return mrb_false_value();
r = mrb_range_ptr(mrb, range);
@@ -445,6 +380,57 @@ mrb_gc_mark_range(mrb_state *mrb, struct RRange *r)
}
}
+MRB_API struct RRange*
+mrb_range_ptr(mrb_state *mrb, mrb_value range)
+{
+ struct RRange *r = mrb_range_raw_ptr(range);
+
+ /* check for if #initialize_copy was removed [#3320] */
+ if (!RANGE_INITIALIZED_P(r)) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "uninitialized range");
+ }
+ return r;
+}
+
+MRB_API mrb_value
+mrb_range_new(mrb_state *mrb, mrb_value beg, mrb_value end, mrb_bool excl)
+{
+ struct RRange *r = range_ptr_init(mrb, NULL, beg, end, excl);
+ return mrb_range_value(r);
+}
+
+MRB_API mrb_int
+mrb_range_beg_len(mrb_state *mrb, mrb_value range, mrb_int *begp, mrb_int *lenp, mrb_int len, mrb_bool trunc)
+{
+ mrb_int beg, end;
+ struct RRange *r;
+
+ if (mrb_type(range) != MRB_TT_RANGE) return 0;
+ r = mrb_range_ptr(mrb, range);
+
+ beg = mrb_int(mrb, RANGE_BEG(r));
+ end = mrb_int(mrb, RANGE_END(r));
+
+ if (beg < 0) {
+ beg += len;
+ if (beg < 0) return 2;
+ }
+
+ if (trunc) {
+ if (beg > len) return 2;
+ if (end > len) end = len;
+ }
+
+ if (end < 0) end += len;
+ if (!RANGE_EXCL(r) && (!trunc || end < len)) end++; /* include end point */
+ len = end - beg;
+ if (len < 0) len = 0;
+
+ *begp = beg;
+ *lenp = len;
+ return 1;
+}
+
void
mrb_init_range(mrb_state *mrb)
{
@@ -456,15 +442,14 @@ mrb_init_range(mrb_state *mrb)
mrb_define_method(mrb, r, "begin", range_beg, MRB_ARGS_NONE()); /* 15.2.14.4.3 */
mrb_define_method(mrb, r, "end", range_end, MRB_ARGS_NONE()); /* 15.2.14.4.5 */
- mrb_define_method(mrb, r, "==", mrb_range_eq, MRB_ARGS_REQ(1)); /* 15.2.14.4.1 */
- mrb_define_method(mrb, r, "===", mrb_range_include, MRB_ARGS_REQ(1)); /* 15.2.14.4.2 */
- mrb_define_method(mrb, r, "exclude_end?", mrb_range_excl, MRB_ARGS_NONE()); /* 15.2.14.4.6 */
+ mrb_define_method(mrb, r, "==", range_eq, MRB_ARGS_REQ(1)); /* 15.2.14.4.1 */
+ mrb_define_method(mrb, r, "===", range_include, MRB_ARGS_REQ(1)); /* 15.2.14.4.2 */
+ mrb_define_method(mrb, r, "exclude_end?", range_excl, MRB_ARGS_NONE()); /* 15.2.14.4.6 */
mrb_define_method(mrb, r, "first", range_beg, MRB_ARGS_NONE()); /* 15.2.14.4.7 */
- mrb_define_method(mrb, r, "include?", mrb_range_include, MRB_ARGS_REQ(1)); /* 15.2.14.4.8 */
- mrb_define_method(mrb, r, "initialize", mrb_range_initialize, MRB_ARGS_ANY()); /* 15.2.14.4.9 */
+ mrb_define_method(mrb, r, "include?", range_include, MRB_ARGS_REQ(1)); /* 15.2.14.4.8 */
+ mrb_define_method(mrb, r, "initialize", range_initialize, MRB_ARGS_ANY()); /* 15.2.14.4.9 */
mrb_define_method(mrb, r, "last", range_end, MRB_ARGS_NONE()); /* 15.2.14.4.10 */
- mrb_define_method(mrb, r, "member?", mrb_range_include, MRB_ARGS_REQ(1)); /* 15.2.14.4.11 */
-
+ mrb_define_method(mrb, r, "member?", range_include, MRB_ARGS_REQ(1)); /* 15.2.14.4.11 */
mrb_define_method(mrb, r, "to_s", range_to_s, MRB_ARGS_NONE()); /* 15.2.14.4.12(x) */
mrb_define_method(mrb, r, "inspect", range_inspect, MRB_ARGS_NONE()); /* 15.2.14.4.13(x) */
mrb_define_method(mrb, r, "eql?", range_eql, MRB_ARGS_REQ(1)); /* 15.2.14.4.14(x) */