Ruby
1.9.3p392(2013-02-22revision39386)
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: 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
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
cmp_eq
(
VALUE
*a)
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
45
cmp_failed
(
void
)
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
60
cmp_equal
(
VALUE
x,
VALUE
y)
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
79
cmp_gt
(
VALUE
x,
VALUE
y)
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
96
cmp_ge
(
VALUE
x,
VALUE
y)
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
113
cmp_lt
(
VALUE
x,
VALUE
y)
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
130
cmp_le
(
VALUE
x,
VALUE
y)
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
154
cmp_between
(
VALUE
x,
VALUE
min
,
VALUE
max
)
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
201
Init_Comparable
(
void
)
202
{
203
#undef rb_intern
204
#define rb_intern(str) rb_intern_const(str)
205
206
rb_mComparable
=
rb_define_module
(
"Comparable"
);
207
rb_define_method
(
rb_mComparable
,
"=="
,
cmp_equal
, 1);
208
rb_define_method
(
rb_mComparable
,
">"
,
cmp_gt
, 1);
209
rb_define_method
(
rb_mComparable
,
">="
,
cmp_ge
, 1);
210
rb_define_method
(
rb_mComparable
,
"<"
,
cmp_lt
, 1);
211
rb_define_method
(
rb_mComparable
,
"<="
,
cmp_le
, 1);
212
rb_define_method
(
rb_mComparable
,
"between?"
,
cmp_between
, 2);
213
214
cmp
=
rb_intern
(
"<=>"
);
215
}
216
Generated on Tue Feb 26 2013 08:40:17 for Ruby by
1.8.3