[macruby-changes] [3627] MacRuby/branches/icu/string.c

source_changes at macosforge.org source_changes at macosforge.org
Thu Feb 25 17:07:51 PST 2010


Revision: 3627
          http://trac.macosforge.org/projects/ruby/changeset/3627
Author:   lsansonetti at apple.com
Date:     2010-02-25 17:07:51 -0800 (Thu, 25 Feb 2010)
Log Message:
-----------
added #<=>

Modified Paths:
--------------
    MacRuby/branches/icu/string.c

Modified: MacRuby/branches/icu/string.c
===================================================================
--- MacRuby/branches/icu/string.c	2010-02-26 00:29:31 UTC (rev 3626)
+++ MacRuby/branches/icu/string.c	2010-02-26 01:07:51 UTC (rev 3627)
@@ -825,36 +825,36 @@
     self->length_in_bytes = new_length_in_bytes;
 }
 
-static bool
-str_is_equal_to_string(rb_str_t *self, rb_str_t *str)
+static int
+str_compare(rb_str_t *self, rb_str_t *str)
 {
     if (self == str) {
-	return true;
+	return 0;
     }
 
     if (self->length_in_bytes == 0) {
 	if (str->length_in_bytes == 0) {
 	    // both strings are empty
-	    return true;
+	    goto bad_length;
 	}
 	else {
 	    // only self is empty
-	    return false;
+	    goto bad_length;
 	}
     }
     else if (str->length_in_bytes == 0) {
 	// only str is empty
-	return false;
+	goto bad_length;
     }
 
     if (str_compatible_encoding(self, str) != NULL) {
 	if (str_is_stored_in_uchars(self) == str_is_stored_in_uchars(str)) {
 	    if (self->length_in_bytes != str->length_in_bytes) {
-		return false;
+		goto bad_length;
 	    }
 	    else {
-		return (memcmp(self->data.bytes, str->data.bytes,
-			    self->length_in_bytes) == 0);
+		return memcmp(self->data.bytes, str->data.bytes,
+			self->length_in_bytes);
 	    }
 	}
 	else { // one is in uchars and the other is in binary
@@ -862,20 +862,23 @@
 		    || !str_try_making_data_uchars(str)) {
 		// one is in uchars but the other one can't be converted in
 		// uchars
-		return false;
+		return -1;
 	    }
 	    if (self->length_in_bytes != str->length_in_bytes) {
-		return false;
+		goto bad_length;
 	    }
 	    else {
-		return (memcmp(self->data.bytes, str->data.bytes,
-			    self->length_in_bytes) == 0);
+		return memcmp(self->data.bytes, str->data.bytes,
+			self->length_in_bytes);
 	    }
 	}
     }
     else { // incompatible encodings
-	return false;
+	return -1;
     }
+
+bad_length:
+    return self->length_in_bytes > str->length_in_bytes ? 1 : -1;
 }
 
 static long
@@ -1795,11 +1798,63 @@
 	}
 	return rb_equal(other, self);
     }
-    return str_is_equal_to_string(RSTR(self), str_need_string(other))
+    return str_compare(RSTR(self), str_need_string(other)) == 0
 	? Qtrue : Qfalse;
 }
 
 /*
+ *  call-seq:
+ *     str <=> other_str   => -1, 0, +1
+ *  
+ *  Comparison---Returns -1 if <i>other_str</i> is less than, 0 if
+ *  <i>other_str</i> is equal to, and +1 if <i>other_str</i> is greater than
+ *  <i>str</i>. If the strings are of different lengths, and the strings are
+ *  equal when compared up to the shortest length, then the longer string is
+ *  considered greater than the shorter one. In older versions of Ruby, setting
+ *  <code>$=</code> allowed case-insensitive comparisons; this is now deprecated
+ *  in favor of using <code>String#casecmp</code>.
+ *
+ *  <code><=></code> is the basis for the methods <code><</code>,
+ *  <code><=</code>, <code>></code>, <code>>=</code>, and <code>between?</code>,
+ *  included from module <code>Comparable</code>.  The method
+ *  <code>String#==</code> does not use <code>Comparable#==</code>.
+ *     
+ *     "abcdef" <=> "abcde"     #=> 1
+ *     "abcdef" <=> "abcdef"    #=> 0
+ *     "abcdef" <=> "abcdefg"   #=> -1
+ *     "abcdef" <=> "ABCDEF"    #=> 1
+ */
+
+static VALUE
+rstr_cmp(VALUE self, SEL sel, VALUE other)
+{
+    long result;
+
+    if (TYPE(other) != T_STRING) {
+	if (!rb_respond_to(other, rb_intern("to_str"))) {
+	    return Qnil;
+	}
+	else if (!rb_vm_respond_to(other, selCmp, false)) {
+	    return Qnil;
+	}
+	else {
+	    VALUE tmp = rb_vm_call(other, selCmp, 1, &self, false);
+	    if (NIL_P(tmp)) {
+		return Qnil;
+	    }
+	    if (!FIXNUM_P(tmp)) {
+		return rb_vm_call(LONG2FIX(0), selMINUS, 1, &tmp, false);
+	    }
+	    result = -FIX2LONG(tmp);
+	}
+    }
+    else {
+	result = str_compare(RSTR(self), str_need_string(other));
+    }
+    return LONG2NUM(result);
+}
+
+/*
  * call-seq:
  *   str.eql?(other)   => true or false
  *
@@ -1816,7 +1871,7 @@
     if (TYPE(other) != T_STRING) {
 	return Qfalse;
     }
-    return str_is_equal_to_string(RSTR(self), str_need_string(other))
+    return str_compare(RSTR(self), str_need_string(other)) == 0
 	? Qtrue : Qfalse;
 }
 
@@ -3204,6 +3259,7 @@
     rb_objc_define_method(rb_cRubyString, "<<", rstr_concat, 1);
     rb_objc_define_method(rb_cRubyString, "concat", rstr_concat, 1);
     rb_objc_define_method(rb_cRubyString, "==", rstr_equal, 1);
+    rb_objc_define_method(rb_cRubyString, "<=>", rstr_cmp, 1);
     rb_objc_define_method(rb_cRubyString, "eql?", rstr_eql, 1);
     rb_objc_define_method(rb_cRubyString, "include?", rstr_includes, 1);
     rb_objc_define_method(rb_cRubyString, "to_s", rstr_to_s, 0);
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20100225/46a215a9/attachment.html>


More information about the macruby-changes mailing list