Modified: MacRuby/trunk/id.c (4469 => 4470)
--- MacRuby/trunk/id.c 2010-08-26 23:33:33 UTC (rev 4469)
+++ MacRuby/trunk/id.c 2010-08-27 00:09:08 UTC (rev 4470)
@@ -48,6 +48,7 @@
selMULT = sel_registerName("*:");
selDIV = sel_registerName("/:");
selMOD = sel_registerName("%:");
+ selAND = sel_registerName("&:");
selEq = sel_registerName("==:");
selNeq = sel_registerName("!=:");
selCmp = sel_registerName("<=>:");
Modified: MacRuby/trunk/id.h (4469 => 4470)
--- MacRuby/trunk/id.h 2010-08-26 23:33:33 UTC (rev 4469)
+++ MacRuby/trunk/id.h 2010-08-27 00:09:08 UTC (rev 4470)
@@ -58,6 +58,7 @@
extern SEL selMULT;
extern SEL selDIV;
extern SEL selMOD;
+extern SEL selAND;
extern SEL selEq;
extern SEL selNeq;
extern SEL selCmp;
Modified: MacRuby/trunk/string.c (4469 => 4470)
--- MacRuby/trunk/string.c 2010-08-26 23:33:33 UTC (rev 4469)
+++ MacRuby/trunk/string.c 2010-08-27 00:09:08 UTC (rev 4470)
@@ -5514,6 +5514,12 @@
* checksum.
*/
+static inline VALUE
+rb_vm_call_simple(VALUE rcv, SEL sel, VALUE arg)
+{
+ return rb_vm_call(rcv, sel, 1, &arg);
+}
+
static VALUE
rstr_sum(VALUE str, SEL sel, int argc, VALUE *argv)
{
@@ -5524,19 +5530,39 @@
bits = NUM2INT(vbits);
}
- if (bits >= sizeof(long) * CHAR_BIT) {
- rb_raise(rb_eArgError, "bits argument too big");
- }
-
- unsigned long sum = 0;
+ VALUE sum = INT2FIX(0);
+ unsigned long sum0 = 0;
for (long i = 0; i < RSTR(str)->length_in_bytes; i++) {
- sum += (unsigned char)RSTR(str)->data.bytes[i];
+ if (FIXNUM_MAX - UCHAR_MAX < sum0) {
+ sum = rb_vm_call_simple(sum, selPLUS, LONG2FIX(sum0));
+ sum0 = 0;
+ }
+ sum0 += (unsigned char)RSTR(str)->data.bytes[i];
}
- if (bits != 0) {
- sum &= (((unsigned long)1) << bits) - 1;
+ if (bits == 0) {
+ if (sum0 != 0) {
+ sum = rb_vm_call_simple(sum, selPLUS, LONG2FIX(sum0));
+ }
}
+ else {
+ if (sum == INT2FIX(0)) {
+ if (bits < (int)sizeof(long) * CHAR_BIT) {
+ sum0 &= (((unsigned long)1) << bits) - 1;
+ }
+ sum = LONG2FIX(sum0);
+ }
+ else {
+ if (sum0 != 0) {
+ sum = rb_vm_call_simple(sum, selPLUS, LONG2FIX(sum0));
+ }
- return rb_int2inum(sum);
+ VALUE mod = rb_vm_call_simple(INT2FIX(1), selLTLT, INT2FIX(bits));
+ mod = rb_vm_call_simple(mod, selMINUS, INT2FIX(1));
+ sum = rb_vm_call_simple(sum, selAND, mod);
+ }
+ }
+
+ return sum;
}
/*