12ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller/* GENERATED SOURCE. DO NOT MODIFY. */
2f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert// © 2016 and later: Unicode, Inc. and others.
3f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert// License & terms of use: http://www.unicode.org/copyright.html#License
42ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller/*
52ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller *******************************************************************************
62ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Copyright (C) 1996-2015, International Business Machines
72ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Corporation and others.  All Rights Reserved.
82ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller *******************************************************************************
92ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * CollationCompare.java, ported from collationcompare.h/.cpp
102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller *
112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * C++ version created on: 2012feb14 with new and old collation code
122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * created by: Markus W. Scherer
132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */
142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerpackage android.icu.impl.coll;
162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport android.icu.text.Collator;
182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
191537b2f39245c07b00aa78c3600f7aebcb172490Neil Fuller/**
201537b2f39245c07b00aa78c3600f7aebcb172490Neil Fuller * @hide Only a subset of ICU is exposed in Android
21836e6b40a94ec3fb7545a76cb072960442b7eee9Neil Fuller */
222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerpublic final class CollationCompare /* all static */ {
232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static int compareUpToQuaternary(CollationIterator left, CollationIterator right,
242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            CollationSettings settings) {
252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int options = settings.options;
262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        long variableTop;
272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if ((options & CollationSettings.ALTERNATE_MASK) == 0) {
282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            variableTop = 0;
292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        } else {
302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            // +1 so that we can use "<" and primary ignorables test out early.
312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            variableTop = settings.variableTop + 1;
322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        boolean anyVariable = false;
342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        // Fetch CEs, compare primaries, store secondary & tertiary weights.
362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        for (;;) {
372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            // We fetch CEs until we get a non-ignorable primary or reach the end.
382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            long leftPrimary;
392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            do {
402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                long ce = left.nextCE();
412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                leftPrimary = ce >>> 32;
422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                if (leftPrimary < variableTop && leftPrimary > Collation.MERGE_SEPARATOR_PRIMARY) {
432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    // Variable CE, shift it to quaternary level.
442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    // Ignore all following primary ignorables, and shift further variable CEs.
452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    anyVariable = true;
462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    do {
472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        // Store only the primary of the variable CE.
482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        left.setCurrentCE(ce & 0xffffffff00000000L);
492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        for (;;) {
502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                            ce = left.nextCE();
512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                            leftPrimary = ce >>> 32;
522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                            if (leftPrimary == 0) {
532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                                left.setCurrentCE(0);
542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                            } else {
552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                                break;
562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                            }
572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        }
582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    } while (leftPrimary < variableTop && leftPrimary > Collation.MERGE_SEPARATOR_PRIMARY);
592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }
602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            } while (leftPrimary == 0);
612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            long rightPrimary;
632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            do {
642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                long ce = right.nextCE();
652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                rightPrimary = ce >>> 32;
662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                if (rightPrimary < variableTop && rightPrimary > Collation.MERGE_SEPARATOR_PRIMARY) {
672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    // Variable CE, shift it to quaternary level.
682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    // Ignore all following primary ignorables, and shift further variable CEs.
692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    anyVariable = true;
702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    do {
712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        // Store only the primary of the variable CE.
722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        right.setCurrentCE(ce & 0xffffffff00000000L);
732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        for (;;) {
742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                            ce = right.nextCE();
752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                            rightPrimary = ce >>> 32;
762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                            if (rightPrimary == 0) {
772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                                right.setCurrentCE(0);
782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                            } else {
792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                                break;
802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                            }
812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        }
822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    } while (rightPrimary < variableTop && rightPrimary > Collation.MERGE_SEPARATOR_PRIMARY);
832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }
842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            } while (rightPrimary == 0);
852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if (leftPrimary != rightPrimary) {
872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                // Return the primary difference, with script reordering.
882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                if (settings.hasReordering()) {
892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    leftPrimary = settings.reorder(leftPrimary);
902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    rightPrimary = settings.reorder(rightPrimary);
912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }
922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                return (leftPrimary < rightPrimary) ? Collation.LESS : Collation.GREATER;
932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if (leftPrimary == Collation.NO_CE_PRIMARY) {
952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                break;
962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        // Compare the buffered secondary & tertiary weights.
1002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        // We might skip the secondary level but continue with the case level
1012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        // which is turned on separately.
1022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if (CollationSettings.getStrength(options) >= Collator.SECONDARY) {
1032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if ((options & CollationSettings.BACKWARD_SECONDARY) == 0) {
1042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                int leftIndex = 0;
1052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                int rightIndex = 0;
1062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                for (;;) {
1072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    int leftSecondary;
1082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    do {
1092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        leftSecondary = ((int) left.getCE(leftIndex++)) >>> 16;
1102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    } while (leftSecondary == 0);
1112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    int rightSecondary;
1132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    do {
1142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        rightSecondary = ((int) right.getCE(rightIndex++)) >>> 16;
1152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    } while (rightSecondary == 0);
1162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    if (leftSecondary != rightSecondary) {
1182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        return (leftSecondary < rightSecondary) ? Collation.LESS : Collation.GREATER;
1192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    }
1202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    if (leftSecondary == Collation.NO_CE_WEIGHT16) {
1212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        break;
1222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    }
1232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }
1242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            } else {
1252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                // The backwards secondary level compares secondary weights backwards
1262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                // within segments separated by the merge separator (U+FFFE, weight 02).
1272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                int leftStart = 0;
1282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                int rightStart = 0;
1292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                for (;;) {
1302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    // Find the merge separator or the NO_CE terminator.
1312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    long p;
1322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    int leftLimit = leftStart;
1332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    while ((p = left.getCE(leftLimit) >>> 32) > Collation.MERGE_SEPARATOR_PRIMARY
1342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                            || p == 0) {
1352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        ++leftLimit;
1362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    }
1372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    int rightLimit = rightStart;
1382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    while ((p = right.getCE(rightLimit) >>> 32) > Collation.MERGE_SEPARATOR_PRIMARY
1392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                            || p == 0) {
1402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        ++rightLimit;
1412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    }
1422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    // Compare the segments.
1442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    int leftIndex = leftLimit;
1452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    int rightIndex = rightLimit;
1462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    for (;;) {
1472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        int leftSecondary = 0;
1482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        while (leftSecondary == 0 && leftIndex > leftStart) {
1492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                            leftSecondary = ((int) left.getCE(--leftIndex)) >>> 16;
1502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        }
1512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        int rightSecondary = 0;
1532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        while (rightSecondary == 0 && rightIndex > rightStart) {
1542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                            rightSecondary = ((int) right.getCE(--rightIndex)) >>> 16;
1552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        }
1562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        if (leftSecondary != rightSecondary) {
1582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                            return (leftSecondary < rightSecondary) ? Collation.LESS : Collation.GREATER;
1592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        }
1602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        if (leftSecondary == 0) {
1612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                            break;
1622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        }
1632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    }
1642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    // Did we reach the end of either string?
1662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    // Both strings have the same number of merge separators,
1672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    // or else there would have been a primary-level difference.
1682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    assert (left.getCE(leftLimit) == right.getCE(rightLimit));
1692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    if (p == Collation.NO_CE_PRIMARY) {
1702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        break;
1712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    }
1722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    // Skip both merge separators and continue.
1732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    leftStart = leftLimit + 1;
1742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    rightStart = rightLimit + 1;
1752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }
1762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
1772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
1782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if ((options & CollationSettings.CASE_LEVEL) != 0) {
1802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            int strength = CollationSettings.getStrength(options);
1812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            int leftIndex = 0;
1822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            int rightIndex = 0;
1832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            for (;;) {
1842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                int leftCase, leftLower32, rightCase;
1852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                if (strength == Collator.PRIMARY) {
1862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    // Primary+caseLevel: Ignore case level weights of primary ignorables.
1872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    // Otherwise we would get a-umlaut > a
1882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    // which is not desirable for accent-insensitive sorting.
1892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    // Check for (lower 32 bits) == 0 as well because variable CEs are stored
1902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    // with only primary weights.
1912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    long ce;
1922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    do {
1932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        ce = left.getCE(leftIndex++);
1942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        leftCase = (int) ce;
1952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    } while ((ce >>> 32) == 0 || leftCase == 0);
1962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    leftLower32 = leftCase;
1972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    leftCase &= 0xc000;
1982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    do {
2002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        ce = right.getCE(rightIndex++);
2012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        rightCase = (int) ce;
2022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    } while ((ce >>> 32) == 0 || rightCase == 0);
2032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    rightCase &= 0xc000;
2042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                } else {
2052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    // Secondary+caseLevel: By analogy with the above,
2062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    // ignore case level weights of secondary ignorables.
2072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    //
2082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    // Note: A tertiary CE has uppercase case bits (0.0.ut)
2092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    // to keep tertiary+caseFirst well-formed.
2102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    //
2112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    // Tertiary+caseLevel: Also ignore case level weights of secondary ignorables.
2122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    // Otherwise a tertiary CE's uppercase would be no greater than
2132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    // a primary/secondary CE's uppercase.
2142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    // (See UCA well-formedness condition 2.)
2152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    // We could construct a special case weight higher than uppercase,
2162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    // but it's simpler to always ignore case weights of secondary ignorables,
2172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    // turning 0.0.ut into 0.0.0.t.
2182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    // (See LDML Collation, Case Parameters.)
2192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    do {
2202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        leftCase = (int) left.getCE(leftIndex++);
2212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    } while ((leftCase & 0xffff0000) == 0);
2222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    leftLower32 = leftCase;
2232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    leftCase &= 0xc000;
2242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    do {
2262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        rightCase = (int) right.getCE(rightIndex++);
2272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    } while ((rightCase & 0xffff0000) == 0);
2282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    rightCase &= 0xc000;
2292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }
2302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                // No need to handle NO_CE and MERGE_SEPARATOR specially:
2322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                // There is one case weight for each previous-level weight,
2332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                // so level length differences were handled there.
2342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                if (leftCase != rightCase) {
2352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    if ((options & CollationSettings.UPPER_FIRST) == 0) {
2362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        return (leftCase < rightCase) ? Collation.LESS : Collation.GREATER;
2372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    } else {
2382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        return (leftCase < rightCase) ? Collation.GREATER : Collation.LESS;
2392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    }
2402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }
2412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                if ((leftLower32 >>> 16) == Collation.NO_CE_WEIGHT16) {
2422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    break;
2432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }
2442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
2452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
2462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if (CollationSettings.getStrength(options) <= Collator.SECONDARY) {
2472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return Collation.EQUAL;
2482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
2492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int tertiaryMask = CollationSettings.getTertiaryMask(options);
2512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int leftIndex = 0;
2532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int rightIndex = 0;
2542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int anyQuaternaries = 0;
2552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        for (;;) {
2562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            int leftLower32, leftTertiary;
2572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            do {
2582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                leftLower32 = (int) left.getCE(leftIndex++);
2592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                anyQuaternaries |= leftLower32;
2602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                assert ((leftLower32 & Collation.ONLY_TERTIARY_MASK) != 0 || (leftLower32 & 0xc0c0) == 0);
2612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                leftTertiary = leftLower32 & tertiaryMask;
2622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            } while (leftTertiary == 0);
2632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            int rightLower32, rightTertiary;
2652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            do {
2662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                rightLower32 = (int) right.getCE(rightIndex++);
2672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                anyQuaternaries |= rightLower32;
2682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                assert ((rightLower32 & Collation.ONLY_TERTIARY_MASK) != 0 || (rightLower32 & 0xc0c0) == 0);
2692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                rightTertiary = rightLower32 & tertiaryMask;
2702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            } while (rightTertiary == 0);
2712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if (leftTertiary != rightTertiary) {
2732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                if (CollationSettings.sortsTertiaryUpperCaseFirst(options)) {
2742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    // Pass through NO_CE and keep real tertiary weights larger than that.
2752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    // Do not change the artificial uppercase weight of a tertiary CE (0.0.ut),
2762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    // to keep tertiary CEs well-formed.
2772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    // Their case+tertiary weights must be greater than those of
2782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    // primary and secondary CEs.
2792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    if (leftTertiary > Collation.NO_CE_WEIGHT16) {
2802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        if ((leftLower32 & 0xffff0000) != 0) {
2812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                            leftTertiary ^= 0xc000;
2822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        } else {
2832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                            leftTertiary += 0x4000;
2842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        }
2852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    }
2862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    if (rightTertiary > Collation.NO_CE_WEIGHT16) {
2872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        if ((rightLower32 & 0xffff0000) != 0) {
2882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                            rightTertiary ^= 0xc000;
2892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        } else {
2902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                            rightTertiary += 0x4000;
2912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        }
2922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    }
2932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }
2942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                return (leftTertiary < rightTertiary) ? Collation.LESS : Collation.GREATER;
2952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
2962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if (leftTertiary == Collation.NO_CE_WEIGHT16) {
2972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                break;
2982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
2992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
3002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if (CollationSettings.getStrength(options) <= Collator.TERTIARY) {
3012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return Collation.EQUAL;
3022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
3032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
3042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if (!anyVariable && (anyQuaternaries & 0xc0) == 0) {
3052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            // If there are no "variable" CEs and no non-zero quaternary weights,
3062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            // then there are no quaternary differences.
3072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return Collation.EQUAL;
3082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
3092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
3102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        leftIndex = 0;
3112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        rightIndex = 0;
3122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        for (;;) {
3132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            long leftQuaternary;
3142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            do {
3152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                long ce = left.getCE(leftIndex++);
3162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                leftQuaternary = ce & 0xffff;
3172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                if (leftQuaternary <= Collation.NO_CE_WEIGHT16) {
3182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    // Variable primary or completely ignorable or NO_CE.
3192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    leftQuaternary = ce >>> 32;
3202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                } else {
3212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    // Regular CE, not tertiary ignorable.
3222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    // Preserve the quaternary weight in bits 7..6.
3232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    leftQuaternary |= 0xffffff3fL;
3242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }
3252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            } while (leftQuaternary == 0);
3262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
3272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            long rightQuaternary;
3282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            do {
3292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                long ce = right.getCE(rightIndex++);
3302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                rightQuaternary = ce & 0xffff;
3312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                if (rightQuaternary <= Collation.NO_CE_WEIGHT16) {
3322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    // Variable primary or completely ignorable or NO_CE.
3332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    rightQuaternary = ce >>> 32;
3342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                } else {
3352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    // Regular CE, not tertiary ignorable.
3362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    // Preserve the quaternary weight in bits 7..6.
3372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    rightQuaternary |= 0xffffff3fL;
3382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }
3392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            } while (rightQuaternary == 0);
3402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
3412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if (leftQuaternary != rightQuaternary) {
3422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                // Return the difference, with script reordering.
3432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                if (settings.hasReordering()) {
3442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    leftQuaternary = settings.reorder(leftQuaternary);
3452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    rightQuaternary = settings.reorder(rightQuaternary);
3462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }
3472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                return (leftQuaternary < rightQuaternary) ? Collation.LESS : Collation.GREATER;
3482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
3492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if (leftQuaternary == Collation.NO_CE_PRIMARY) {
3502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                break;
3512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
3522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
3532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return Collation.EQUAL;
3542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
3552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller}
356