Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: mruby_mbed_web mirb_mbed
range.c
00001 #include "mruby.h" 00002 #include "mruby/range.h" 00003 #include <math.h> 00004 00005 static mrb_bool 00006 r_le(mrb_state *mrb, mrb_value a, mrb_value b) 00007 { 00008 mrb_value r = mrb_funcall(mrb, a, "<=>", 1, b); /* compare result */ 00009 /* output :a < b => -1, a = b => 0, a > b => +1 */ 00010 00011 if (mrb_fixnum_p(r)) { 00012 mrb_int c = mrb_fixnum(r); 00013 if (c == 0 || c == -1) return TRUE; 00014 } 00015 00016 return FALSE; 00017 } 00018 00019 static mrb_bool 00020 r_lt(mrb_state *mrb, mrb_value a, mrb_value b) 00021 { 00022 mrb_value r = mrb_funcall(mrb, a, "<=>", 1, b); 00023 /* output :a < b => -1, a = b => 0, a > b => +1 */ 00024 00025 return mrb_fixnum_p(r) && mrb_fixnum(r) == -1; 00026 } 00027 00028 /* 00029 * call-seq: 00030 * rng.cover?(obj) -> true or false 00031 * 00032 * Returns <code>true</code> if +obj+ is between the begin and end of 00033 * the range. 00034 * 00035 * This tests <code>begin <= obj <= end</code> when #exclude_end? is +false+ 00036 * and <code>begin <= obj < end</code> when #exclude_end? is +true+. 00037 * 00038 * ("a".."z").cover?("c") #=> true 00039 * ("a".."z").cover?("5") #=> false 00040 * ("a".."z").cover?("cc") #=> true 00041 */ 00042 static mrb_value 00043 mrb_range_cover(mrb_state *mrb, mrb_value range) 00044 { 00045 mrb_value val; 00046 struct RRange *r = mrb_range_ptr(range); 00047 mrb_value beg, end; 00048 00049 mrb_get_args(mrb, "o", &val); 00050 00051 beg = r->edges->beg; 00052 end = r->edges->end; 00053 00054 if (r_le(mrb, beg, val)) { 00055 if (r->excl) { 00056 if (r_lt(mrb, val, end)) 00057 return mrb_true_value(); 00058 } 00059 else { 00060 if (r_le(mrb, val, end)) 00061 return mrb_true_value(); 00062 } 00063 } 00064 00065 return mrb_false_value(); 00066 } 00067 00068 /* 00069 * call-seq: 00070 * rng.first -> obj 00071 * rng.first(n) -> an_array 00072 * 00073 * Returns the first object in the range, or an array of the first +n+ 00074 * elements. 00075 * 00076 * (10..20).first #=> 10 00077 * (10..20).first(3) #=> [10, 11, 12] 00078 */ 00079 static mrb_value 00080 mrb_range_first(mrb_state *mrb, mrb_value range) 00081 { 00082 mrb_int num; 00083 mrb_value array; 00084 struct RRange *r = mrb_range_ptr(range); 00085 00086 if (mrb_get_args(mrb, "|i", &num) == 0) { 00087 return r->edges->beg; 00088 } 00089 00090 array = mrb_funcall(mrb, range, "to_a", 0); 00091 return mrb_funcall(mrb, array, "first", 1, mrb_fixnum_value(num)); 00092 } 00093 00094 /* 00095 * call-seq: 00096 * rng.last -> obj 00097 * rng.last(n) -> an_array 00098 * 00099 * Returns the last object in the range, 00100 * or an array of the last +n+ elements. 00101 * 00102 * Note that with no arguments +last+ will return the object that defines 00103 * the end of the range even if #exclude_end? is +true+. 00104 * 00105 * (10..20).last #=> 20 00106 * (10...20).last #=> 20 00107 * (10..20).last(3) #=> [18, 19, 20] 00108 * (10...20).last(3) #=> [17, 18, 19] 00109 */ 00110 static mrb_value 00111 mrb_range_last(mrb_state *mrb, mrb_value range) 00112 { 00113 mrb_value num; 00114 mrb_value array; 00115 struct RRange *r = mrb_range_ptr(range); 00116 00117 if (mrb_get_args(mrb, "|o", &num) == 0) { 00118 return r->edges->end; 00119 } 00120 00121 array = mrb_funcall(mrb, range, "to_a", 0); 00122 return mrb_funcall(mrb, array, "last", 1, mrb_to_int(mrb, num)); 00123 } 00124 00125 /* 00126 * call-seq: 00127 * rng.size -> num 00128 * 00129 * Returns the number of elements in the range. Both the begin and the end of 00130 * the Range must be Numeric, otherwise nil is returned. 00131 * 00132 * (10..20).size #=> 11 00133 * ('a'..'z').size #=> nil 00134 */ 00135 00136 static mrb_value 00137 mrb_range_size(mrb_state *mrb, mrb_value range) 00138 { 00139 struct RRange *r = mrb_range_ptr(range); 00140 mrb_value beg, end; 00141 double beg_f, end_f; 00142 mrb_bool num_p = TRUE; 00143 00144 beg = r->edges->beg; 00145 end = r->edges->end; 00146 if (mrb_fixnum_p(beg)) { 00147 beg_f = (double)mrb_fixnum(beg); 00148 } 00149 else if (mrb_float_p(beg)) { 00150 beg_f = mrb_float(beg); 00151 } 00152 else { 00153 num_p = FALSE; 00154 } 00155 if (mrb_fixnum_p(end)) { 00156 end_f = (double)mrb_fixnum(end); 00157 } 00158 else if (mrb_float_p(end)) { 00159 end_f = mrb_float(end); 00160 } 00161 else { 00162 num_p = FALSE; 00163 } 00164 if (num_p) { 00165 double f; 00166 00167 if (beg_f > end_f) return mrb_fixnum_value(0); 00168 f = end_f - beg_f; 00169 if (!r->excl) { 00170 return mrb_fixnum_value((mrb_int)ceil(f + 1)); 00171 } 00172 return mrb_fixnum_value((mrb_int)ceil(f)); 00173 } 00174 return mrb_nil_value(); 00175 } 00176 00177 void 00178 mrb_mruby_range_ext_gem_init(mrb_state* mrb) 00179 { 00180 struct RClass * s = mrb_class_get(mrb, "Range"); 00181 00182 mrb_define_method(mrb, s, "cover?", mrb_range_cover, MRB_ARGS_REQ(1)); 00183 mrb_define_method(mrb, s, "first", mrb_range_first, MRB_ARGS_OPT(1)); 00184 mrb_define_method(mrb, s, "last", mrb_range_last, MRB_ARGS_OPT(1)); 00185 mrb_define_method(mrb, s, "size", mrb_range_size, MRB_ARGS_NONE()); 00186 } 00187 00188 void 00189 mrb_mruby_range_ext_gem_final(mrb_state* mrb) 00190 { 00191 } 00192
Generated on Tue Jul 12 2022 18:00:35 by
1.7.2