Ruby
2.1.3p242(2014-09-19revision47630)
Main Page
Modules
Data Structures
Files
File List
Globals
compar.c
Go to the documentation of this file.
1
/**********************************************************************
2
3
compar.c -
4
5
$Author: nobu $
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
14
VALUE
rb_mComparable
;
15
16
static
ID
cmp
;
17
18
void
19
rb_cmperr
(
VALUE
x,
VALUE
y)
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
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
42
rb_invcmp
(
VALUE
x,
VALUE
y)
43
{
44
VALUE
invcmp =
rb_exec_recursive
(
invcmp_recursive
, x, y);
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_funcallv
(arg1,
cmp
, 1, &arg2);
59
}
60
61
static
VALUE
62
cmp_eq
(
VALUE
*a)
63
{
64
VALUE
c
=
rb_exec_recursive_paired_outer
(
cmp_eq_recursive
, a[0], a[1], a[1]);
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
72
cmp_failed
(
void
)
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 ignored and returns false.
87
*/
88
89
static
VALUE
90
cmp_equal
(
VALUE
x,
VALUE
y)
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
109
cmp_gt
(
VALUE
x,
VALUE
y)
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
126
cmp_ge
(
VALUE
x,
VALUE
y)
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
143
cmp_lt
(
VALUE
x,
VALUE
y)
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
160
cmp_le
(
VALUE
x,
VALUE
y)
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
184
cmp_between
(
VALUE
x,
VALUE
min,
VALUE
max
)
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
231
Init_Comparable
(
void
)
232
{
233
#undef rb_intern
234
#define rb_intern(str) rb_intern_const(str)
235
236
rb_mComparable
=
rb_define_module
(
"Comparable"
);
237
rb_define_method
(
rb_mComparable
,
"=="
,
cmp_equal
, 1);
238
rb_define_method
(
rb_mComparable
,
">"
,
cmp_gt
, 1);
239
rb_define_method
(
rb_mComparable
,
">="
,
cmp_ge
, 1);
240
rb_define_method
(
rb_mComparable
,
"<"
,
cmp_lt
, 1);
241
rb_define_method
(
rb_mComparable
,
"<="
,
cmp_le
, 1);
242
rb_define_method
(
rb_mComparable
,
"between?"
,
cmp_between
, 2);
243
244
cmp
=
rb_intern
(
"<=>"
);
245
}
246
Generated on Mon Sep 22 2014 11:05:19 for Ruby by
1.8.2