[Mono-devel-list] [PATCH] make String.Compare trasitive

Michal Moskal malekith at pld-linux.org
Sat Oct 4 12:59:00 EDT 2003


string-icalls.c:877:

/*
 * @mode:
 * 0 = StringCompareModeDirect
 * 1 = StringCompareModeCaseInsensitive
 * 2 = StringCompareModeOrdinal
 */
static gint32
string_icall_cmp_char (gunichar2 c1, gunichar2 c2, gint32 mode)
{
        gint32 result;
        GUnicodeType c1type, c2type;

        c1type = g_unichar_type (c1);
        c2type = g_unichar_type (c2);

        switch (mode) {
        case 0:
                /* TODO: compare with culture info */
                if (c1type == G_UNICODE_UPPERCASE_LETTER && c2type == G_UNICODE_LOWERCASE_LETTER)
                        return 1;

                if (c1type == G_UNICODE_LOWERCASE_LETTER && c2type == G_UNICODE_UPPERCASE_LETTER)
                        return -1;

                result = (gint32) c1 - c2;
                break;
		
This code causes lowercase letters to be always smaller then uppercase
letters (against ASCII order). Anyway the problem is that this causes
String.Compare not to be transitive. For example:

  "_" < "a" < "A"

But:

  "_" > "A"

Non-transitive comparison function causes problems for tree-like
data structures using it, and for sorting algorithms (some versions of
qsort() will for example crash).

I understand that this is going to be fixed some day (TODO), but as for
now maybe it would be better to treat normal comparison as ordinal (i.e.
remove the check for upper-lower case).

I attach patch to do that.

-- 
: Michal Moskal :: http://www.kernel.pl/~malekith : GCS {C,UL}++++$ a? !tv
: When in doubt, use brute force. -- Ken Thompson : {E-,w}-- {b++,e}>+++ h
-------------- next part --------------
--- mono-0.28/mono/metadata/string-icalls.c~	2003-10-04 18:57:04.000000000 +0200
+++ mono-0.28/mono/metadata/string-icalls.c	2003-10-04 18:57:52.000000000 +0200
@@ -891,13 +891,8 @@
 
 	switch (mode) {
 	case 0:	
-		/* TODO: compare with culture info */
-		if (c1type == G_UNICODE_UPPERCASE_LETTER && c2type == G_UNICODE_LOWERCASE_LETTER)
-			return 1;
-					
-		if (c1type == G_UNICODE_LOWERCASE_LETTER && c2type == G_UNICODE_UPPERCASE_LETTER)
-			return -1;
-	
+		/* TODO: we should compare with culture info here, but remember to keep
+		 * this function transitve! */
 		result = (gint32) c1 - c2;
 		break;
 	case 1:	


More information about the Mono-devel-list mailing list