Ruby  2.0.0p645(2015-04-13revision50299)
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) || BUILTIN_TYPE(y) == T_FLOAT) {
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 invcmp_recursive(VALUE x, VALUE y, int recursive)
36 {
37  if (recursive) return Qnil;
38  return rb_check_funcall(y, cmp, 1, &x);
39 }
40 
41 VALUE
43 {
45  if (invcmp == Qundef || NIL_P(invcmp)) {
46  return Qnil;
47  }
48  else {
49  int result = -rb_cmpint(invcmp, x, y);
50  return INT2FIX(result);
51  }
52 }
53 
54 static VALUE
55 cmp_eq_recursive(VALUE arg1, VALUE arg2, int recursive)
56 {
57  if (recursive) return Qfalse;
58  return rb_funcall(arg1, cmp, 1, arg2);
59 }
60 
61 static VALUE
63 {
65 
66  if (NIL_P(c)) return Qfalse;
67  if (rb_cmpint(c, a[0], a[1]) == 0) return Qtrue;
68  return Qfalse;
69 }
70 
71 static VALUE
73 {
74  return Qfalse;
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 0. Also returns true if
83  * _obj_ and _other_ are the same object.
84  *
85  * Even if _obj_ <=> _other_ raised an exception, the exception
86  * is ignoread and returns false.
87  */
88 
89 static VALUE
91 {
92  VALUE a[2];
93 
94  if (x == y) return Qtrue;
95 
96  a[0] = x; a[1] = y;
97  return rb_rescue(cmp_eq, (VALUE)a, cmp_failed, 0);
98 }
99 
100 /*
101  * call-seq:
102  * obj > other -> true or false
103  *
104  * Compares two objects based on the receiver's <code><=></code>
105  * method, returning true if it returns 1.
106  */
107 
108 static VALUE
110 {
111  VALUE c = rb_funcall(x, cmp, 1, y);
112 
113  if (rb_cmpint(c, x, y) > 0) return Qtrue;
114  return Qfalse;
115 }
116 
117 /*
118  * call-seq:
119  * obj >= other -> true or false
120  *
121  * Compares two objects based on the receiver's <code><=></code>
122  * method, returning true if it returns 0 or 1.
123  */
124 
125 static VALUE
127 {
128  VALUE c = rb_funcall(x, cmp, 1, y);
129 
130  if (rb_cmpint(c, x, y) >= 0) return Qtrue;
131  return Qfalse;
132 }
133 
134 /*
135  * call-seq:
136  * obj < other -> true or false
137  *
138  * Compares two objects based on the receiver's <code><=></code>
139  * method, returning true if it returns -1.
140  */
141 
142 static VALUE
144 {
145  VALUE c = rb_funcall(x, cmp, 1, y);
146 
147  if (rb_cmpint(c, x, y) < 0) return Qtrue;
148  return Qfalse;
149 }
150 
151 /*
152  * call-seq:
153  * obj <= other -> true or false
154  *
155  * Compares two objects based on the receiver's <code><=></code>
156  * method, returning true if it returns -1 or 0.
157  */
158 
159 static VALUE
161 {
162  VALUE c = rb_funcall(x, cmp, 1, y);
163 
164  if (rb_cmpint(c, x, y) <= 0) return Qtrue;
165  return Qfalse;
166 }
167 
168 /*
169  * call-seq:
170  * obj.between?(min, max) -> true or false
171  *
172  * Returns <code>false</code> if <i>obj</i> <code><=></code>
173  * <i>min</i> is less than zero or if <i>anObject</i> <code><=></code>
174  * <i>max</i> is greater than zero, <code>true</code> otherwise.
175  *
176  * 3.between?(1, 5) #=> true
177  * 6.between?(1, 5) #=> false
178  * 'cat'.between?('ant', 'dog') #=> true
179  * 'gnu'.between?('ant', 'dog') #=> false
180  *
181  */
182 
183 static VALUE
185 {
186  if (RTEST(cmp_lt(x, min))) return Qfalse;
187  if (RTEST(cmp_gt(x, max))) return Qfalse;
188  return Qtrue;
189 }
190 
191 /*
192  * The <code>Comparable</code> mixin is used by classes whose objects
193  * may be ordered. The class must define the <code><=></code> operator,
194  * which compares the receiver against another object, returning -1, 0,
195  * or +1 depending on whether the receiver is less than, equal to, or
196  * greater than the other object. If the other object is not comparable
197  * then the <code><=></code> operator should return nil.
198  * <code>Comparable</code> uses
199  * <code><=></code> to implement the conventional comparison operators
200  * (<code><</code>, <code><=</code>, <code>==</code>, <code>>=</code>,
201  * and <code>></code>) and the method <code>between?</code>.
202  *
203  * class SizeMatters
204  * include Comparable
205  * attr :str
206  * def <=>(anOther)
207  * str.size <=> anOther.str.size
208  * end
209  * def initialize(str)
210  * @str = str
211  * end
212  * def inspect
213  * @str
214  * end
215  * end
216  *
217  * s1 = SizeMatters.new("Z")
218  * s2 = SizeMatters.new("YY")
219  * s3 = SizeMatters.new("XXX")
220  * s4 = SizeMatters.new("WWWW")
221  * s5 = SizeMatters.new("VVVVV")
222  *
223  * s1 < s2 #=> true
224  * s4.between?(s1, s3) #=> false
225  * s4.between?(s3, s5) #=> true
226  * [ s3, s2, s5, s4, s1 ].sort #=> [Z, YY, XXX, WWWW, VVVVV]
227  *
228  */
229 
230 void
232 {
233 #undef rb_intern
234 #define rb_intern(str) rb_intern_const(str)
235 
236  rb_mComparable = rb_define_module("Comparable");
243 
244  cmp = rb_intern("<=>");
245 }
static VALUE classname(VALUE klass, int *permanent)
Returns +classpath+ of klass, if it is named, or +nil+ for anonymous +class+/+module+.
Definition: variable.c:160
static VALUE cmp_gt(VALUE x, VALUE y)
Definition: compar.c:109
void Init_Comparable(void)
Definition: compar.c:231
static VALUE cmp_eq(VALUE *a)
Definition: compar.c:62
static VALUE cmp_le(VALUE x, VALUE y)
Definition: compar.c:160
static int max(int a, int b)
Definition: strftime.c:141
static VALUE invcmp_recursive(VALUE x, VALUE y, int recursive)
Definition: compar.c:35
#define Qtrue
Definition: ruby.h:434
static VALUE cmp_equal(VALUE x, VALUE y)
Definition: compar.c:90
VALUE rb_funcall(VALUE, ID, int,...)
Calls a method.
Definition: vm_eval.c:773
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:1788
VALUE rb_exec_recursive(VALUE(*)(VALUE, VALUE, int), VALUE, VALUE)
Definition: thread.c:4881
int rb_cmpint(VALUE val, VALUE a, VALUE b)
Definition: bignum.c:97
#define rb_intern(str)
const char * rb_obj_classname(VALUE)
Definition: variable.c:396
VALUE rb_rescue(VALUE(*b_proc)(ANYARGS), VALUE data1, VALUE(*r_proc)(ANYARGS), VALUE data2)
Definition: eval.c:763
VALUE rb_mComparable
Definition: compar.c:14
#define NIL_P(v)
Definition: ruby.h:446
#define T_FLOAT
Definition: ruby.h:489
#define Qfalse
Definition: ruby.h:433
static VALUE cmp_between(VALUE x, VALUE min, VALUE max)
Definition: compar.c:184
VALUE rb_check_funcall(VALUE, ID, int, VALUE *)
Definition: vm_eval.c:408
static VALUE cmp_ge(VALUE x, VALUE y)
Definition: compar.c:126
unsigned long ID
Definition: ruby.h:105
#define Qnil
Definition: ruby.h:435
#define BUILTIN_TYPE(x)
Definition: ruby.h:510
unsigned long VALUE
Definition: ruby.h:104
static VALUE result
Definition: nkf.c:40
static VALUE cmp_failed(void)
Definition: compar.c:72
static VALUE cmp_eq_recursive(VALUE arg1, VALUE arg2, int recursive)
Definition: compar.c:55
static VALUE cmp_lt(VALUE x, VALUE y)
Definition: compar.c:143
#define INT2FIX(i)
Definition: ruby.h:241
#define RTEST(v)
Definition: ruby.h:445
VALUE rb_exec_recursive_paired_outer(VALUE(*)(VALUE, VALUE, int), VALUE, VALUE, VALUE)
Definition: thread.c:4916
#define StringValuePtr(v)
Definition: ruby.h:547
VALUE rb_inspect(VALUE)
Definition: object.c:411
#define SPECIAL_CONST_P(x)
Definition: ruby.h:1143
VALUE rb_define_module(const char *name)
Definition: class.c:606
#define Qundef
Definition: ruby.h:436
VALUE rb_invcmp(VALUE x, VALUE y)
Definition: compar.c:42
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1344
VALUE rb_eArgError
Definition: error.c:517
static ID cmp
Definition: compar.c:16
void rb_cmperr(VALUE x, VALUE y)
Definition: compar.c:19