示例#1
0
U_CAPI int32_t U_EXPORT2
unorm_compare(const UChar *s1, int32_t length1,
              const UChar *s2, int32_t length2,
              uint32_t options,
              UErrorCode *pErrorCode) {
    UChar fcd1[300], fcd2[300];
    UChar *d1, *d2;
    const UnicodeSet *nx;
    UNormalizationMode mode;
    int32_t normOptions;
    int32_t result;

    /* argument checking */
    if(pErrorCode==0 || U_FAILURE(*pErrorCode)) {
        return 0;
    }
    if(s1==0 || length1<-1 || s2==0 || length2<-1) {
        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
        return 0;
    }

    if(!unorm_haveData(pErrorCode)) {
        return 0;
    }
    if(!uprv_haveProperties(pErrorCode)) {
        return 0;
    }

    normOptions=(int32_t)(options>>UNORM_COMPARE_NORM_OPTIONS_SHIFT);
    nx=unorm_getNX(normOptions, pErrorCode);
    if(U_FAILURE(*pErrorCode)) {
        return 0;
    }

    d1=d2=0;
    options|=_COMPARE_EQUIV;
    result=0;

    /*
     * UAX #21 Case Mappings, as fixed for Unicode version 4
     * (see Jitterbug 2021), defines a canonical caseless match as
     *
     * A string X is a canonical caseless match
     * for a string Y if and only if
     * NFD(toCasefold(NFD(X))) = NFD(toCasefold(NFD(Y)))
     *
     * For better performance, we check for FCD (or let the caller tell us that
     * both strings are in FCD) for the inner normalization.
     * BasicNormalizerTest::FindFoldFCDExceptions() makes sure that
     * case-folding preserves the FCD-ness of a string.
     * The outer normalization is then only performed by unorm_cmpEquivFold()
     * when there is a difference.
     *
     * Exception: When using the Turkic case-folding option, we do perform
     * full NFD first. This is because in the Turkic case precomposed characters
     * with 0049 capital I or 0069 small i fold differently whether they
     * are first decomposed or not, so an FCD check - a check only for
     * canonical order - is not sufficient.
     */
    if(options&U_FOLD_CASE_EXCLUDE_SPECIAL_I) {
        mode=UNORM_NFD;
        options&=~UNORM_INPUT_IS_FCD;
    } else {
        mode=UNORM_FCD;
    }

    if(!(options&UNORM_INPUT_IS_FCD)) {
        int32_t _len1, _len2;
        UBool isFCD1, isFCD2;

        // check if s1 and/or s2 fulfill the FCD conditions
        isFCD1= UNORM_YES==unorm_internalQuickCheck(s1, length1, mode, TRUE, nx, pErrorCode);
        isFCD2= UNORM_YES==unorm_internalQuickCheck(s2, length2, mode, TRUE, nx, pErrorCode);
        if(U_FAILURE(*pErrorCode)) {
            return 0;
        }

        /*
         * ICU 2.4 had a further optimization:
         * If both strings were not in FCD, then they were both NFD'ed,
         * and the _COMPARE_EQUIV option was turned off.
         * It is not entirely clear that this is valid with the current
         * definition of the canonical caseless match.
         * Therefore, ICU 2.6 removes that optimization.
         */

        if(!isFCD1) {
            _len1=unorm_internalNormalizeWithNX(fcd1, LENGTHOF(fcd1),
                                                s1, length1,
                                                mode, normOptions, nx,
                                                pErrorCode);
            if(*pErrorCode!=U_BUFFER_OVERFLOW_ERROR) {
                s1=fcd1;
            } else {
                d1=(UChar *)uprv_malloc(_len1*U_SIZEOF_UCHAR);
                if(d1==0) {
                    *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
                    goto cleanup;
                }

                *pErrorCode=U_ZERO_ERROR;
                _len1=unorm_internalNormalizeWithNX(d1, _len1,
                                                    s1, length1,
                                                    mode, normOptions, nx,
                                                    pErrorCode);
                if(U_FAILURE(*pErrorCode)) {
                    goto cleanup;
                }

                s1=d1;
            }
            length1=_len1;
        }

        if(!isFCD2) {
            _len2=unorm_internalNormalizeWithNX(fcd2, LENGTHOF(fcd2),
                                                s2, length2,
                                                mode, normOptions, nx,
                                                pErrorCode);
            if(*pErrorCode!=U_BUFFER_OVERFLOW_ERROR) {
                s2=fcd2;
            } else {
                d2=(UChar *)uprv_malloc(_len2*U_SIZEOF_UCHAR);
                if(d2==0) {
                    *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
                    goto cleanup;
                }

                *pErrorCode=U_ZERO_ERROR;
                _len2=unorm_internalNormalizeWithNX(d2, _len2,
                                                    s2, length2,
                                                    mode, normOptions, nx,
                                                    pErrorCode);
                if(U_FAILURE(*pErrorCode)) {
                    goto cleanup;
                }

                s2=d2;
            }
            length2=_len2;
        }
    }

    if(U_SUCCESS(*pErrorCode)) {
        result=unorm_cmpEquivFold(s1, length1, s2, length2, options, pErrorCode);
    }

cleanup:
    if(d1!=0) {
        uprv_free(d1);
    }
    if(d2!=0) {
        uprv_free(d2);
    }

    return result;
}
示例#2
0
U_CAPI int32_t U_EXPORT2
unorm_compare(const UChar *s1, int32_t length1,
              const UChar *s2, int32_t length2,
              uint32_t options,
              UErrorCode *pErrorCode) {
    /* argument checking */
    if(U_FAILURE(*pErrorCode)) {
        return 0;
    }
    if(s1==0 || length1<-1 || s2==0 || length2<-1) {
        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
        return 0;
    }

    UnicodeString fcd1, fcd2;
    int32_t normOptions=(int32_t)(options>>UNORM_COMPARE_NORM_OPTIONS_SHIFT);
    options|=_COMPARE_EQUIV;

    /*
     * UAX #21 Case Mappings, as fixed for Unicode version 4
     * (see Jitterbug 2021), defines a canonical caseless match as
     *
     * A string X is a canonical caseless match
     * for a string Y if and only if
     * NFD(toCasefold(NFD(X))) = NFD(toCasefold(NFD(Y)))
     *
     * For better performance, we check for FCD (or let the caller tell us that
     * both strings are in FCD) for the inner normalization.
     * BasicNormalizerTest::FindFoldFCDExceptions() makes sure that
     * case-folding preserves the FCD-ness of a string.
     * The outer normalization is then only performed by unorm_cmpEquivFold()
     * when there is a difference.
     *
     * Exception: When using the Turkic case-folding option, we do perform
     * full NFD first. This is because in the Turkic case precomposed characters
     * with 0049 capital I or 0069 small i fold differently whether they
     * are first decomposed or not, so an FCD check - a check only for
     * canonical order - is not sufficient.
     */
    if(!(options&UNORM_INPUT_IS_FCD) || (options&U_FOLD_CASE_EXCLUDE_SPECIAL_I)) {
        const Normalizer2 *n2;
        if(options&U_FOLD_CASE_EXCLUDE_SPECIAL_I) {
            n2=Normalizer2Factory::getNFDInstance(*pErrorCode);
        } else {
            n2=Normalizer2Factory::getFCDInstance(*pErrorCode);
        }
        if (U_FAILURE(*pErrorCode)) {
            return 0;
        }

        // check if s1 and/or s2 fulfill the FCD conditions
        const UnicodeSet *uni32;
        if(normOptions&UNORM_UNICODE_3_2) {
            uni32=uniset_getUnicode32Instance(*pErrorCode);
        } else {
            uni32=NULL;  // unused
        }
        FilteredNormalizer2 fn2(*n2, *uni32);
        if(normOptions&UNORM_UNICODE_3_2) {
            n2=&fn2;
        }

        UnicodeString str1(length1<0, s1, length1);
        UnicodeString str2(length2<0, s2, length2);
        int32_t spanQCYes1=n2->spanQuickCheckYes(str1, *pErrorCode);
        int32_t spanQCYes2=n2->spanQuickCheckYes(str2, *pErrorCode);
        if(U_FAILURE(*pErrorCode)) {
            return 0;
        }

        /*
         * ICU 2.4 had a further optimization:
         * If both strings were not in FCD, then they were both NFD'ed,
         * and the _COMPARE_EQUIV option was turned off.
         * It is not entirely clear that this is valid with the current
         * definition of the canonical caseless match.
         * Therefore, ICU 2.6 removes that optimization.
         */

        if(spanQCYes1<str1.length()) {
            UnicodeString unnormalized=str1.tempSubString(spanQCYes1);
            fcd1.setTo(FALSE, str1.getBuffer(), spanQCYes1);
            n2->normalizeSecondAndAppend(fcd1, unnormalized, *pErrorCode);
            s1=fcd1.getBuffer();
            length1=fcd1.length();
        }
        if(spanQCYes2<str2.length()) {
            UnicodeString unnormalized=str2.tempSubString(spanQCYes2);
            fcd2.setTo(FALSE, str2.getBuffer(), spanQCYes2);
            n2->normalizeSecondAndAppend(fcd2, unnormalized, *pErrorCode);
            s2=fcd2.getBuffer();
            length2=fcd2.length();
        }
    }

    if(U_SUCCESS(*pErrorCode)) {
        return unorm_cmpEquivFold(s1, length1, s2, length2, options, pErrorCode);
    } else {
        return 0;
    }
}