Ruby  1.9.3p551(2014-11-13revision48407)
compar.c
Go to the documentation of this file.
1 /**********************************************************************
2 
3  compar.c -
4 
5  $Author: usa $
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
35 cmp_eq_recursive(VALUE arg1, VALUE arg2, int recursive)
36 {
37  if (recursive) return Qfalse;
38  return rb_funcall2(arg1, cmp, 1, &arg2);
39 }
40 
41 static VALUE
43 {
45 
46  if (NIL_P(c)) return Qfalse;
47  if (rb_cmpint(c, a[0], a[1]) == 0) return Qtrue;
48  return Qfalse;
49 }
50 
51 static VALUE
53 {
54  return Qfalse;
55 }
56 
57 /*
58  * call-seq:
59  * obj == other -> true or false
60  *
61  * Compares two objects based on the receiver's <code><=></code>
62  * method, returning true if it returns 0. Also returns true if
63  * _obj_ and _other_ are the same object.
64  */
65 
66 static VALUE
68 {
69  VALUE a[2];
70 
71  if (x == y) return Qtrue;
72 
73  a[0] = x; a[1] = y;
74  return rb_rescue(cmp_eq, (VALUE)a, cmp_failed, 0);
75 }
76 
77 /*
78  * call-seq:
79  * obj > other -> true or false
80  *
81  * Compares two objects based on the receiver's <code><=></code>
82  * method, returning true if it returns 1.
83  */
84 
85 static VALUE
87 {
88  VALUE c = rb_funcall(x, cmp, 1, y);
89 
90  if (rb_cmpint(c, x, y) > 0) return Qtrue;
91  return Qfalse;
92 }
93 
94 /*
95  * call-seq:
96  * obj >= other -> true or false
97  *
98  * Compares two objects based on the receiver's <code><=></code>
99  * method, returning true if it returns 0 or 1.
100  */
101 
102 static VALUE
104 {
105  VALUE c = rb_funcall(x, cmp, 1, y);
106 
107  if (rb_cmpint(c, x, y) >= 0) return Qtrue;
108  return Qfalse;
109 }
110 
111 /*
112  * call-seq:
113  * obj < other -> true or false
114  *
115  * Compares two objects based on the receiver's <code><=></code>
116  * method, returning true if it returns -1.
117  */
118 
119 static VALUE
121 {
122  VALUE c = rb_funcall(x, cmp, 1, y);
123 
124  if (rb_cmpint(c, x, y) < 0) return Qtrue;
125  return Qfalse;
126 }
127 
128 /*
129  * call-seq:
130  * obj <= other -> true or false
131  *
132  * Compares two objects based on the receiver's <code><=></code>
133  * method, returning true if it returns -1 or 0.
134  */
135 
136 static VALUE
138 {
139  VALUE c = rb_funcall(x, cmp, 1, y);
140 
141  if (rb_cmpint(c, x, y) <= 0) return Qtrue;
142  return Qfalse;
143 }
144 
145 /*
146  * call-seq:
147  * obj.between?(min, max) -> true or false
148  *
149  * Returns <code>false</code> if <i>obj</i> <code><=></code>
150  * <i>min</i> is less than zero or if <i>anObject</i> <code><=></code>
151  * <i>max</i> is greater than zero, <code>true</code> otherwise.
152  *
153  * 3.between?(1, 5) #=> true
154  * 6.between?(1, 5) #=> false
155  * 'cat'.between?('ant', 'dog') #=> true
156  * 'gnu'.between?('ant', 'dog') #=> false
157  *
158  */
159 
160 static VALUE
162 {
163  if (RTEST(cmp_lt(x, min))) return Qfalse;
164  if (RTEST(cmp_gt(x, max))) return Qfalse;
165  return Qtrue;
166 }
167 
168 /*
169  * The <code>Comparable</code> mixin is used by classes whose objects
170  * may be ordered. The class must define the <code><=></code> operator,
171  * which compares the receiver against another object, returning -1, 0,
172  * or +1 depending on whether the receiver is less than, equal to, or
173  * greater than the other object. If the other object is not comparable
174  * then the <code><=></code> operator should return nil.
175  * <code>Comparable</code> uses
176  * <code><=></code> to implement the conventional comparison operators
177  * (<code><</code>, <code><=</code>, <code>==</code>, <code>>=</code>,
178  * and <code>></code>) and the method <code>between?</code>.
179  *
180  * class SizeMatters
181  * include Comparable
182  * attr :str
183  * def <=>(anOther)
184  * str.size <=> anOther.str.size
185  * end
186  * def initialize(str)
187  * @str = str
188  * end
189  * def inspect
190  * @str
191  * end
192  * end
193  *
194  * s1 = SizeMatters.new("Z")
195  * s2 = SizeMatters.new("YY")
196  * s3 = SizeMatters.new("XXX")
197  * s4 = SizeMatters.new("WWWW")
198  * s5 = SizeMatters.new("VVVVV")
199  *
200  * s1 < s2 #=> true
201  * s4.between?(s1, s3) #=> false
202  * s4.between?(s3, s5) #=> true
203  * [ s3, s2, s5, s4, s1 ].sort #=> [Z, YY, XXX, WWWW, VVVVV]
204  *
205  */
206 
207 void
209 {
210 #undef rb_intern
211 #define rb_intern(str) rb_intern_const(str)
212 
213  rb_mComparable = rb_define_module("Comparable");
220 
221  cmp = rb_intern("<=>");
222 }
static VALUE cmp_gt(VALUE x, VALUE y)
Definition: compar.c:86
void Init_Comparable(void)
Definition: compar.c:208
static VALUE cmp_eq(VALUE *a)
Definition: compar.c:42
static VALUE cmp_le(VALUE x, VALUE y)
Definition: compar.c:137
unsigned long VALUE
Definition: ruby.h:88
static VALUE cmp_equal(VALUE x, VALUE y)
Definition: compar.c:67
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:1574
return Qtrue
Definition: tcltklib.c:9597
int rb_cmpint(VALUE val, VALUE a, VALUE b)
Definition: bignum.c:96
const char * rb_obj_classname(VALUE)
Definition: variable.c:318
VALUE rb_rescue(VALUE(*b_proc)(ANYARGS), VALUE data1, VALUE(*r_proc)(ANYARGS), VALUE data2)
Definition: eval.c:696
VALUE rb_mComparable
Definition: compar.c:14
return Qfalse
Definition: tcltklib.c:6768
#define NIL_P(v)
Definition: ruby.h:374
static VALUE classname(VALUE klass)
Definition: variable.c:144
static VALUE cmp_between(VALUE x, VALUE min, VALUE max)
Definition: compar.c:161
VALUE rb_funcall2(VALUE, ID, int, const VALUE *)
Calls a method.
Definition: vm_eval.c:669
static VALUE cmp_ge(VALUE x, VALUE y)
Definition: compar.c:103
unsigned long ID
Definition: ruby.h:89
static VALUE cmp_failed(void)
Definition: compar.c:52
VpDivd * c
Definition: bigdecimal.c:1163
static VALUE cmp_eq_recursive(VALUE arg1, VALUE arg2, int recursive)
Definition: compar.c:35
static VALUE cmp_lt(VALUE x, VALUE y)
Definition: compar.c:120
#define RTEST(v)
Definition: ruby.h:373
VALUE rb_exec_recursive_paired_outer(VALUE(*)(VALUE, VALUE, int), VALUE, VALUE, VALUE)
Definition: thread.c:4405
return rb_funcall(q->proc, ID_call, 0)
#define StringValuePtr(v)
Definition: ruby.h:467
VALUE rb_inspect(VALUE)
Definition: object.c:372
#define SPECIAL_CONST_P(x)
Definition: ruby.h:953
VALUE rb_define_module(const char *name)
Definition: class.c:587
#define rb_intern(str)
Real * a
Definition: bigdecimal.c:1140
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1210
VALUE rb_eArgError
Definition: error.c:468
static ID cmp
Definition: compar.c:16
void rb_cmperr(VALUE x, VALUE y)
Definition: compar.c:19