Ruby  1.9.3p392(2013-02-22revision39386)
compar.c
Go to the documentation of this file.
1 /**********************************************************************
2 
3  compar.c -
4 
5  $Author: marcandre $
6  created at: Thu Aug 26 14:39:48 JST 1993
7 
8  Copyright (C) 1993-2007 Yukihiro Matsumoto
9 
10 **********************************************************************/
11 
12 #include "ruby/ruby.h"
13 
15 
16 static ID cmp;
17 
18 void
20 {
21  const char *classname;
22 
23  if (SPECIAL_CONST_P(y)) {
24  y = rb_inspect(y);
25  classname = StringValuePtr(y);
26  }
27  else {
28  classname = rb_obj_classname(y);
29  }
30  rb_raise(rb_eArgError, "comparison of %s with %s failed",
31  rb_obj_classname(x), classname);
32 }
33 
34 static VALUE
36 {
37  VALUE c = rb_funcall(a[0], cmp, 1, a[1]);
38 
39  if (NIL_P(c)) return Qfalse;
40  if (rb_cmpint(c, a[0], a[1]) == 0) return Qtrue;
41  return Qfalse;
42 }
43 
44 static VALUE
46 {
47  return Qfalse;
48 }
49 
50 /*
51  * call-seq:
52  * obj == other -> true or false
53  *
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.
57  */
58 
59 static VALUE
61 {
62  VALUE a[2];
63 
64  if (x == y) return Qtrue;
65 
66  a[0] = x; a[1] = y;
67  return rb_rescue(cmp_eq, (VALUE)a, cmp_failed, 0);
68 }
69 
70 /*
71  * call-seq:
72  * obj > other -> true or false
73  *
74  * Compares two objects based on the receiver's <code><=></code>
75  * method, returning true if it returns 1.
76  */
77 
78 static VALUE
80 {
81  VALUE c = rb_funcall(x, cmp, 1, y);
82 
83  if (rb_cmpint(c, x, y) > 0) return Qtrue;
84  return Qfalse;
85 }
86 
87 /*
88  * call-seq:
89  * obj >= other -> true or false
90  *
91  * Compares two objects based on the receiver's <code><=></code>
92  * method, returning true if it returns 0 or 1.
93  */
94 
95 static VALUE
97 {
98  VALUE c = rb_funcall(x, cmp, 1, y);
99 
100  if (rb_cmpint(c, x, y) >= 0) return Qtrue;
101  return Qfalse;
102 }
103 
104 /*
105  * call-seq:
106  * obj < other -> true or false
107  *
108  * Compares two objects based on the receiver's <code><=></code>
109  * method, returning true if it returns -1.
110  */
111 
112 static VALUE
114 {
115  VALUE c = rb_funcall(x, cmp, 1, y);
116 
117  if (rb_cmpint(c, x, y) < 0) return Qtrue;
118  return Qfalse;
119 }
120 
121 /*
122  * call-seq:
123  * obj <= other -> true or false
124  *
125  * Compares two objects based on the receiver's <code><=></code>
126  * method, returning true if it returns -1 or 0.
127  */
128 
129 static VALUE
131 {
132  VALUE c = rb_funcall(x, cmp, 1, y);
133 
134  if (rb_cmpint(c, x, y) <= 0) return Qtrue;
135  return Qfalse;
136 }
137 
138 /*
139  * call-seq:
140  * obj.between?(min, max) -> true or false
141  *
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.
145  *
146  * 3.between?(1, 5) #=> true
147  * 6.between?(1, 5) #=> false
148  * 'cat'.between?('ant', 'dog') #=> true
149  * 'gnu'.between?('ant', 'dog') #=> false
150  *
151  */
152 
153 static VALUE
155 {
156  if (RTEST(cmp_lt(x, min))) return Qfalse;
157  if (RTEST(cmp_gt(x, max))) return Qfalse;
158  return Qtrue;
159 }
160 
161 /*
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. If the other object is not comparable
167  * then the <code><=></code> operator should return nil.
168  * <code>Comparable</code> uses
169  * <code><=></code> to implement the conventional comparison operators
170  * (<code><</code>, <code><=</code>, <code>==</code>, <code>>=</code>,
171  * and <code>></code>) and the method <code>between?</code>.
172  *
173  * class SizeMatters
174  * include Comparable
175  * attr :str
176  * def <=>(anOther)
177  * str.size <=> anOther.str.size
178  * end
179  * def initialize(str)
180  * @str = str
181  * end
182  * def inspect
183  * @str
184  * end
185  * end
186  *
187  * s1 = SizeMatters.new("Z")
188  * s2 = SizeMatters.new("YY")
189  * s3 = SizeMatters.new("XXX")
190  * s4 = SizeMatters.new("WWWW")
191  * s5 = SizeMatters.new("VVVVV")
192  *
193  * s1 < s2 #=> true
194  * s4.between?(s1, s3) #=> false
195  * s4.between?(s3, s5) #=> true
196  * [ s3, s2, s5, s4, s1 ].sort #=> [Z, YY, XXX, WWWW, VVVVV]
197  *
198  */
199 
200 void
202 {
203 #undef rb_intern
204 #define rb_intern(str) rb_intern_const(str)
205 
206  rb_mComparable = rb_define_module("Comparable");
213 
214  cmp = rb_intern("<=>");
215 }
216