Ruby
1.9.3p551(2014-11-13revision48407)
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: 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
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_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
42
cmp_eq
(
VALUE
*a)
43
{
44
VALUE
c =
rb_exec_recursive_paired_outer
(
cmp_eq_recursive
, a[0], a[1], a[1]);
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
52
cmp_failed
(
void
)
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
67
cmp_equal
(
VALUE
x,
VALUE
y)
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
86
cmp_gt
(
VALUE
x,
VALUE
y)
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
103
cmp_ge
(
VALUE
x,
VALUE
y)
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
120
cmp_lt
(
VALUE
x,
VALUE
y)
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
137
cmp_le
(
VALUE
x,
VALUE
y)
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
161
cmp_between
(
VALUE
x,
VALUE
min
,
VALUE
max
)
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
208
Init_Comparable
(
void
)
209
{
210
#undef rb_intern
211
#define rb_intern(str) rb_intern_const(str)
212
213
rb_mComparable
=
rb_define_module
(
"Comparable"
);
214
rb_define_method
(
rb_mComparable
,
"=="
,
cmp_equal
, 1);
215
rb_define_method
(
rb_mComparable
,
">"
,
cmp_gt
, 1);
216
rb_define_method
(
rb_mComparable
,
">="
,
cmp_ge
, 1);
217
rb_define_method
(
rb_mComparable
,
"<"
,
cmp_lt
, 1);
218
rb_define_method
(
rb_mComparable
,
"<="
,
cmp_le
, 1);
219
rb_define_method
(
rb_mComparable
,
"between?"
,
cmp_between
, 2);
220
221
cmp
=
rb_intern
(
"<=>"
);
222
}
223
Generated on Fri Nov 14 2014 16:01:57 for Ruby by
1.8.3