mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
range: Refactor range.h/range.c
Functions order, name, linkage and so on.
This commit is contained in:
@@ -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
|
||||
|
||||
+201
-216
@@ -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 <i>rng</i>.
|
||||
*/
|
||||
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 <i>rng</i>.
|
||||
*
|
||||
* (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 <code>true</code> if <i>range</i> 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 <i>start</i> and <i>end</i>. If the third
|
||||
* parameter is omitted or is <code>false</code>, the <i>range</i> 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 <code>true</code> only if
|
||||
* 1) <i>obj</i> is a Range,
|
||||
* 2) <i>obj</i> has equivalent beginning and end items (by comparing them with <code>==</code>),
|
||||
* 3) <i>obj</i> has the same #exclude_end? setting as <i>rng</t>.
|
||||
*
|
||||
* (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 <i>rng</i>.
|
||||
*/
|
||||
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 <i>rng</i>.
|
||||
*
|
||||
* (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 <code>true</code> if <i>range</i> 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 <i>start</i> and <i>end</i>. If the third
|
||||
* parameter is omitted or is <code>false</code>, the <i>range</i> 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 <code>true</code> only if
|
||||
* 1) <i>obj</i> is a Range,
|
||||
* 2) <i>obj</i> has equivalent beginning and end items (by comparing them with <code>==</code>),
|
||||
* 3) <i>obj</i> has the same #exclude_end? setting as <i>rng</t>.
|
||||
*
|
||||
* (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)
|
||||
* <code>inspect</code> 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) */
|
||||
|
||||
Reference in New Issue
Block a user