summaryrefslogtreecommitdiff
path: root/string.c
diff options
context:
space:
mode:
authorduerst <duerst@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2016-11-28 08:37:32 +0000
committerduerst <duerst@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2016-11-28 08:37:32 +0000
commitad619e02c465eebd15fa57dc658f8e042decdebb (patch)
tree0bac3a6db831461a32c07aaaa5b845403c7289aa /string.c
parentbd2fd73196bbff7dc5349c624342e212c09d174e (diff)
implement String/Symbol#casecmp? including Unicode case folding
* string.c: Implement String#casecmp? and Symbol#casecmp? by using String#downcase :fold for Unicode case folding. This does not include options such as :turkic, because these currently cannot be combined with the :fold option. This implements feature #12786. * test/ruby/test_string.rb/test_symbol.rb: Tests for above. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@56912 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'string.c')
-rw-r--r--string.c54
1 files changed, 54 insertions, 0 deletions
diff --git a/string.c b/string.c
index 2ca835c74a..82ec6cdfdf 100644
--- a/string.c
+++ b/string.c
@@ -3194,6 +3194,40 @@ rb_str_casecmp(VALUE str1, VALUE str2)
return INT2FIX(-1);
}
+/*
+ * call-seq:
+ * str.casecmp?(other_str) -> true, false, or nil
+ *
+ * Returns true if str and other_other_str are equal after Unicode case folding,
+ * false if they are not equal, and nil if other_str is not a string.
+ *
+ * "abcdef".casecmp("abcde") #=> false
+ * "aBcDeF".casecmp("abcdef") #=> true
+ * "abcdef".casecmp("abcdefg") #=> false
+ * "abcdef".casecmp("ABCDEF") #=> true
+ */
+
+
+static VALUE rb_str_downcase(int argc, VALUE *argv, VALUE str); /* forward declaration */
+static VALUE
+rb_str_casecmp_p(VALUE str1, VALUE str2)
+{
+ rb_encoding *enc;
+ VALUE folded_str1, folded_str2;
+ VALUE fold_opt = sym_fold;
+
+ StringValue(str2);
+ enc = rb_enc_compatible(str1, str2);
+ if (!enc) {
+ return Qnil;
+ }
+
+ folded_str1 = rb_str_downcase(1, &fold_opt, str1);
+ folded_str2 = rb_str_downcase(1, &fold_opt, str2);
+
+ return rb_str_eql(folded_str1, folded_str2);
+}
+
#define rb_str_index(str, sub, offset) rb_strseq_index(str, sub, offset, 0)
static long
@@ -9617,6 +9651,24 @@ sym_casecmp(VALUE sym, VALUE other)
/*
* call-seq:
+ *
+ * sym.casecmp?(other) -> true, false, or nil
+ *
+ * Returns true if sym and other are equal after Unicode case folding,
+ * false if they are not equal, and nil if other is not a symbol.
+ */
+
+static VALUE
+sym_casecmp_p(VALUE sym, VALUE other)
+{
+ if (!SYMBOL_P(other)) {
+ return Qnil;
+ }
+ return rb_str_casecmp_p(rb_sym2str(sym), rb_sym2str(other));
+}
+
+/*
+ * call-seq:
* sym =~ obj -> integer or nil
*
* Returns <code>sym.to_s =~ obj</code>.
@@ -9814,6 +9866,7 @@ Init_String(void)
rb_define_method(rb_cString, "eql?", rb_str_eql, 1);
rb_define_method(rb_cString, "hash", rb_str_hash_m, 0);
rb_define_method(rb_cString, "casecmp", rb_str_casecmp, 1);
+ rb_define_method(rb_cString, "casecmp?", rb_str_casecmp_p, 1);
rb_define_method(rb_cString, "+", rb_str_plus, 1);
rb_define_method(rb_cString, "*", rb_str_times, 1);
rb_define_method(rb_cString, "%", rb_str_format_m, 1);
@@ -9963,6 +10016,7 @@ Init_String(void)
rb_define_method(rb_cSymbol, "<=>", sym_cmp, 1);
rb_define_method(rb_cSymbol, "casecmp", sym_casecmp, 1);
+ rb_define_method(rb_cSymbol, "casecmp?", sym_casecmp_p, 1);
rb_define_method(rb_cSymbol, "=~", sym_match, 1);
rb_define_method(rb_cSymbol, "[]", sym_aref, -1);