]> git.sur5r.net Git - openldap/commitdiff
Added UTF8bvnormcmp(), should replace UTF8normcmp()
authorStig Venaas <venaas@openldap.org>
Wed, 20 Feb 2002 15:51:10 +0000 (15:51 +0000)
committerStig Venaas <venaas@openldap.org>
Wed, 20 Feb 2002 15:51:10 +0000 (15:51 +0000)
include/ldap_pvt_uc.h
libraries/liblunicode/ucstr.c

index fb3b29b5a07c03f77b05dd8ed818f425d7bfb00e..6778628fa6c3a8c680ebbf9e57a46a5c8c33c7a7 100644 (file)
@@ -154,6 +154,11 @@ LDAP_LUNICODE_F(int) UTF8normcmp(
        const char *,
        unsigned );
 
+LDAP_LUNICODE_F(int) UTF8bvnormcmp(
+       struct berval *,
+       struct berval *,
+       unsigned );
+
 LDAP_END_DECL
 
 #endif
index d0d76214396d62f9a500776ac8e557d4470dc21d..395bd6b9505ac165cfb7fd7da18df9613fdf9dad 100644 (file)
@@ -498,3 +498,132 @@ int UTF8normcmp(
        }
        return l1 > l2 ? 1 : -1;
 }
+
+/* compare UTF8-strings, optionally ignore casing */
+/* slow, should be optimized */
+int UTF8bvnormcmp(
+       struct berval *bv1,
+       struct berval *bv2,
+       unsigned casefold )
+{
+       int i, l1, l2, len, ulen, res;
+       char *s1, *s2, *done;
+       unsigned long *ucs, *ucsout1, *ucsout2;
+
+       if (bv1 == NULL) {
+               return bv2 == NULL ? 0 : -1;
+       } else if (bv2 == NULL) {
+               return 1;
+       }
+
+       l1 = bv1->bv_len;
+       l2 = bv2->bv_len;
+
+       len = (l1 < l2) ? l1 : l2;
+       if (len == 0) {
+               return l1 == 0 ? (l2 == 0 ? 0 : -1) : 1;
+       }
+
+       s1 = bv1->bv_val;
+       s2 = bv2->bv_val;
+       done = s1 + len;
+
+       while ( (s1 < done) && LDAP_UTF8_ISASCII(s1) && LDAP_UTF8_ISASCII(s2) ) {
+               if (casefold) {
+                       char c1 = TOUPPER(*s1);
+                       char c2 = TOUPPER(*s2);
+                       res = c1 - c2;
+               } else {
+                       res = *s1 - *s2;
+               }                       
+               s1++;
+               s2++;
+               if (res) {
+                       /* done unless next character in s1 or s2 is non-ascii */
+                       if (s1 < done) {
+                               if (!LDAP_UTF8_ISASCII(s1) || !LDAP_UTF8_ISASCII(s2)) {
+                                       break;
+                               }
+                       } else if ((len < l1) && !LDAP_UTF8_ISASCII(s1) ||
+                                  (len < l2) && !LDAP_UTF8_ISASCII(s2)) {
+                               break;
+                       }
+                       return res;
+               }
+       }
+
+       /* We have encountered non-ascii or strings equal up to len */
+
+       /* set i to number of iterations */
+       i = s1 - done + len;
+       /* passed through loop at least once? */
+       if (i > 0) {
+               if (!res && (s1 == done) &&
+                   ((len == l1) || LDAP_UTF8_ISASCII(s1)) &&
+                   ((len == l2) || LDAP_UTF8_ISASCII(s2))) {
+                       /* all ascii and equal up to len */
+                       return l1 - l2;
+               }
+
+               /* rewind one char, and do normalized compare from there */
+               s1--;
+               s2--;
+               l1 -= i - 1;
+               l2 -= i - 1;
+       }
+                       
+       /* FIXME: Should first check to see if strings are already in
+        * proper normalized form.
+        */
+
+       ucs = (long *) malloc( ( l1 > l2 ? l1 : l2 ) * sizeof(*ucs) );
+       if ( ucs == NULL ) {
+               return l1 > l2 ? 1 : -1; /* what to do??? */
+       }
+       
+       /*
+        * XXYYZ: we convert to ucs4 even though -llunicode
+        * expects ucs2 in an unsigned long
+        */
+       
+       /* convert and normalize 1st string */
+       for ( i = 0, ulen = 0; i < l1; i += len, ulen++ ) {
+                ucs[ulen] = ldap_x_utf8_to_ucs4( s1 + i );
+                if ( ucs[ulen] == LDAP_UCS4_INVALID ) {
+                       free( ucs );
+                        return -1; /* what to do??? */
+                }
+               len = LDAP_UTF8_CHARLEN( s1 + i );
+       }
+       uccanondecomp( ucs, ulen, &ucsout1, &l1 );
+       l1 = uccanoncomp( ucsout1, l1 );
+
+       /* convert and normalize 2nd string */
+       for ( i = 0, ulen = 0; i < l2; i += len, ulen++ ) {
+                ucs[ulen] = ldap_x_utf8_to_ucs4( s2 + i );
+                if ( ucs[ulen] == LDAP_UCS4_INVALID ) {
+                       free( ucsout1 );
+                       free( ucs );
+                        return 1; /* what to do??? */
+                }
+               len = LDAP_UTF8_CHARLEN( s2 + i );
+       }
+       uccanondecomp( ucs, ulen, &ucsout2, &l2 );
+       l2 = uccanoncomp( ucsout2, l2 );
+
+       free( ucs );
+
+       res = casefold
+               ? ucstrncasecmp( ucsout1, ucsout2, l1 < l2 ? l1 : l2 )
+               : ucstrncmp( ucsout1, ucsout2, l1 < l2 ? l1 : l2 );
+       free( ucsout1 );
+       free( ucsout2 );
+
+       if ( res != 0 ) {
+               return res;
+       }
+       if ( l1 == l2 ) {
+               return 0;
+       }
+       return l1 > l2 ? 1 : -1;
+}