00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "ruby/ruby.h"
00013
00014 VALUE rb_mComparable;
00015
00016 static ID cmp;
00017
00018 void
00019 rb_cmperr(VALUE x, VALUE y)
00020 {
00021 const char *classname;
00022
00023 if (SPECIAL_CONST_P(y)) {
00024 y = rb_inspect(y);
00025 classname = StringValuePtr(y);
00026 }
00027 else {
00028 classname = rb_obj_classname(y);
00029 }
00030 rb_raise(rb_eArgError, "comparison of %s with %s failed",
00031 rb_obj_classname(x), classname);
00032 }
00033
00034 static VALUE
00035 cmp_eq(VALUE *a)
00036 {
00037 VALUE c = rb_funcall(a[0], cmp, 1, a[1]);
00038
00039 if (NIL_P(c)) return Qfalse;
00040 if (rb_cmpint(c, a[0], a[1]) == 0) return Qtrue;
00041 return Qfalse;
00042 }
00043
00044 static VALUE
00045 cmp_failed(void)
00046 {
00047 return Qfalse;
00048 }
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059 static VALUE
00060 cmp_equal(VALUE x, VALUE y)
00061 {
00062 VALUE a[2];
00063
00064 if (x == y) return Qtrue;
00065
00066 a[0] = x; a[1] = y;
00067 return rb_rescue(cmp_eq, (VALUE)a, cmp_failed, 0);
00068 }
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078 static VALUE
00079 cmp_gt(VALUE x, VALUE y)
00080 {
00081 VALUE c = rb_funcall(x, cmp, 1, y);
00082
00083 if (rb_cmpint(c, x, y) > 0) return Qtrue;
00084 return Qfalse;
00085 }
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095 static VALUE
00096 cmp_ge(VALUE x, VALUE y)
00097 {
00098 VALUE c = rb_funcall(x, cmp, 1, y);
00099
00100 if (rb_cmpint(c, x, y) >= 0) return Qtrue;
00101 return Qfalse;
00102 }
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112 static VALUE
00113 cmp_lt(VALUE x, VALUE y)
00114 {
00115 VALUE c = rb_funcall(x, cmp, 1, y);
00116
00117 if (rb_cmpint(c, x, y) < 0) return Qtrue;
00118 return Qfalse;
00119 }
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129 static VALUE
00130 cmp_le(VALUE x, VALUE y)
00131 {
00132 VALUE c = rb_funcall(x, cmp, 1, y);
00133
00134 if (rb_cmpint(c, x, y) <= 0) return Qtrue;
00135 return Qfalse;
00136 }
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153 static VALUE
00154 cmp_between(VALUE x, VALUE min, VALUE max)
00155 {
00156 if (RTEST(cmp_lt(x, min))) return Qfalse;
00157 if (RTEST(cmp_gt(x, max))) return Qfalse;
00158 return Qtrue;
00159 }
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200 void
00201 Init_Comparable(void)
00202 {
00203 #undef rb_intern
00204 #define rb_intern(str) rb_intern_const(str)
00205
00206 rb_mComparable = rb_define_module("Comparable");
00207 rb_define_method(rb_mComparable, "==", cmp_equal, 1);
00208 rb_define_method(rb_mComparable, ">", cmp_gt, 1);
00209 rb_define_method(rb_mComparable, ">=", cmp_ge, 1);
00210 rb_define_method(rb_mComparable, "<", cmp_lt, 1);
00211 rb_define_method(rb_mComparable, "<=", cmp_le, 1);
00212 rb_define_method(rb_mComparable, "between?", cmp_between, 2);
00213
00214 cmp = rb_intern("<=>");
00215 }
00216