Groonga 3.0.9 Source Code Document
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
range.c
Go to the documentation of this file.
1 #include "mruby.h"
2 #include "mruby/range.h"
3 
4 static mrb_bool
5 r_le(mrb_state *mrb, mrb_value a, mrb_value b)
6 {
7  mrb_value r = mrb_funcall(mrb, a, "<=>", 1, b); /* compare result */
8  /* output :a < b => -1, a = b => 0, a > b => +1 */
9 
10  if (mrb_type(r) == MRB_TT_FIXNUM) {
11  mrb_int c = mrb_fixnum(r);
12  if (c == 0 || c == -1) return TRUE;
13  }
14 
15  return FALSE;
16 }
17 
18 static mrb_bool
19 r_lt(mrb_state *mrb, mrb_value a, mrb_value b)
20 {
21  mrb_value r = mrb_funcall(mrb, a, "<=>", 1, b);
22  /* output :a < b => -1, a = b => 0, a > b => +1 */
23 
24  if (mrb_type(r) == MRB_TT_FIXNUM) {
25  if (mrb_fixnum(r) == -1) return TRUE;
26  }
27 
28  return FALSE;
29 }
30 
31 /*
32  * call-seq:
33  * rng.cover?(obj) -> true or false
34  *
35  * Returns <code>true</code> if +obj+ is between the begin and end of
36  * the range.
37  *
38  * This tests <code>begin <= obj <= end</code> when #exclude_end? is +false+
39  * and <code>begin <= obj < end</code> when #exclude_end? is +true+.
40  *
41  * ("a".."z").cover?("c") #=> true
42  * ("a".."z").cover?("5") #=> false
43  * ("a".."z").cover?("cc") #=> true
44  */
45 static mrb_value
46 mrb_range_cover(mrb_state *mrb, mrb_value range)
47 {
48  mrb_value val;
49  struct RRange *r = mrb_range_ptr(range);
50  mrb_value beg, end;
51 
52  mrb_get_args(mrb, "o", &val);
53 
54  beg = r->edges->beg;
55  end = r->edges->end;
56 
57  if (r_le(mrb, beg, val)) {
58  if (r->excl) {
59  if (r_lt(mrb, val, end))
60  return mrb_true_value();
61  }
62  else {
63  if (r_le(mrb, val, end))
64  return mrb_true_value();
65  }
66  }
67 
68  return mrb_false_value();
69 }
70 
71 /*
72  * call-seq:
73  * rng.first -> obj
74  * rng.first(n) -> an_array
75  *
76  * Returns the first object in the range, or an array of the first +n+
77  * elements.
78  *
79  * (10..20).first #=> 10
80  * (10..20).first(3) #=> [10, 11, 12]
81  */
82 static mrb_value
83 mrb_range_first(mrb_state *mrb, mrb_value range)
84 {
85  mrb_value num;
86  mrb_value array;
87  struct RRange *r = mrb_range_ptr(range);
88 
89  if (mrb_get_args(mrb, "|o", &num) == 0) {
90  return r->edges->beg;
91  }
92 
93  array = mrb_funcall(mrb, range, "to_a", 0);
94  return mrb_funcall(mrb, array, "first", 1, mrb_to_int(mrb, num));
95 }
96 
97 /*
98  * call-seq:
99  * rng.last -> obj
100  * rng.last(n) -> an_array
101  *
102  * Returns the last object in the range,
103  * or an array of the last +n+ elements.
104  *
105  * Note that with no arguments +last+ will return the object that defines
106  * the end of the range even if #exclude_end? is +true+.
107  *
108  * (10..20).last #=> 20
109  * (10...20).last #=> 20
110  * (10..20).last(3) #=> [18, 19, 20]
111  * (10...20).last(3) #=> [17, 18, 19]
112  */
113 static mrb_value
114 mrb_range_last(mrb_state *mrb, mrb_value range)
115 {
116  mrb_value num;
117  mrb_value array;
118  struct RRange *r = mrb_range_ptr(range);
119 
120  if (mrb_get_args(mrb, "|o", &num) == 0) {
121  return r->edges->end;
122  }
123 
124  array = mrb_funcall(mrb, range, "to_a", 0);
125  return mrb_funcall(mrb, array, "last", 1, mrb_to_int(mrb, num));
126 }
127 
128 void
130 {
131  struct RClass * s = mrb_class_get(mrb, "Range");
132 
133  mrb_define_method(mrb, s, "cover?", mrb_range_cover, MRB_ARGS_REQ(1));
134  mrb_define_method(mrb, s, "first", mrb_range_first, MRB_ARGS_OPT(1));
135  mrb_define_method(mrb, s, "last", mrb_range_last, MRB_ARGS_OPT(1));
136 }
137 
138 void
140 {
141 }