Ruby  1.9.3p448(2013-06-27revision41675)
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 }
static VALUE cmp_gt(VALUE x, VALUE y)
Definition: compar.c:79
void Init_Comparable(void)
Definition: compar.c:201
static VALUE cmp_eq(VALUE *a)
Definition: compar.c:35
static VALUE cmp_le(VALUE x, VALUE y)
Definition: compar.c:130
static int max(int a, int b)
#define Qtrue
Definition: ruby.h:366
static VALUE cmp_equal(VALUE x, VALUE y)
Definition: compar.c:60
VALUE rb_funcall(VALUE, ID, int,...)
Calls a method.
Definition: vm_eval.c:638
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:1574
static int min(int a, int b)
int rb_cmpint(VALUE val, VALUE a, VALUE b)
Definition: bignum.c:96
#define rb_intern(str)
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
#define NIL_P(v)
Definition: ruby.h:374
static VALUE classname(VALUE klass)
Definition: variable.c:144
#define Qfalse
Definition: ruby.h:365
static VALUE cmp_between(VALUE x, VALUE min, VALUE max)
Definition: compar.c:154
static VALUE cmp_ge(VALUE x, VALUE y)
Definition: compar.c:96
unsigned long ID
Definition: ruby.h:89
unsigned long VALUE
Definition: ruby.h:88
static VALUE cmp_failed(void)
Definition: compar.c:45
static VALUE cmp_lt(VALUE x, VALUE y)
Definition: compar.c:113
#define RTEST(v)
Definition: ruby.h:373
#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:586
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1209
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