Project

General

Profile

Feature #2571 » 0001-string.c-rb_str_hamming_distance-Init_String.patch

mrkn (Kenta Murata), 01/07/2010 05:06 PM

View differences:

ChangeLog
Thu Jan 7 16:32:00 2010 Kenta Murata <mrkn@mrkn.jp>
* string.c (rb_str_hamming_distance, Init_String),
test/ruby/test_string.c (test_hamming_distance): Added support for
calculating hamming distance between two strings.
Thu Jan 7 07:56:09 2010 Ryan Davis <ryand-ruby@zenspider.com>
* lib/minitest/*.rb: Imported minitest 1.5.0 r5596.
string.c
*var = val;
}
/*
*/
VALUE
rb_str_hamming_distance(VALUE str1, VALUE str2)
{
long d = 0;
rb_encoding *enc;
char *p1, *p1end, *p2, *p2end;
if (TYPE(str2) != T_STRING) return Qnil;
enc = rb_enc_compatible(str1, str2);
if (!enc) return Qnil;
if (str_strlen(str1, enc) != str_strlen(str2, enc)) return Qnil;
p1 = RSTRING_PTR(str1); p1end = RSTRING_END(str1);
p2 = RSTRING_PTR(str2); p2end = RSTRING_END(str2);
if (single_byte_optimizable(str1) && single_byte_optimizable(str2)) {
while (p1 < p1end) {
if (*p1 != *p2) ++d;
++p1;
++p2;
}
}
else {
while (p1 < p1end && p2 < p2end) {
int l1, c1 = rb_enc_ascget(p1, p1end, &l1, enc);
int l2, c2 = rb_enc_ascget(p2, p2end, &l2, enc);
if (0 <= c1 && 0 <= c2) {
if (c1 != c2) ++d;
}
else {
int r, len;
l1 = rb_enc_mbclen(p1, p1end, enc);
l2 = rb_enc_mbclen(p2, p2end, enc);
len = l1 < l2 ? l1 : l2;
r = memcmp(p1, p2, len);
if (r != 0 || l1 != l2) ++d;
}
p1 += l1;
p2 += l2;
}
}
return LONG2NUM(d);
}
/*
* call-seq:
......
rb_define_method(rb_cString, "partition", rb_str_partition, 1);
rb_define_method(rb_cString, "rpartition", rb_str_rpartition, 1);
rb_define_method(rb_cString, "hamming_distance", rb_str_hamming_distance, 1);
rb_define_method(rb_cString, "^", rb_str_hamming_distance, 1);
rb_define_method(rb_cString, "encoding", rb_obj_encoding, 0); /* in encoding.c */
rb_define_method(rb_cString, "force_encoding", rb_str_force_encoding, 1);
rb_define_method(rb_cString, "valid_encoding?", rb_str_valid_encoding_p, 0);
test/ruby/test_string.rb
assert_equal(s, k, '[ruby-dev:39068]')
assert_equal(Encoding::UTF_8, k.encoding, '[ruby-dev:39068]')
end
def test_hamming_distance
assert_nil("a" ^ "abc")
assert_equal(0, "" ^ "")
assert_equal(2, "abc" ^ "dbf")
assert_equal(1, "aXb" ^ "a\u{ff38}b")
assert_equal(1, "\u3042\u3044\u3046" ^ "\u3042\u3044\u3048")
assert_equal(3, "\u3042a\u3044\u3046" ^ "\u3042\u3044b\u3048")
assert_equal(1, "aXb".force_encoding("EUC-JP") ^ "aYb".force_encoding("Shift_JIS"))
assert_nil("\u3042\u3044\u3046".force_encoding("EUC-JP") ^ "\u3042\u3044\u3046".force_encoding("Shift_JIS"))
end
end
    (1-1/1)