diff options
author | akr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2010-03-18 20:35:18 +0000 |
---|---|---|
committer | akr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2010-03-18 20:35:18 +0000 |
commit | 053d89ca2bde48126e058700799baa7ca370ca8d (patch) | |
tree | 778efd22c3bb478bd0bb6e132d33034658e9d56b /string.c | |
parent | bd5e925cc4580517e7fa08d46768cdb690598c3e (diff) | |
download | ruby-053d89ca2bde48126e058700799baa7ca370ca8d.tar.gz |
* string.c (rb_str_sum): don't call method for each byte.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@26975 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'string.c')
-rw-r--r-- | string.c | 58 |
1 files changed, 33 insertions, 25 deletions
@@ -6537,7 +6537,7 @@ rb_str_ord(VALUE s) * Returns a basic <em>n</em>-bit checksum of the characters in <i>str</i>, * where <em>n</em> is the optional <code>Fixnum</code> parameter, defaulting * to 16. The result is simply the sum of the binary value of each character in - * <i>str</i> modulo <code>2n - 1</code>. This is not a particularly good + * <i>str</i> modulo <code>2**n - 1</code>. This is not a particularly good * checksum. */ @@ -6548,6 +6548,8 @@ rb_str_sum(int argc, VALUE *argv, VALUE str) int bits; char *ptr, *p, *pend; long len; + VALUE sum = INT2FIX(0); + unsigned long sum0 = 0; if (argc == 0) { bits = 16; @@ -6559,36 +6561,42 @@ rb_str_sum(int argc, VALUE *argv, VALUE str) ptr = p = RSTRING_PTR(str); len = RSTRING_LEN(str); pend = p + len; - if (bits >= (int)sizeof(long)*CHAR_BIT) { - VALUE sum = INT2FIX(0); - while (p < pend) { - str_mod_check(str, ptr, len); - sum = rb_funcall(sum, '+', 1, INT2FIX((unsigned char)*p)); - p++; - } - if (bits != 0) { - VALUE mod; + while (p < pend) { + if (FIXNUM_MAX - 255 < sum0) { + sum = rb_funcall(sum, '+', 1, LONG2FIX(sum0)); + str_mod_check(str, ptr, len); + sum0 = 0; + } + sum0 += (unsigned char)*p; + p++; + } - mod = rb_funcall(INT2FIX(1), rb_intern("<<"), 1, INT2FIX(bits)); - mod = rb_funcall(mod, '-', 1, INT2FIX(1)); - sum = rb_funcall(sum, '&', 1, mod); - } - return sum; + if (bits == 0) { + if (sum0) { + sum = rb_funcall(sum, '+', 1, LONG2FIX(sum0)); + } } else { - unsigned long sum = 0; + if (sum == INT2FIX(0)) { + if (bits < (int)sizeof(long)*CHAR_BIT) { + sum0 &= (((unsigned long)1)<<bits)-1; + } + sum = LONG2FIX(sum0); + } + else { + VALUE mod; - while (p < pend) { - str_mod_check(str, ptr, len); - sum += (unsigned char)*p; - p++; - } - if (bits != 0) { - sum &= (((unsigned long)1)<<bits)-1; - } - return rb_int2inum(sum); + if (sum0) { + sum = rb_funcall(sum, '+', 1, LONG2FIX(sum0)); + } + + mod = rb_funcall(INT2FIX(1), rb_intern("<<"), 1, INT2FIX(bits)); + mod = rb_funcall(mod, '-', 1, INT2FIX(1)); + sum = rb_funcall(sum, '&', 1, mod); + } } + return sum; } static VALUE |