String.st
changeset 23218 6d01ac9aebbd
parent 23117 ca5a1992dafc
child 23279 d6fe9893f0a8
--- a/String.st	Wed Jul 18 15:28:49 2018 +0200
+++ b/String.st	Thu Jul 19 11:37:30 2018 +0200
@@ -2466,6 +2466,88 @@
     "
 !
 
+sameAs:aString
+    "Compare the receiver with the argument like =, but ignore case differences.
+     Return true or false."
+
+%{  /* NOCONTEXT */
+    OBJ slf = self;
+    OBJ arg = aString;
+
+    if (__qIsStringLike(slf) &&__isStringLike(arg)) {
+        unsigned char *src1, *src2;
+        int len;
+
+        len = __stringSize(slf);
+        if (len != __stringSize(arg)) {
+            RETURN ( false );
+        }
+
+        src1 = __stringVal(slf);
+        src2 = __stringVal(arg);
+
+        // fast skip over same chars
+        while (len >= sizeof(int)) {
+            if ( ((int*)src1)[0] != ((int*)src2)[0] ) break;
+            len -= sizeof(int);
+            src1 += sizeof(int);
+            src2 += sizeof(int);
+        }
+        while (len > 0) {
+            if ( src1[0] != src2[0] ) break;
+            len--;
+            src1++;
+            src2++;
+        }
+        
+        while (len > 0) {
+            // the trouble is, that it is not as easy as we might thing on first thought;
+            // for plain ascii (i.e. 7bits), we can check for chars being letters and then ignore the 0x20 bit.
+            // this even works for the national characters except for 0xFF / 0xDF
+            unsigned char ch1 = src1[0];
+            unsigned char ch2 = src2[0];
+            if (ch1 != ch2) {
+                unsigned char Uch1 = ch1 & ~0x20; // upper cased
+                unsigned char Uch2 = ch2 & ~0x20; // uppÞer cased
+                if ( (Uch1 >= 'A') && (Uch1 <= 'Z') ) {
+                    // letter
+                    if (Uch1 != Uch2) {
+                        RETURN(false);
+                    }    
+                } else {
+                    if ( (Uch1 >= 0xC0) && (Uch1 <= 0xDE) ) {
+                        // national letter 
+                        if (Uch1 != Uch2) {
+                            RETURN(false);
+                        }    
+                    } else {
+                        // other
+                        RETURN(false);
+                    }
+                }
+            }
+            len--;
+            src1++;
+            src2++;
+        }
+        RETURN (true);
+    }
+%}.
+    "use fallback for wide strings"
+    ^ super sameAs:aString
+
+    "
+     'hello' sameAs:'hello'
+     'hello' sameAs:'Hello'
+     'hello' sameAs:''
+     '' sameAs:'Hello'
+     'hello' sameAs:'hellO'
+     'hello' sameAs:'Hellx'
+    "
+    
+    "Created: / 19-07-2018 / 10:44:07 / Claus Gittinger"
+!
+
 startsWith:aStringOrChar
     "return true, if the receiver starts with something, aStringOrChar.
      If the argument is empty, true is returned.