Revision: 4470 http://trac.macosforge.org/projects/ruby/changeset/4470 Author: lsansonetti@apple.com Date: 2010-08-26 17:09:08 -0700 (Thu, 26 Aug 2010) Log Message: ----------- fixed String#sum to accept bits argument greater than 64 (logic imported from 1.9 upstream sources) Modified Paths: -------------- MacRuby/trunk/id.c MacRuby/trunk/id.h MacRuby/trunk/string.c Modified: MacRuby/trunk/id.c =================================================================== --- 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 =================================================================== --- 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 =================================================================== --- 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; } /*