1 /**********************************************************************
6 created at: Thu Aug 26 14:39:48 JST 1993
8 Copyright (C) 1993-2007 Yukihiro Matsumoto
10 **********************************************************************/
12 #include "ruby/ruby.h"
19 rb_cmperr(VALUE x
, VALUE y
)
21 const char *classname
;
23 if (SPECIAL_CONST_P(y
)) {
25 classname
= StringValuePtr(y
);
28 classname
= rb_obj_classname(y
);
30 rb_raise(rb_eArgError
, "comparison of %s with %s failed",
31 rb_obj_classname(x
), classname
);
37 VALUE c
= rb_funcall(a
[0], cmp
, 1, a
[1]);
39 if (NIL_P(c
)) return Qfalse
;
40 if (rb_cmpint(c
, a
[0], a
[1]) == 0) return Qtrue
;
52 * obj == other => true or false
54 * Compares two objects based on the receiver's <code><=></code>
55 * method, returning true if it returns 0. Also returns true if
56 * _obj_ and _other_ are the same object.
60 cmp_equal(VALUE x
, VALUE y
)
64 if (x
== y
) return Qtrue
;
67 return rb_rescue(cmp_eq
, (VALUE
)a
, cmp_failed
, 0);
72 * obj > other => true or false
74 * Compares two objects based on the receiver's <code><=></code>
75 * method, returning true if it returns 1.
79 cmp_gt(VALUE x
, VALUE y
)
81 VALUE c
= rb_funcall(x
, cmp
, 1, y
);
83 if (rb_cmpint(c
, x
, y
) > 0) return Qtrue
;
89 * obj >= other => true or false
91 * Compares two objects based on the receiver's <code><=></code>
92 * method, returning true if it returns 0 or 1.
96 cmp_ge(VALUE x
, VALUE y
)
98 VALUE c
= rb_funcall(x
, cmp
, 1, y
);
100 if (rb_cmpint(c
, x
, y
) >= 0) return Qtrue
;
106 * obj < other => true or false
108 * Compares two objects based on the receiver's <code><=></code>
109 * method, returning true if it returns -1.
113 cmp_lt(VALUE x
, VALUE y
)
115 VALUE c
= rb_funcall(x
, cmp
, 1, y
);
117 if (rb_cmpint(c
, x
, y
) < 0) return Qtrue
;
123 * obj <= other => true or false
125 * Compares two objects based on the receiver's <code><=></code>
126 * method, returning true if it returns -1 or 0.
130 cmp_le(VALUE x
, VALUE y
)
132 VALUE c
= rb_funcall(x
, cmp
, 1, y
);
134 if (rb_cmpint(c
, x
, y
) <= 0) return Qtrue
;
140 * obj.between?(min, max) => true or false
142 * Returns <code>false</code> if <i>obj</i> <code><=></code>
143 * <i>min</i> is less than zero or if <i>anObject</i> <code><=></code>
144 * <i>max</i> is greater than zero, <code>true</code> otherwise.
146 * 3.between?(1, 5) #=> true
147 * 6.between?(1, 5) #=> false
148 * 'cat'.between?('ant', 'dog') #=> true
149 * 'gnu'.between?('ant', 'dog') #=> false
154 cmp_between(VALUE x
, VALUE min
, VALUE max
)
156 if (RTEST(cmp_lt(x
, min
))) return Qfalse
;
157 if (RTEST(cmp_gt(x
, max
))) return Qfalse
;
162 * The <code>Comparable</code> mixin is used by classes whose objects
163 * may be ordered. The class must define the <code><=></code> operator,
164 * which compares the receiver against another object, returning -1, 0,
165 * or +1 depending on whether the receiver is less than, equal to, or
166 * greater than the other object. <code>Comparable</code> uses
167 * <code><=></code> to implement the conventional comparison operators
168 * (<code><</code>, <code><=</code>, <code>==</code>, <code>>=</code>,
169 * and <code>></code>) and the method <code>between?</code>.
175 * str.size <=> anOther.str.size
177 * def initialize(str)
185 * s1 = SizeMatters.new("Z")
186 * s2 = SizeMatters.new("YY")
187 * s3 = SizeMatters.new("XXX")
188 * s4 = SizeMatters.new("WWWW")
189 * s5 = SizeMatters.new("VVVVV")
192 * s4.between?(s1, s3) #=> false
193 * s4.between?(s3, s5) #=> true
194 * [ s3, s2, s5, s4, s1 ].sort #=> [Z, YY, XXX, WWWW, VVVVV]
199 Init_Comparable(void)
201 rb_mComparable
= rb_define_module("Comparable");
202 rb_define_method(rb_mComparable
, "==", cmp_equal
, 1);
203 rb_define_method(rb_mComparable
, ">", cmp_gt
, 1);
204 rb_define_method(rb_mComparable
, ">=", cmp_ge
, 1);
205 rb_define_method(rb_mComparable
, "<", cmp_lt
, 1);
206 rb_define_method(rb_mComparable
, "<=", cmp_le
, 1);
207 rb_define_method(rb_mComparable
, "between?", cmp_between
, 2);
209 cmp
= rb_intern("<=>");